^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Kernel module for testing copy_to/from_user infrastructure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2013 Google Inc. All Rights Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Kees Cook <keescook@chromium.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Several 32-bit architectures support 64-bit {get,put}_user() calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * As there doesn't appear to be anything that can safely determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * their capability at compile-time, we just have to opt-out certain archs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #if BITS_PER_LONG == 64 || (!(defined(CONFIG_ARM) && !defined(MMU)) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) !defined(CONFIG_M68K) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) !defined(CONFIG_MICROBLAZE) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) !defined(CONFIG_NIOS2) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) !defined(CONFIG_PPC32) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) !defined(CONFIG_SUPERH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) # define TEST_U64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define test(condition, msg, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int cond = (condition); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (cond) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pr_warn("[%d] " msg "\n", __LINE__, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) cond; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static bool is_zeroed(void *from, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return memchr_inv(from, 0x0, size) == NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int test_check_nonzero_user(char *kmem, char __user *umem, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) size_t start, end, i, zero_start, zero_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (test(size < 2 * PAGE_SIZE, "buffer too small"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * We want to cross a page boundary to exercise the code more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * effectively. We also don't want to make the size we scan too large,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * otherwise the test can take a long time and cause soft lockups. So
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * scan a 1024 byte region across the page boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) size = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) start = PAGE_SIZE - (size / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) kmem += start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) umem += start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) zero_start = size / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) zero_end = size - zero_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * We conduct a series of check_nonzero_user() tests on a block of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * memory with the following byte-pattern (trying every possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * [start,end] pair):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * [ 00 ff 00 ff ... 00 00 00 00 ... ff 00 ff 00 ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * And we verify that check_nonzero_user() acts identically to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * memchr_inv().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) memset(kmem, 0x0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) for (i = 1; i < zero_start; i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) kmem[i] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) for (i = zero_end; i < size; i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) kmem[i] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ret |= test(copy_to_user(umem, kmem, size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "legitimate copy_to_user failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) for (start = 0; start <= size; start++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) for (end = start; end <= size; end++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) size_t len = end - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int retval = check_zeroed_user(umem + start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int expected = is_zeroed(kmem + start, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret |= test(retval != expected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) "check_nonzero_user(=%d) != memchr_inv(=%d) mismatch (start=%zu, end=%zu)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) retval, expected, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int test_copy_struct_from_user(char *kmem, char __user *umem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) char *umem_src = NULL, *expected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) size_t ksize, usize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) umem_src = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ret = test(umem_src == NULL, "kmalloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) expected = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = test(expected == NULL, "kmalloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Fill umem with a fixed byte pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) memset(umem_src, 0x3e, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret |= test(copy_to_user(umem, umem_src, size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "legitimate copy_to_user failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Check basic case -- (usize == ksize). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ksize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) usize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) memcpy(expected, umem_src, ksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) memset(kmem, 0x0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret |= test(copy_struct_from_user(kmem, ksize, umem, usize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) "copy_struct_from_user(usize == ksize) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ret |= test(memcmp(kmem, expected, ksize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) "copy_struct_from_user(usize == ksize) gives unexpected copy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Old userspace case -- (usize < ksize). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ksize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) usize = size / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) memcpy(expected, umem_src, usize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) memset(expected + usize, 0x0, ksize - usize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) memset(kmem, 0x0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret |= test(copy_struct_from_user(kmem, ksize, umem, usize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "copy_struct_from_user(usize < ksize) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret |= test(memcmp(kmem, expected, ksize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "copy_struct_from_user(usize < ksize) gives unexpected copy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* New userspace (-E2BIG) case -- (usize > ksize). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ksize = size / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) usize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) memset(kmem, 0x0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ret |= test(copy_struct_from_user(kmem, ksize, umem, usize) != -E2BIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) "copy_struct_from_user(usize > ksize) didn't give E2BIG");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* New userspace (success) case -- (usize > ksize). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ksize = size / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) usize = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) memcpy(expected, umem_src, ksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ret |= test(clear_user(umem + ksize, usize - ksize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) "legitimate clear_user failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) memset(kmem, 0x0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ret |= test(copy_struct_from_user(kmem, ksize, umem, usize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "copy_struct_from_user(usize > ksize) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret |= test(memcmp(kmem, expected, ksize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) "copy_struct_from_user(usize > ksize) gives unexpected copy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) kfree(expected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) kfree(umem_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static int __init test_user_copy_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) char *kmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) char __user *usermem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) char *bad_usermem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned long user_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u8 val_u8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u16 val_u16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u32 val_u32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #ifdef TEST_U64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u64 val_u64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) kmem = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!kmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) user_addr = vm_mmap(NULL, 0, PAGE_SIZE * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) PROT_READ | PROT_WRITE | PROT_EXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) MAP_ANONYMOUS | MAP_PRIVATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (user_addr >= (unsigned long)(TASK_SIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pr_warn("Failed to allocate user memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) kfree(kmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) usermem = (char __user *)user_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) bad_usermem = (char *)user_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Legitimate usage: none of these copies should fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) memset(kmem, 0x3a, PAGE_SIZE * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret |= test(copy_to_user(usermem, kmem, PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) "legitimate copy_to_user failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) memset(kmem, 0x0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ret |= test(copy_from_user(kmem, usermem, PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) "legitimate copy_from_user failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ret |= test(memcmp(kmem, kmem + PAGE_SIZE, PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "legitimate usercopy failed to copy data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define test_legit(size, check) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) val_##size = check; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ret |= test(put_user(val_##size, (size __user *)usermem), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "legitimate put_user (" #size ") failed"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) val_##size = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret |= test(get_user(val_##size, (size __user *)usermem), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) "legitimate get_user (" #size ") failed"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret |= test(val_##size != check, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "legitimate get_user (" #size ") failed to do copy"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (val_##size != check) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pr_info("0x%llx != 0x%llx\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) (unsigned long long)val_##size, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) (unsigned long long)check); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) test_legit(u8, 0x5a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) test_legit(u16, 0x5a5b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) test_legit(u32, 0x5a5b5c5d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #ifdef TEST_U64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) test_legit(u64, 0x5a5b5c5d6a6b6c6d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #undef test_legit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* Test usage of check_nonzero_user(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ret |= test_check_nonzero_user(kmem, usermem, 2 * PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Test usage of copy_struct_from_user(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ret |= test_copy_struct_from_user(kmem, usermem, 2 * PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * Invalid usage: none of these copies should succeed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* Prepare kernel memory with check values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) memset(kmem, 0x5a, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) memset(kmem + PAGE_SIZE, 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Reject kernel-to-kernel copies through copy_from_user(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret |= test(!copy_from_user(kmem, (char __user *)(kmem + PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) "illegal all-kernel copy_from_user passed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* Destination half of buffer should have been zeroed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret |= test(memcmp(kmem + PAGE_SIZE, kmem, PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) "zeroing failure for illegal all-kernel copy_from_user");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * When running with SMAP/PAN/etc, this will Oops the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * due to the zeroing of userspace memory on failure. This needs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * to be tested in LKDTM instead, since this test module does not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * expect to explode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ret |= test(!copy_from_user(bad_usermem, (char __user *)kmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) "illegal reversed copy_from_user passed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ret |= test(!copy_to_user((char __user *)kmem, kmem + PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) "illegal all-kernel copy_to_user passed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ret |= test(!copy_to_user((char __user *)kmem, bad_usermem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) PAGE_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) "illegal reversed copy_to_user passed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #define test_illegal(size, check) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) val_##size = (check); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret |= test(!get_user(val_##size, (size __user *)kmem), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) "illegal get_user (" #size ") passed"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ret |= test(val_##size != (size)0, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) "zeroing failure for illegal get_user (" #size ")"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (val_##size != (size)0) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) pr_info("0x%llx != 0\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) (unsigned long long)val_##size); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ret |= test(!put_user(val_##size, (size __user *)kmem), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) "illegal put_user (" #size ") passed"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) test_illegal(u8, 0x5a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) test_illegal(u16, 0x5a5b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) test_illegal(u32, 0x5a5b5c5d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #ifdef TEST_U64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) test_illegal(u64, 0x5a5b5c5d6a6b6c6d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #undef test_illegal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) vm_munmap(user_addr, PAGE_SIZE * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) kfree(kmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pr_info("tests passed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) module_init(test_user_copy_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void __exit test_user_copy_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) pr_info("unloaded.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) module_exit(test_user_copy_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) MODULE_AUTHOR("Kees Cook <keescook@chromium.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) MODULE_LICENSE("GPL");