From ca180efeeceeece2ba89eef5c3e87e3f641c9292 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 3 Nov 2018 17:02:38 +0000 Subject: [PATCH] cst_vdisk: Avoid that vdisk_usn_vpd() can trigger a buffer overflow Additionally, this patch avoids that the following compiler warning is reported on Fedora 29: In function 'strncpy', inlined from 'vdisk_usn_vpd.isra.24' at /home/bart/software/scst.git/scst/src/dev_handlers/scst_vdisk.c:3866:3: ./include/linux/string.h:246:9: warning: '__builtin_strncpy' output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation] return __builtin_strncpy(p, q, size); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/bart/software/scst.git/scst/src/dev_handlers/scst_vdisk.c: In function 'vdisk_usn_vpd.isra.24': ./include/linux/string.h:267:10: note: length computed here return __builtin_strlen(p); ^~~~~~~~~~~~~~~~~~~ git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7599 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 5ca48a612..eaa3236a3 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -3849,27 +3849,20 @@ static int vdisk_sup_vpd(uint8_t *buf, struct scst_cmd *cmd, static int vdisk_usn_vpd(uint8_t *buf, struct scst_cmd *cmd, struct scst_vdisk_dev *virt_dev) { + uint16_t usn_len, max_len = INQ_BUF_SZ - 4; + buf[1] = 0x80; if (cmd->tgtt->get_serial) { - buf[3] = cmd->tgtt->get_serial(cmd->tgt_dev, &buf[4], - INQ_BUF_SZ - 4); + usn_len = cmd->tgtt->get_serial(cmd->tgt_dev, &buf[4], max_len); } else { - int usn_len; - read_lock(&vdisk_serial_rwlock); usn_len = strlen(virt_dev->usn); - buf[3] = usn_len; -#if __GNUC__ -0 >= 8 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" -#endif - strncpy(&buf[4], virt_dev->usn, usn_len); -#if __GNUC__ -0 >= 8 -#pragma GCC diagnostic pop -#endif + WARN_ON_ONCE(usn_len > max_len); + memcpy(&buf[4], virt_dev->usn, usn_len); read_unlock(&vdisk_serial_rwlock); } - return buf[3] + 4; + put_unaligned_be16(usn_len, &buf[2]); + return usn_len + 4; } /* Device Identification VPD page (83h) */