diff --git a/scst/include/backport.h b/scst/include/backport.h index 63659596b..debb5bf7f 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -776,6 +776,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) 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/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 8d24696a2..44ceb48f8 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) */ diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index ea90e6898..274b32b38 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -2581,6 +2581,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)) @@ -2596,7 +2603,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))