All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: kernel-janitors@vger.kernel.org
Subject: re: libnvdimm: control (ioctl) messages for nvdimm_bus and nvdimm devices
Date: Tue, 23 Jun 2015 12:49:37 +0000	[thread overview]
Message-ID: <20150623124937.GA6019@mwanda> (raw)

Hello Dan Williams,

The patch 85af0c1db6d8: "libnvdimm: control (ioctl) messages for
nvdimm_bus and nvdimm devices" from Jun 8, 2015, leads to the
following static checker warning:

	drivers/nvdimm/bus.c:484 __nd_ioctl()
	warn: should we be adding 'in_size' of the min_t value?

drivers/nvdimm/bus.c
   466          /* process an input envelope */
   467          for (i = 0; i < desc->in_num; i++) {
   468                  u32 in_size, copy;
   469  
   470                  in_size = nd_cmd_in_size(nvdimm, cmd, desc, i, in_env);
   471                  if (in_size = UINT_MAX) {
   472                          dev_err(dev, "%s:%s unknown input size cmd: %s field: %d\n",
   473                                          __func__, dimm_name, cmd_name, i);
   474                          return -ENXIO;
   475                  }
   476                  if (!access_ok(VERIFY_READ, p + in_len, in_size))
   477                          return -EFAULT;
   478                  if (in_len < sizeof(in_env))
   479                          copy = min_t(u32, sizeof(in_env) - in_len, in_size);
   480                  else
   481                          copy = 0;
   482                  if (copy && copy_from_user(&in_env[in_len], p + in_len, copy))
   483                          return -EFAULT;
   484                  in_len += in_size;

The warning message is saying that probably this should be:

			in_len += copy;

I think this is true.  On most iterations an invalid "in_size" would be
caught perhaps except on the last iteration.  It means "in_len" is
something invalid when we use it below.

   485          }
   486  
   487          /* process an output envelope */
   488          for (i = 0; i < desc->out_num; i++) {
   489                  u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
   490                                  (u32 *) in_env, (u32 *) out_env);
   491                  u32 copy;
   492  
   493                  if (out_size = UINT_MAX) {
   494                          dev_dbg(dev, "%s:%s unknown output size cmd: %s field: %d\n",
   495                                          __func__, dimm_name, cmd_name, i);
   496                          return -EFAULT;
   497                  }
   498                  if (!access_ok(VERIFY_WRITE, p + in_len + out_len, out_size))

Most of the time an invalid "in_len" doesn't really matter.  Maybe it
could be used to trigger an integer overflow?

   499                          return -EFAULT;
   500                  if (out_len < sizeof(out_env))
   501                          copy = min_t(u32, sizeof(out_env) - out_len, out_size);
   502                  else
   503                          copy = 0;
   504                  if (copy && copy_from_user(&out_env[out_len],
   505                                          p + in_len + out_len, copy))
   506                          return -EFAULT;
   507                  out_len += out_size;
   508          }
   509  
   510          buf_len = out_len + in_len;


So "buflen" is something invalid.  Integer overflow as well?

   511          if (!access_ok(VERIFY_WRITE, p, sizeof(buf_len)))
                                                ^^^^^^^^^^^^^^^

This is shoud be:

		if (!access_ok(VERIFY_WRITE, p, buf_len))

These days Linus frowns on anyone using __copy_to/from_user unless they
have benchmark data to prove it matters so do we even need this
access_ok() check?

   512                  return -EFAULT;
   513  
   514          if (buf_len > ND_IOCTL_MAX_BUFLEN) {
   515                  dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__,
   516                                  dimm_name, cmd_name, buf_len,
   517                                  ND_IOCTL_MAX_BUFLEN);
   518                  return -EINVAL;
   519          }
   520  
   521          buf = vmalloc(buf_len);
   522          if (!buf)
   523                  return -ENOMEM;
   524  
   525          if (copy_from_user(buf, p, buf_len)) {
   526                  rc = -EFAULT;
   527                  goto out;
   528          }
   529  
   530          nvdimm_bus_lock(&nvdimm_bus->dev);
   531          rc = nd_cmd_clear_to_send(nvdimm, cmd);
   532          if (rc)
   533                  goto out_unlock;
   534  
   535          rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len);

This is the only place where two bugs might make a difference.  I didn't
follow it through.  Probably it is not exploitable, but it's worth
cleaning up.

   536          if (rc < 0)
   537                  goto out_unlock;
   538          if (copy_to_user(p, buf, buf_len))
   539                  rc = -EFAULT;
   540   out_unlock:
   541          nvdimm_bus_unlock(&nvdimm_bus->dev);
   542   out:
   543          vfree(buf);
   544          return rc;
   545  }

regards,
dan carpenter

             reply	other threads:[~2015-06-23 12:49 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-23 12:49 Dan Carpenter [this message]
2015-06-30 18:15 ` libnvdimm: control (ioctl) messages for nvdimm_bus and nvdimm devices Dan Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150623124937.GA6019@mwanda \
    --to=dan.carpenter@oracle.com \
    --cc=kernel-janitors@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.