Skip to content

Commit 04ffde1

Browse files
committed
uaccess: Add minimum bounds check on kernel buffer size
While there is logic about the difference between ksize and usize, copy_struct_from_user() didn't check the size of the destination buffer (when it was known) against ksize. Add this check so there is an upper bounds check on the possible memset() call, otherwise lower bounds checks made by callers will trigger bounds warnings under -Warray-bounds. Seen under GCC 13: In function 'copy_struct_from_user', inlined from 'iommufd_fops_ioctl' at ../drivers/iommu/iommufd/main.c:333:8: ../include/linux/fortify-string.h:59:33: warning: '__builtin_memset' offset [57, 4294967294] is out of the bounds [0, 56] of object 'buf' with type 'union ucmd_buffer' [-Warray-bounds=] 59 | #define __underlying_memset __builtin_memset | ^ ../include/linux/fortify-string.h:453:9: note: in expansion of macro '__underlying_memset' 453 | __underlying_memset(p, c, __fortify_size); \ | ^~~~~~~~~~~~~~~~~~~ ../include/linux/fortify-string.h:461:25: note: in expansion of macro '__fortify_memset_chk' 461 | #define memset(p, c, s) __fortify_memset_chk(p, c, s, \ | ^~~~~~~~~~~~~~~~~~~~ ../include/linux/uaccess.h:334:17: note: in expansion of macro 'memset' 334 | memset(dst + size, 0, rest); | ^~~~~~ ../drivers/iommu/iommufd/main.c: In function 'iommufd_fops_ioctl': ../drivers/iommu/iommufd/main.c:311:27: note: 'buf' declared here 311 | union ucmd_buffer buf; | ^~~ Cc: Christian Brauner <[email protected]> Cc: Rasmus Villemoes <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Dinh Nguyen <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Geert Uytterhoeven <[email protected]> Cc: Alexander Potapenko <[email protected]> Acked-by: Aleksa Sarai <[email protected]> Signed-off-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/lkml/[email protected]/
1 parent 25b8400 commit 04ffde1

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

include/linux/uaccess.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,10 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
329329
size_t size = min(ksize, usize);
330330
size_t rest = max(ksize, usize) - size;
331331

332+
/* Double check if ksize is larger than a known object size. */
333+
if (WARN_ON_ONCE(ksize > __builtin_object_size(dst, 1)))
334+
return -E2BIG;
335+
332336
/* Deal with trailing bytes. */
333337
if (usize < ksize) {
334338
memset(dst + size, 0, rest);

0 commit comments

Comments
 (0)