From: Heitor Ricardo Alves de Siqueira Date: Wed, 13 Jul 2016 13:27:36 +0000 (-0300) Subject: Fix read/write memory corruption issues X-Git-Tag: v0.9~17^2~2^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=bf5eb4e867f9ad7ba2291bdfff2d41872bed7c2a;p=users%2Fsagi%2Fnvme-cli.git Fix read/write memory corruption issues When issuing a read to the device, if we pass a data size smaller than the current sector size, the ioctl() will overflow the data buffer. This will also happen when reading more than one block from the device, if the buffer does not have enough bytes to store the result. This patch adds a simple check using the requested block count to correctly allocate a buffer of minimum size. Signed-off-by: Heitor Ricardo Alves de Siqueira --- diff --git a/nvme.c b/nvme.c index 3e1b3d60..cf15bbf5 100644 --- a/nvme.c +++ b/nvme.c @@ -2113,6 +2113,8 @@ static int submit_io(int opcode, char *command, const char *desc, int flags = opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT; int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; __u16 control = 0; + int phys_sector_size = 0; + long long buffer_size = 0; const char *start_block = "64-bit addr of first block to access"; const char *block_count = "number of blocks (zeroes based) on device to access"; @@ -2211,7 +2213,18 @@ static int submit_io(int opcode, char *command, const char *desc, return EINVAL; } - if (posix_memalign(&buffer, getpagesize(), cfg.data_size)) + if (ioctl(fd, BLKPBSZGET, &phys_sector_size) < 0) + return errno; + + buffer_size = (cfg.block_count + 1) * phys_sector_size; + if (cfg.data_size < buffer_size) { + fprintf(stderr, "Rounding data size to fit block count (%lld bytes)\n", + buffer_size); + } else { + buffer_size = cfg.data_size; + } + + if (posix_memalign(&buffer, getpagesize(), buffer_size)) return ENOMEM; memset(buffer, 0, cfg.data_size);