All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
To: Dan Williams
	<dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	dave.jiang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org
Subject: [bug report] acpi/nfit: Add support for Intel DSM 1.8 commands
Date: Thu, 2 May 2019 13:07:28 +0300	[thread overview]
Message-ID: <20190502100728.GA10650@mwanda> (raw)

Hello Dan Williams,

Commit 11189c1089da ("acpi/nfit: Fix command-supported detection") from
Jan 19, 2019 leads to the following static checker warning:

    drivers/acpi/nfit/core.c:503 acpi_nfit_ctl()
    error: passing untrusted data 'func' to 'variable_test_bit()'

Related but not critical:

    drivers/acpi/nfit/core.c:3510 acpi_nfit_clear_to_send()
    error: undefined (user controlled) shift '1 << func'

drivers/nvdimm/bus.c
  1062          buf = vmalloc(buf_len);
  1063          if (!buf)
  1064                  return -ENOMEM;
  1065  
  1066          if (copy_from_user(buf, p, buf_len)) {
  1067                  rc = -EFAULT;
  1068                  goto out;
  1069          }
  1070  
  1071          nvdimm_bus_lock(&nvdimm_bus->dev);
  1072          rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
  1073          if (rc)
  1074                  goto out_unlock;
  1075  
  1076          rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
  1077          if (rc < 0)
  1078                  goto out_unlock;

This is __nd_ioctl().  We get "buf" from the user and then pass it to
acpi_nfit_clear_to_send() and then acpi_nfit_ctl().

drivers/acpi/nfit/core.c
   446  int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
   447                  unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
   448  {
   449          struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
   450          struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
   451          union acpi_object in_obj, in_buf, *out_obj;
   452          const struct nd_cmd_desc *desc = NULL;
   453          struct device *dev = acpi_desc->dev;
   454          struct nd_cmd_pkg *call_pkg = NULL;
   455          const char *cmd_name, *dimm_name;
   456          unsigned long cmd_mask, dsm_mask;
   457          u32 offset, fw_status = 0;
   458          acpi_handle handle;
   459          const guid_t *guid;
   460          int func, rc, i;
   461  
   462          if (cmd_rc)
   463                  *cmd_rc = -EINVAL;
   464  
   465          if (cmd == ND_CMD_CALL)
   466                  call_pkg = buf;
                        ^^^^^^^^^^^^^^

   467          func = cmd_to_func(nfit_mem, cmd, call_pkg);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

We set func = call_pkg->nd_command (0-s32max).


   468          if (func < 0)
   469                  return func;
   470  
   471          if (nvdimm) {
   472                  struct acpi_device *adev = nfit_mem->adev;
   473  
   474                  if (!adev)
   475                          return -ENOTTY;
   476  
   477                  dimm_name = nvdimm_name(nvdimm);
   478                  cmd_name = nvdimm_cmd_name(cmd);
   479                  cmd_mask = nvdimm_cmd_mask(nvdimm);
   480                  dsm_mask = nfit_mem->dsm_mask;
   481                  desc = nd_cmd_dimm_desc(cmd);
   482                  guid = to_nfit_uuid(nfit_mem->family);
   483                  handle = adev->handle;
   484          } else {
   485                  struct acpi_device *adev = to_acpi_dev(acpi_desc);
   486  
   487                  cmd_name = nvdimm_bus_cmd_name(cmd);
   488                  cmd_mask = nd_desc->cmd_mask;
   489                  dsm_mask = nd_desc->bus_dsm_mask;
   490                  desc = nd_cmd_bus_desc(cmd);
   491                  guid = to_nfit_uuid(NFIT_DEV_BUS);
   492                  handle = adev->handle;
   493                  dimm_name = "bus";
   494          }
   495  
   496          if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
   497                  return -ENOTTY;
   498  
   499          /*
   500           * Check for a valid command.  For ND_CMD_CALL, we also have to
   501           * make sure that the DSM function is supported.
   502           */
   503          if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
                                                    ^^^^

"func" might be beyond the end of the bitmap so it could be an out of
bounds read.  We do bounds check it to <= 31 in nfit_dsm_revid() but I
couldn't see any range checking in acpi_evaluate_dsm().

   504                  return -ENOTTY;
   505          else if (!test_bit(cmd, &cmd_mask))
   506                  return -ENOTTY;
   507  
   508          in_obj.type = ACPI_TYPE_PACKAGE;
   509          in_obj.package.count = 1;
   510          in_obj.package.elements = &in_buf;
   511          in_buf.type = ACPI_TYPE_BUFFER;
   512          in_buf.buffer.pointer = buf;
   513          in_buf.buffer.length = 0;
   514  
   515          /* libnvdimm has already validated the input envelope */
   516          for (i = 0; i < desc->in_num; i++)
   517                  in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
   518                                  i, buf);
   519  
   520          if (call_pkg) {
   521                  /* skip over package wrapper */
   522                  in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
   523                  in_buf.buffer.length = call_pkg->nd_size_in;
   524          }
   525  
   526          dev_dbg(dev, "%s cmd: %d: func: %d input length: %d\n",
   527                  dimm_name, cmd, func, in_buf.buffer.length);
   528          if (payload_dumpable(nvdimm, func))

[ snip ]

  3500  /* prevent security commands from being issued via ioctl */
  3501  static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
  3502                  struct nvdimm *nvdimm, unsigned int cmd, void *buf)
  3503  {
  3504          struct nd_cmd_pkg *call_pkg = buf;
  3505          unsigned int func;
  3506  
  3507          if (nvdimm && cmd == ND_CMD_CALL &&
  3508                          call_pkg->nd_family == NVDIMM_FAMILY_INTEL) {
  3509                  func = call_pkg->nd_command;
  3510                  if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
                             ^^^^^^^^^
This is undefined and it would be nice to fix, but not important for
run time.

  3511                          return -EOPNOTSUPP;
  3512          }
  3513  
  3514          return __acpi_nfit_clear_to_send(nd_desc, nvdimm, cmd);
  3515  }

regards,
dan carpenter

WARNING: multiple messages have this Message-ID (diff)
From: Dan Carpenter <dan.carpenter@oracle.com>
To: Dan Williams <dan.j.williams@intel.com>, dave.jiang@intel.com
Cc: linux-nvdimm@lists.01.org, linux-acpi@vger.kernel.org
Subject: [bug report] acpi/nfit: Add support for Intel DSM 1.8 commands
Date: Thu, 2 May 2019 13:07:28 +0300	[thread overview]
Message-ID: <20190502100728.GA10650@mwanda> (raw)
Message-ID: <20190502100728.P4KKW8D94oGg9NibykW9pM3vQgTh1-Nj663RK0hSC3g@z> (raw)

Hello Dan Williams,

Commit 11189c1089da ("acpi/nfit: Fix command-supported detection") from
Jan 19, 2019 leads to the following static checker warning:

    drivers/acpi/nfit/core.c:503 acpi_nfit_ctl()
    error: passing untrusted data 'func' to 'variable_test_bit()'

Related but not critical:

    drivers/acpi/nfit/core.c:3510 acpi_nfit_clear_to_send()
    error: undefined (user controlled) shift '1 << func'

drivers/nvdimm/bus.c
  1062          buf = vmalloc(buf_len);
  1063          if (!buf)
  1064                  return -ENOMEM;
  1065  
  1066          if (copy_from_user(buf, p, buf_len)) {
  1067                  rc = -EFAULT;
  1068                  goto out;
  1069          }
  1070  
  1071          nvdimm_bus_lock(&nvdimm_bus->dev);
  1072          rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
  1073          if (rc)
  1074                  goto out_unlock;
  1075  
  1076          rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
  1077          if (rc < 0)
  1078                  goto out_unlock;

This is __nd_ioctl().  We get "buf" from the user and then pass it to
acpi_nfit_clear_to_send() and then acpi_nfit_ctl().

drivers/acpi/nfit/core.c
   446  int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
   447                  unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
   448  {
   449          struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
   450          struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
   451          union acpi_object in_obj, in_buf, *out_obj;
   452          const struct nd_cmd_desc *desc = NULL;
   453          struct device *dev = acpi_desc->dev;
   454          struct nd_cmd_pkg *call_pkg = NULL;
   455          const char *cmd_name, *dimm_name;
   456          unsigned long cmd_mask, dsm_mask;
   457          u32 offset, fw_status = 0;
   458          acpi_handle handle;
   459          const guid_t *guid;
   460          int func, rc, i;
   461  
   462          if (cmd_rc)
   463                  *cmd_rc = -EINVAL;
   464  
   465          if (cmd == ND_CMD_CALL)
   466                  call_pkg = buf;
                        ^^^^^^^^^^^^^^

   467          func = cmd_to_func(nfit_mem, cmd, call_pkg);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

We set func = call_pkg->nd_command (0-s32max).


   468          if (func < 0)
   469                  return func;
   470  
   471          if (nvdimm) {
   472                  struct acpi_device *adev = nfit_mem->adev;
   473  
   474                  if (!adev)
   475                          return -ENOTTY;
   476  
   477                  dimm_name = nvdimm_name(nvdimm);
   478                  cmd_name = nvdimm_cmd_name(cmd);
   479                  cmd_mask = nvdimm_cmd_mask(nvdimm);
   480                  dsm_mask = nfit_mem->dsm_mask;
   481                  desc = nd_cmd_dimm_desc(cmd);
   482                  guid = to_nfit_uuid(nfit_mem->family);
   483                  handle = adev->handle;
   484          } else {
   485                  struct acpi_device *adev = to_acpi_dev(acpi_desc);
   486  
   487                  cmd_name = nvdimm_bus_cmd_name(cmd);
   488                  cmd_mask = nd_desc->cmd_mask;
   489                  dsm_mask = nd_desc->bus_dsm_mask;
   490                  desc = nd_cmd_bus_desc(cmd);
   491                  guid = to_nfit_uuid(NFIT_DEV_BUS);
   492                  handle = adev->handle;
   493                  dimm_name = "bus";
   494          }
   495  
   496          if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
   497                  return -ENOTTY;
   498  
   499          /*
   500           * Check for a valid command.  For ND_CMD_CALL, we also have to
   501           * make sure that the DSM function is supported.
   502           */
   503          if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
                                                    ^^^^

"func" might be beyond the end of the bitmap so it could be an out of
bounds read.  We do bounds check it to <= 31 in nfit_dsm_revid() but I
couldn't see any range checking in acpi_evaluate_dsm().

   504                  return -ENOTTY;
   505          else if (!test_bit(cmd, &cmd_mask))
   506                  return -ENOTTY;
   507  
   508          in_obj.type = ACPI_TYPE_PACKAGE;
   509          in_obj.package.count = 1;
   510          in_obj.package.elements = &in_buf;
   511          in_buf.type = ACPI_TYPE_BUFFER;
   512          in_buf.buffer.pointer = buf;
   513          in_buf.buffer.length = 0;
   514  
   515          /* libnvdimm has already validated the input envelope */
   516          for (i = 0; i < desc->in_num; i++)
   517                  in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
   518                                  i, buf);
   519  
   520          if (call_pkg) {
   521                  /* skip over package wrapper */
   522                  in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
   523                  in_buf.buffer.length = call_pkg->nd_size_in;
   524          }
   525  
   526          dev_dbg(dev, "%s cmd: %d: func: %d input length: %d\n",
   527                  dimm_name, cmd, func, in_buf.buffer.length);
   528          if (payload_dumpable(nvdimm, func))

[ snip ]

  3500  /* prevent security commands from being issued via ioctl */
  3501  static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
  3502                  struct nvdimm *nvdimm, unsigned int cmd, void *buf)
  3503  {
  3504          struct nd_cmd_pkg *call_pkg = buf;
  3505          unsigned int func;
  3506  
  3507          if (nvdimm && cmd == ND_CMD_CALL &&
  3508                          call_pkg->nd_family == NVDIMM_FAMILY_INTEL) {
  3509                  func = call_pkg->nd_command;
  3510                  if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
                             ^^^^^^^^^
This is undefined and it would be nice to fix, but not important for
run time.

  3511                          return -EOPNOTSUPP;
  3512          }
  3513  
  3514          return __acpi_nfit_clear_to_send(nd_desc, nvdimm, cmd);
  3515  }

regards,
dan carpenter

WARNING: multiple messages have this Message-ID (diff)
From: Dan Carpenter <dan.carpenter@oracle.com>
To: Dan Williams <dan.j.williams@intel.com>, dave.jiang@intel.com
Cc: linux-acpi@vger.kernel.org, linux-nvdimm@lists.01.org
Subject: [bug report] acpi/nfit: Add support for Intel DSM 1.8 commands
Date: Thu, 2 May 2019 13:07:28 +0300	[thread overview]
Message-ID: <20190502100728.GA10650@mwanda> (raw)

Hello Dan Williams,

Commit 11189c1089da ("acpi/nfit: Fix command-supported detection") from
Jan 19, 2019 leads to the following static checker warning:

    drivers/acpi/nfit/core.c:503 acpi_nfit_ctl()
    error: passing untrusted data 'func' to 'variable_test_bit()'

Related but not critical:

    drivers/acpi/nfit/core.c:3510 acpi_nfit_clear_to_send()
    error: undefined (user controlled) shift '1 << func'

drivers/nvdimm/bus.c
  1062          buf = vmalloc(buf_len);
  1063          if (!buf)
  1064                  return -ENOMEM;
  1065  
  1066          if (copy_from_user(buf, p, buf_len)) {
  1067                  rc = -EFAULT;
  1068                  goto out;
  1069          }
  1070  
  1071          nvdimm_bus_lock(&nvdimm_bus->dev);
  1072          rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf);
  1073          if (rc)
  1074                  goto out_unlock;
  1075  
  1076          rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, &cmd_rc);
  1077          if (rc < 0)
  1078                  goto out_unlock;

This is __nd_ioctl().  We get "buf" from the user and then pass it to
acpi_nfit_clear_to_send() and then acpi_nfit_ctl().

drivers/acpi/nfit/core.c
   446  int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
   447                  unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
   448  {
   449          struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
   450          struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
   451          union acpi_object in_obj, in_buf, *out_obj;
   452          const struct nd_cmd_desc *desc = NULL;
   453          struct device *dev = acpi_desc->dev;
   454          struct nd_cmd_pkg *call_pkg = NULL;
   455          const char *cmd_name, *dimm_name;
   456          unsigned long cmd_mask, dsm_mask;
   457          u32 offset, fw_status = 0;
   458          acpi_handle handle;
   459          const guid_t *guid;
   460          int func, rc, i;
   461  
   462          if (cmd_rc)
   463                  *cmd_rc = -EINVAL;
   464  
   465          if (cmd == ND_CMD_CALL)
   466                  call_pkg = buf;
                        ^^^^^^^^^^^^^^

   467          func = cmd_to_func(nfit_mem, cmd, call_pkg);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

We set func = call_pkg->nd_command (0-s32max).


   468          if (func < 0)
   469                  return func;
   470  
   471          if (nvdimm) {
   472                  struct acpi_device *adev = nfit_mem->adev;
   473  
   474                  if (!adev)
   475                          return -ENOTTY;
   476  
   477                  dimm_name = nvdimm_name(nvdimm);
   478                  cmd_name = nvdimm_cmd_name(cmd);
   479                  cmd_mask = nvdimm_cmd_mask(nvdimm);
   480                  dsm_mask = nfit_mem->dsm_mask;
   481                  desc = nd_cmd_dimm_desc(cmd);
   482                  guid = to_nfit_uuid(nfit_mem->family);
   483                  handle = adev->handle;
   484          } else {
   485                  struct acpi_device *adev = to_acpi_dev(acpi_desc);
   486  
   487                  cmd_name = nvdimm_bus_cmd_name(cmd);
   488                  cmd_mask = nd_desc->cmd_mask;
   489                  dsm_mask = nd_desc->bus_dsm_mask;
   490                  desc = nd_cmd_bus_desc(cmd);
   491                  guid = to_nfit_uuid(NFIT_DEV_BUS);
   492                  handle = adev->handle;
   493                  dimm_name = "bus";
   494          }
   495  
   496          if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
   497                  return -ENOTTY;
   498  
   499          /*
   500           * Check for a valid command.  For ND_CMD_CALL, we also have to
   501           * make sure that the DSM function is supported.
   502           */
   503          if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
                                                    ^^^^

"func" might be beyond the end of the bitmap so it could be an out of
bounds read.  We do bounds check it to <= 31 in nfit_dsm_revid() but I
couldn't see any range checking in acpi_evaluate_dsm().

   504                  return -ENOTTY;
   505          else if (!test_bit(cmd, &cmd_mask))
   506                  return -ENOTTY;
   507  
   508          in_obj.type = ACPI_TYPE_PACKAGE;
   509          in_obj.package.count = 1;
   510          in_obj.package.elements = &in_buf;
   511          in_buf.type = ACPI_TYPE_BUFFER;
   512          in_buf.buffer.pointer = buf;
   513          in_buf.buffer.length = 0;
   514  
   515          /* libnvdimm has already validated the input envelope */
   516          for (i = 0; i < desc->in_num; i++)
   517                  in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
   518                                  i, buf);
   519  
   520          if (call_pkg) {
   521                  /* skip over package wrapper */
   522                  in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
   523                  in_buf.buffer.length = call_pkg->nd_size_in;
   524          }
   525  
   526          dev_dbg(dev, "%s cmd: %d: func: %d input length: %d\n",
   527                  dimm_name, cmd, func, in_buf.buffer.length);
   528          if (payload_dumpable(nvdimm, func))

[ snip ]

  3500  /* prevent security commands from being issued via ioctl */
  3501  static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
  3502                  struct nvdimm *nvdimm, unsigned int cmd, void *buf)
  3503  {
  3504          struct nd_cmd_pkg *call_pkg = buf;
  3505          unsigned int func;
  3506  
  3507          if (nvdimm && cmd == ND_CMD_CALL &&
  3508                          call_pkg->nd_family == NVDIMM_FAMILY_INTEL) {
  3509                  func = call_pkg->nd_command;
  3510                  if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
                             ^^^^^^^^^
This is undefined and it would be nice to fix, but not important for
run time.

  3511                          return -EOPNOTSUPP;
  3512          }
  3513  
  3514          return __acpi_nfit_clear_to_send(nd_desc, nvdimm, cmd);
  3515  }

regards,
dan carpenter
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

             reply	other threads:[~2019-05-02 10:07 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-02 10:07 Dan Carpenter [this message]
2019-05-02 10:07 ` [bug report] acpi/nfit: Add support for Intel DSM 1.8 commands Dan Carpenter
2019-05-02 10:07 ` Dan Carpenter

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=20190502100728.GA10650@mwanda \
    --to=dan.carpenter-qhclzuegtsvqt0dzr+alfa@public.gmane.org \
    --cc=dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=dave.jiang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.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.