From ca180efeeceeece2ba89eef5c3e87e3f641c9292 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 3 Nov 2018 17:02:38 +0000 Subject: [PATCH 1/3] 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) */ From 133b012f82596d792c59479b869b77850a8e18e5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 3 Nov 2018 17:03:41 +0000 Subject: [PATCH 2/3] scst: Introduce a backport of kmem_cache_create_usercopy() This patch does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7600 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/backport.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/scst/include/backport.h b/scst/include/backport.h index c9c381d6b..b5929aed0 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -774,6 +774,39 @@ static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) } #endif +/* + * See also commit 8eb8284b4129 ("usercopy: Prepare for usercopy + * whitelisting"). + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) +static inline struct kmem_cache *kmem_cache_create_usercopy(const char *name, + unsigned int size, unsigned int align, + unsigned long flags, + unsigned int useroffset, unsigned int usersize, + void (*ctor)(void *)) +{ + return kmem_cache_create(name, size, align, flags, ctor, NULL); +} +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) +static inline struct kmem_cache *kmem_cache_create_usercopy(const char *name, + unsigned int size, unsigned int align, + unsigned long flags, + unsigned int useroffset, unsigned int usersize, + void (*ctor)(void *)) +{ + return kmem_cache_create(name, size, align, flags, ctor); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) +#define KMEM_CACHE_USERCOPY(__struct, __flags, __field) \ + kmem_cache_create_usercopy(#__struct, \ + sizeof(struct __struct), \ + __alignof__(struct __struct), (__flags), \ + offsetof(struct __struct, __field), \ + sizeof_field(struct __struct, __field), NULL) +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) From 4ceb343966960c79b6b6ed29208df7e8b38cf28d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 3 Nov 2018 17:06:01 +0000 Subject: [PATCH 3/3] scst, scst_user: Add support for usercopy hardening Avoid that with CONFIG_HARDENED_USERCOPY enabled warnings appear about kernel memory exposure attempts when using scst_user. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7601 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_user.c | 4 ++-- scst/src/scst_main.c | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index d213c691a..911796c3a 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -4212,8 +4212,8 @@ static int __init init_scst_user(void) goto out; } - user_cmd_cachep = KMEM_CACHE(scst_user_cmd, - SCST_SLAB_FLAGS|SLAB_HWCACHE_ALIGN); + user_cmd_cachep = KMEM_CACHE_USERCOPY(scst_user_cmd, + SCST_SLAB_FLAGS | SLAB_HWCACHE_ALIGN, user_cmd); if (user_cmd_cachep == NULL) { res = -ENOMEM; goto out_dev_cache; diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 8d3183a65..7660e288a 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -2586,6 +2586,13 @@ static int __init init_scst(void) sizeof(struct s)); \ (p); \ }) +#define INIT_CACHEP_ALIGN_USERCOPY(p, s, f) ({ \ + (p) = KMEM_CACHE_USERCOPY(s, SCST_SLAB_FLAGS | \ + SLAB_HWCACHE_ALIGN, f); \ + TRACE_MEM("Slab create: %s at %p size %zd", #s, (p), \ + sizeof(struct s)); \ + (p); \ + }) res = -ENOMEM; if (!INIT_CACHEP(scst_mgmt_cachep, scst_mgmt_cmd)) @@ -2601,7 +2608,7 @@ static int __init init_scst(void) } if (!INIT_CACHEP(scst_aen_cachep, scst_aen)) /* read-mostly */ goto out_destroy_sense_cache; - if (!INIT_CACHEP_ALIGN(scst_cmd_cachep, scst_cmd)) + if (!INIT_CACHEP_ALIGN_USERCOPY(scst_cmd_cachep, scst_cmd, cdb)) goto out_destroy_aen_cache; /* Big enough with read-mostly head and tail */ if (!INIT_CACHEP(scst_sess_cachep, scst_session))