Skip to content

Commit 29c969c

Browse files
djbwgregkh
authored andcommitted
libnvdimm: fix integer overflow static analysis warning
commit 58738c4 upstream. Dan reports: The patch 62232e4: "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:1018 __nd_ioctl() warn: integer overflows 'buf_len' From a casual review, this seems like it might be a real bug. On the first iteration we load some data into in_env[]. On the second iteration we read a use controlled "in_size" from nd_cmd_in_size(). It can go up to UINT_MAX - 1. A high number means we will fill the whole in_env[] buffer. But we potentially keep looping and adding more to in_len so now it can be any value. It simple enough to change, but it feels weird that we keep looping even though in_env is totally full. Shouldn't we just return an error if we don't have space for desc->in_num. We keep looping because the size of the total input is allowed to be bigger than the 'envelope' which is a subset of the payload that tells us how much data to expect. For safety explicitly check that buf_len does not overflow which is what the checker flagged. Cc: <stable@vger.kernel.org> Fixes: 62232e4: "libnvdimm: control (ioctl) messages for nvdimm_bus..." Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f06c2c6 commit 29c969c

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

drivers/nvdimm/bus.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -812,16 +812,17 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
812812
int read_only, unsigned int ioctl_cmd, unsigned long arg)
813813
{
814814
struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
815-
size_t buf_len = 0, in_len = 0, out_len = 0;
816815
static char out_env[ND_CMD_MAX_ENVELOPE];
817816
static char in_env[ND_CMD_MAX_ENVELOPE];
818817
const struct nd_cmd_desc *desc = NULL;
819818
unsigned int cmd = _IOC_NR(ioctl_cmd);
820819
void __user *p = (void __user *) arg;
821820
struct device *dev = &nvdimm_bus->dev;
822-
struct nd_cmd_pkg pkg;
823821
const char *cmd_name, *dimm_name;
822+
u32 in_len = 0, out_len = 0;
824823
unsigned long cmd_mask;
824+
struct nd_cmd_pkg pkg;
825+
u64 buf_len = 0;
825826
void *buf;
826827
int rc, i;
827828

@@ -882,7 +883,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
882883
}
883884

884885
if (cmd == ND_CMD_CALL) {
885-
dev_dbg(dev, "%s:%s, idx: %llu, in: %zu, out: %zu, len %zu\n",
886+
dev_dbg(dev, "%s:%s, idx: %llu, in: %u, out: %u, len %llu\n",
886887
__func__, dimm_name, pkg.nd_command,
887888
in_len, out_len, buf_len);
888889

@@ -912,9 +913,9 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
912913
out_len += out_size;
913914
}
914915

915-
buf_len = out_len + in_len;
916+
buf_len = (u64) out_len + (u64) in_len;
916917
if (buf_len > ND_IOCTL_MAX_BUFLEN) {
917-
dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__,
918+
dev_dbg(dev, "%s:%s cmd: %s buf_len: %llu > %d\n", __func__,
918919
dimm_name, cmd_name, buf_len,
919920
ND_IOCTL_MAX_BUFLEN);
920921
return -EINVAL;

0 commit comments

Comments
 (0)