]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
Fix read/write memory corruption issues
authorHeitor Ricardo Alves de Siqueira <halves@linux.vnet.ibm.com>
Wed, 13 Jul 2016 13:27:36 +0000 (10:27 -0300)
committerHeitor Ricardo Alves de Siqueira <halves@linux.vnet.ibm.com>
Wed, 13 Jul 2016 13:59:24 +0000 (10:59 -0300)
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 <halves@linux.vnet.ibm.com>
nvme.c

diff --git a/nvme.c b/nvme.c
index 3e1b3d60e663ea6360fdd73e5c7e3d374b8f07c3..cf15bbf596d531198d8abcb5d9799af992f43e31 100644 (file)
--- 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);