at v4.18 15 kB view raw
1// SPDX-License-Identifier: GPL-2.0 OR MIT 2/* 3 * Test cases for arithmetic overflow checks. 4 */ 5#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 6 7#include <linux/device.h> 8#include <linux/init.h> 9#include <linux/kernel.h> 10#include <linux/mm.h> 11#include <linux/module.h> 12#include <linux/overflow.h> 13#include <linux/slab.h> 14#include <linux/types.h> 15#include <linux/vmalloc.h> 16 17#define DEFINE_TEST_ARRAY(t) \ 18 static const struct test_ ## t { \ 19 t a, b; \ 20 t sum, diff, prod; \ 21 bool s_of, d_of, p_of; \ 22 } t ## _tests[] __initconst 23 24DEFINE_TEST_ARRAY(u8) = { 25 {0, 0, 0, 0, 0, false, false, false}, 26 {1, 1, 2, 0, 1, false, false, false}, 27 {0, 1, 1, U8_MAX, 0, false, true, false}, 28 {1, 0, 1, 1, 0, false, false, false}, 29 {0, U8_MAX, U8_MAX, 1, 0, false, true, false}, 30 {U8_MAX, 0, U8_MAX, U8_MAX, 0, false, false, false}, 31 {1, U8_MAX, 0, 2, U8_MAX, true, true, false}, 32 {U8_MAX, 1, 0, U8_MAX-1, U8_MAX, true, false, false}, 33 {U8_MAX, U8_MAX, U8_MAX-1, 0, 1, true, false, true}, 34 35 {U8_MAX, U8_MAX-1, U8_MAX-2, 1, 2, true, false, true}, 36 {U8_MAX-1, U8_MAX, U8_MAX-2, U8_MAX, 2, true, true, true}, 37 38 {1U << 3, 1U << 3, 1U << 4, 0, 1U << 6, false, false, false}, 39 {1U << 4, 1U << 4, 1U << 5, 0, 0, false, false, true}, 40 {1U << 4, 1U << 3, 3*(1U << 3), 1U << 3, 1U << 7, false, false, false}, 41 {1U << 7, 1U << 7, 0, 0, 0, true, false, true}, 42 43 {48, 32, 80, 16, 0, false, false, true}, 44 {128, 128, 0, 0, 0, true, false, true}, 45 {123, 234, 101, 145, 110, true, true, true}, 46}; 47DEFINE_TEST_ARRAY(u16) = { 48 {0, 0, 0, 0, 0, false, false, false}, 49 {1, 1, 2, 0, 1, false, false, false}, 50 {0, 1, 1, U16_MAX, 0, false, true, false}, 51 {1, 0, 1, 1, 0, false, false, false}, 52 {0, U16_MAX, U16_MAX, 1, 0, false, true, false}, 53 {U16_MAX, 0, U16_MAX, U16_MAX, 0, false, false, false}, 54 {1, U16_MAX, 0, 2, U16_MAX, true, true, false}, 55 {U16_MAX, 1, 0, U16_MAX-1, U16_MAX, true, false, false}, 56 {U16_MAX, U16_MAX, U16_MAX-1, 0, 1, true, false, true}, 57 58 {U16_MAX, U16_MAX-1, U16_MAX-2, 1, 2, true, false, true}, 59 {U16_MAX-1, U16_MAX, U16_MAX-2, U16_MAX, 2, true, true, true}, 60 61 {1U << 7, 1U << 7, 1U << 8, 0, 1U << 14, false, false, false}, 62 {1U << 8, 1U << 8, 1U << 9, 0, 0, false, false, true}, 63 {1U << 8, 1U << 7, 3*(1U << 7), 1U << 7, 1U << 15, false, false, false}, 64 {1U << 15, 1U << 15, 0, 0, 0, true, false, true}, 65 66 {123, 234, 357, 65425, 28782, false, true, false}, 67 {1234, 2345, 3579, 64425, 10146, false, true, true}, 68}; 69DEFINE_TEST_ARRAY(u32) = { 70 {0, 0, 0, 0, 0, false, false, false}, 71 {1, 1, 2, 0, 1, false, false, false}, 72 {0, 1, 1, U32_MAX, 0, false, true, false}, 73 {1, 0, 1, 1, 0, false, false, false}, 74 {0, U32_MAX, U32_MAX, 1, 0, false, true, false}, 75 {U32_MAX, 0, U32_MAX, U32_MAX, 0, false, false, false}, 76 {1, U32_MAX, 0, 2, U32_MAX, true, true, false}, 77 {U32_MAX, 1, 0, U32_MAX-1, U32_MAX, true, false, false}, 78 {U32_MAX, U32_MAX, U32_MAX-1, 0, 1, true, false, true}, 79 80 {U32_MAX, U32_MAX-1, U32_MAX-2, 1, 2, true, false, true}, 81 {U32_MAX-1, U32_MAX, U32_MAX-2, U32_MAX, 2, true, true, true}, 82 83 {1U << 15, 1U << 15, 1U << 16, 0, 1U << 30, false, false, false}, 84 {1U << 16, 1U << 16, 1U << 17, 0, 0, false, false, true}, 85 {1U << 16, 1U << 15, 3*(1U << 15), 1U << 15, 1U << 31, false, false, false}, 86 {1U << 31, 1U << 31, 0, 0, 0, true, false, true}, 87 88 {-2U, 1U, -1U, -3U, -2U, false, false, false}, 89 {-4U, 5U, 1U, -9U, -20U, true, false, true}, 90}; 91 92DEFINE_TEST_ARRAY(u64) = { 93 {0, 0, 0, 0, 0, false, false, false}, 94 {1, 1, 2, 0, 1, false, false, false}, 95 {0, 1, 1, U64_MAX, 0, false, true, false}, 96 {1, 0, 1, 1, 0, false, false, false}, 97 {0, U64_MAX, U64_MAX, 1, 0, false, true, false}, 98 {U64_MAX, 0, U64_MAX, U64_MAX, 0, false, false, false}, 99 {1, U64_MAX, 0, 2, U64_MAX, true, true, false}, 100 {U64_MAX, 1, 0, U64_MAX-1, U64_MAX, true, false, false}, 101 {U64_MAX, U64_MAX, U64_MAX-1, 0, 1, true, false, true}, 102 103 {U64_MAX, U64_MAX-1, U64_MAX-2, 1, 2, true, false, true}, 104 {U64_MAX-1, U64_MAX, U64_MAX-2, U64_MAX, 2, true, true, true}, 105 106 {1ULL << 31, 1ULL << 31, 1ULL << 32, 0, 1ULL << 62, false, false, false}, 107 {1ULL << 32, 1ULL << 32, 1ULL << 33, 0, 0, false, false, true}, 108 {1ULL << 32, 1ULL << 31, 3*(1ULL << 31), 1ULL << 31, 1ULL << 63, false, false, false}, 109 {1ULL << 63, 1ULL << 63, 0, 0, 0, true, false, true}, 110 {1000000000ULL /* 10^9 */, 10000000000ULL /* 10^10 */, 111 11000000000ULL, 18446744064709551616ULL, 10000000000000000000ULL, 112 false, true, false}, 113 {-15ULL, 10ULL, -5ULL, -25ULL, -150ULL, false, false, true}, 114}; 115 116DEFINE_TEST_ARRAY(s8) = { 117 {0, 0, 0, 0, 0, false, false, false}, 118 119 {0, S8_MAX, S8_MAX, -S8_MAX, 0, false, false, false}, 120 {S8_MAX, 0, S8_MAX, S8_MAX, 0, false, false, false}, 121 {0, S8_MIN, S8_MIN, S8_MIN, 0, false, true, false}, 122 {S8_MIN, 0, S8_MIN, S8_MIN, 0, false, false, false}, 123 124 {-1, S8_MIN, S8_MAX, S8_MAX, S8_MIN, true, false, true}, 125 {S8_MIN, -1, S8_MAX, -S8_MAX, S8_MIN, true, false, true}, 126 {-1, S8_MAX, S8_MAX-1, S8_MIN, -S8_MAX, false, false, false}, 127 {S8_MAX, -1, S8_MAX-1, S8_MIN, -S8_MAX, false, true, false}, 128 {-1, -S8_MAX, S8_MIN, S8_MAX-1, S8_MAX, false, false, false}, 129 {-S8_MAX, -1, S8_MIN, S8_MIN+2, S8_MAX, false, false, false}, 130 131 {1, S8_MIN, -S8_MAX, -S8_MAX, S8_MIN, false, true, false}, 132 {S8_MIN, 1, -S8_MAX, S8_MAX, S8_MIN, false, true, false}, 133 {1, S8_MAX, S8_MIN, S8_MIN+2, S8_MAX, true, false, false}, 134 {S8_MAX, 1, S8_MIN, S8_MAX-1, S8_MAX, true, false, false}, 135 136 {S8_MIN, S8_MIN, 0, 0, 0, true, false, true}, 137 {S8_MAX, S8_MAX, -2, 0, 1, true, false, true}, 138 139 {-4, -32, -36, 28, -128, false, false, true}, 140 {-4, 32, 28, -36, -128, false, false, false}, 141}; 142 143DEFINE_TEST_ARRAY(s16) = { 144 {0, 0, 0, 0, 0, false, false, false}, 145 146 {0, S16_MAX, S16_MAX, -S16_MAX, 0, false, false, false}, 147 {S16_MAX, 0, S16_MAX, S16_MAX, 0, false, false, false}, 148 {0, S16_MIN, S16_MIN, S16_MIN, 0, false, true, false}, 149 {S16_MIN, 0, S16_MIN, S16_MIN, 0, false, false, false}, 150 151 {-1, S16_MIN, S16_MAX, S16_MAX, S16_MIN, true, false, true}, 152 {S16_MIN, -1, S16_MAX, -S16_MAX, S16_MIN, true, false, true}, 153 {-1, S16_MAX, S16_MAX-1, S16_MIN, -S16_MAX, false, false, false}, 154 {S16_MAX, -1, S16_MAX-1, S16_MIN, -S16_MAX, false, true, false}, 155 {-1, -S16_MAX, S16_MIN, S16_MAX-1, S16_MAX, false, false, false}, 156 {-S16_MAX, -1, S16_MIN, S16_MIN+2, S16_MAX, false, false, false}, 157 158 {1, S16_MIN, -S16_MAX, -S16_MAX, S16_MIN, false, true, false}, 159 {S16_MIN, 1, -S16_MAX, S16_MAX, S16_MIN, false, true, false}, 160 {1, S16_MAX, S16_MIN, S16_MIN+2, S16_MAX, true, false, false}, 161 {S16_MAX, 1, S16_MIN, S16_MAX-1, S16_MAX, true, false, false}, 162 163 {S16_MIN, S16_MIN, 0, 0, 0, true, false, true}, 164 {S16_MAX, S16_MAX, -2, 0, 1, true, false, true}, 165}; 166DEFINE_TEST_ARRAY(s32) = { 167 {0, 0, 0, 0, 0, false, false, false}, 168 169 {0, S32_MAX, S32_MAX, -S32_MAX, 0, false, false, false}, 170 {S32_MAX, 0, S32_MAX, S32_MAX, 0, false, false, false}, 171 {0, S32_MIN, S32_MIN, S32_MIN, 0, false, true, false}, 172 {S32_MIN, 0, S32_MIN, S32_MIN, 0, false, false, false}, 173 174 {-1, S32_MIN, S32_MAX, S32_MAX, S32_MIN, true, false, true}, 175 {S32_MIN, -1, S32_MAX, -S32_MAX, S32_MIN, true, false, true}, 176 {-1, S32_MAX, S32_MAX-1, S32_MIN, -S32_MAX, false, false, false}, 177 {S32_MAX, -1, S32_MAX-1, S32_MIN, -S32_MAX, false, true, false}, 178 {-1, -S32_MAX, S32_MIN, S32_MAX-1, S32_MAX, false, false, false}, 179 {-S32_MAX, -1, S32_MIN, S32_MIN+2, S32_MAX, false, false, false}, 180 181 {1, S32_MIN, -S32_MAX, -S32_MAX, S32_MIN, false, true, false}, 182 {S32_MIN, 1, -S32_MAX, S32_MAX, S32_MIN, false, true, false}, 183 {1, S32_MAX, S32_MIN, S32_MIN+2, S32_MAX, true, false, false}, 184 {S32_MAX, 1, S32_MIN, S32_MAX-1, S32_MAX, true, false, false}, 185 186 {S32_MIN, S32_MIN, 0, 0, 0, true, false, true}, 187 {S32_MAX, S32_MAX, -2, 0, 1, true, false, true}, 188}; 189DEFINE_TEST_ARRAY(s64) = { 190 {0, 0, 0, 0, 0, false, false, false}, 191 192 {0, S64_MAX, S64_MAX, -S64_MAX, 0, false, false, false}, 193 {S64_MAX, 0, S64_MAX, S64_MAX, 0, false, false, false}, 194 {0, S64_MIN, S64_MIN, S64_MIN, 0, false, true, false}, 195 {S64_MIN, 0, S64_MIN, S64_MIN, 0, false, false, false}, 196 197 {-1, S64_MIN, S64_MAX, S64_MAX, S64_MIN, true, false, true}, 198 {S64_MIN, -1, S64_MAX, -S64_MAX, S64_MIN, true, false, true}, 199 {-1, S64_MAX, S64_MAX-1, S64_MIN, -S64_MAX, false, false, false}, 200 {S64_MAX, -1, S64_MAX-1, S64_MIN, -S64_MAX, false, true, false}, 201 {-1, -S64_MAX, S64_MIN, S64_MAX-1, S64_MAX, false, false, false}, 202 {-S64_MAX, -1, S64_MIN, S64_MIN+2, S64_MAX, false, false, false}, 203 204 {1, S64_MIN, -S64_MAX, -S64_MAX, S64_MIN, false, true, false}, 205 {S64_MIN, 1, -S64_MAX, S64_MAX, S64_MIN, false, true, false}, 206 {1, S64_MAX, S64_MIN, S64_MIN+2, S64_MAX, true, false, false}, 207 {S64_MAX, 1, S64_MIN, S64_MAX-1, S64_MAX, true, false, false}, 208 209 {S64_MIN, S64_MIN, 0, 0, 0, true, false, true}, 210 {S64_MAX, S64_MAX, -2, 0, 1, true, false, true}, 211 212 {-1, -1, -2, 0, 1, false, false, false}, 213 {-1, -128, -129, 127, 128, false, false, false}, 214 {-128, -1, -129, -127, 128, false, false, false}, 215 {0, -S64_MAX, -S64_MAX, S64_MAX, 0, false, false, false}, 216}; 217 218#define check_one_op(t, fmt, op, sym, a, b, r, of) do { \ 219 t _r; \ 220 bool _of; \ 221 \ 222 _of = check_ ## op ## _overflow(a, b, &_r); \ 223 if (_of != of) { \ 224 pr_warn("expected "fmt" "sym" "fmt \ 225 " to%s overflow (type %s)\n", \ 226 a, b, of ? "" : " not", #t); \ 227 err = 1; \ 228 } \ 229 if (_r != r) { \ 230 pr_warn("expected "fmt" "sym" "fmt" == " \ 231 fmt", got "fmt" (type %s)\n", \ 232 a, b, r, _r, #t); \ 233 err = 1; \ 234 } \ 235} while (0) 236 237#define DEFINE_TEST_FUNC(t, fmt) \ 238static int __init do_test_ ## t(const struct test_ ## t *p) \ 239{ \ 240 int err = 0; \ 241 \ 242 check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \ 243 check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \ 244 check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \ 245 check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of); \ 246 check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of); \ 247 \ 248 return err; \ 249} \ 250 \ 251static int __init test_ ## t ## _overflow(void) { \ 252 int err = 0; \ 253 unsigned i; \ 254 \ 255 pr_info("%-3s: %zu tests\n", #t, ARRAY_SIZE(t ## _tests)); \ 256 for (i = 0; i < ARRAY_SIZE(t ## _tests); ++i) \ 257 err |= do_test_ ## t(&t ## _tests[i]); \ 258 return err; \ 259} 260 261DEFINE_TEST_FUNC(u8, "%d"); 262DEFINE_TEST_FUNC(s8, "%d"); 263DEFINE_TEST_FUNC(u16, "%d"); 264DEFINE_TEST_FUNC(s16, "%d"); 265DEFINE_TEST_FUNC(u32, "%u"); 266DEFINE_TEST_FUNC(s32, "%d"); 267#if BITS_PER_LONG == 64 268DEFINE_TEST_FUNC(u64, "%llu"); 269DEFINE_TEST_FUNC(s64, "%lld"); 270#endif 271 272static int __init test_overflow_calculation(void) 273{ 274 int err = 0; 275 276 err |= test_u8_overflow(); 277 err |= test_s8_overflow(); 278 err |= test_u16_overflow(); 279 err |= test_s16_overflow(); 280 err |= test_u32_overflow(); 281 err |= test_s32_overflow(); 282#if BITS_PER_LONG == 64 283 err |= test_u64_overflow(); 284 err |= test_s64_overflow(); 285#endif 286 287 return err; 288} 289 290/* 291 * Deal with the various forms of allocator arguments. See comments above 292 * the DEFINE_TEST_ALLOC() instances for mapping of the "bits". 293 */ 294#define alloc010(alloc, arg, sz) alloc(sz, GFP_KERNEL) 295#define alloc011(alloc, arg, sz) alloc(sz, GFP_KERNEL, NUMA_NO_NODE) 296#define alloc000(alloc, arg, sz) alloc(sz) 297#define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE) 298#define alloc110(alloc, arg, sz) alloc(arg, sz, GFP_KERNEL) 299#define free0(free, arg, ptr) free(ptr) 300#define free1(free, arg, ptr) free(arg, ptr) 301 302/* Wrap around to 8K */ 303#define TEST_SIZE (9 << PAGE_SHIFT) 304 305#define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\ 306static int __init test_ ## func (void *arg) \ 307{ \ 308 volatile size_t a = TEST_SIZE; \ 309 volatile size_t b = (SIZE_MAX / TEST_SIZE) + 1; \ 310 void *ptr; \ 311 \ 312 /* Tiny allocation test. */ \ 313 ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, 1);\ 314 if (!ptr) { \ 315 pr_warn(#func " failed regular allocation?!\n"); \ 316 return 1; \ 317 } \ 318 free ## want_arg (free_func, arg, ptr); \ 319 \ 320 /* Wrapped allocation test. */ \ 321 ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, \ 322 a * b); \ 323 if (!ptr) { \ 324 pr_warn(#func " unexpectedly failed bad wrapping?!\n"); \ 325 return 1; \ 326 } \ 327 free ## want_arg (free_func, arg, ptr); \ 328 \ 329 /* Saturated allocation test. */ \ 330 ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, \ 331 array_size(a, b)); \ 332 if (ptr) { \ 333 pr_warn(#func " missed saturation!\n"); \ 334 free ## want_arg (free_func, arg, ptr); \ 335 return 1; \ 336 } \ 337 pr_info(#func " detected saturation\n"); \ 338 return 0; \ 339} 340 341/* 342 * Allocator uses a trailing node argument --------+ (e.g. kmalloc_node()) 343 * Allocator uses the gfp_t argument -----------+ | (e.g. kmalloc()) 344 * Allocator uses a special leading argument + | | (e.g. devm_kmalloc()) 345 * | | | 346 */ 347DEFINE_TEST_ALLOC(kmalloc, kfree, 0, 1, 0); 348DEFINE_TEST_ALLOC(kmalloc_node, kfree, 0, 1, 1); 349DEFINE_TEST_ALLOC(kzalloc, kfree, 0, 1, 0); 350DEFINE_TEST_ALLOC(kzalloc_node, kfree, 0, 1, 1); 351DEFINE_TEST_ALLOC(vmalloc, vfree, 0, 0, 0); 352DEFINE_TEST_ALLOC(vmalloc_node, vfree, 0, 0, 1); 353DEFINE_TEST_ALLOC(vzalloc, vfree, 0, 0, 0); 354DEFINE_TEST_ALLOC(vzalloc_node, vfree, 0, 0, 1); 355DEFINE_TEST_ALLOC(kvmalloc, kvfree, 0, 1, 0); 356DEFINE_TEST_ALLOC(kvmalloc_node, kvfree, 0, 1, 1); 357DEFINE_TEST_ALLOC(kvzalloc, kvfree, 0, 1, 0); 358DEFINE_TEST_ALLOC(kvzalloc_node, kvfree, 0, 1, 1); 359DEFINE_TEST_ALLOC(devm_kmalloc, devm_kfree, 1, 1, 0); 360DEFINE_TEST_ALLOC(devm_kzalloc, devm_kfree, 1, 1, 0); 361 362static int __init test_overflow_allocation(void) 363{ 364 const char device_name[] = "overflow-test"; 365 struct device *dev; 366 int err = 0; 367 368 /* Create dummy device for devm_kmalloc()-family tests. */ 369 dev = root_device_register(device_name); 370 if (IS_ERR(dev)) { 371 pr_warn("Cannot register test device\n"); 372 return 1; 373 } 374 375 err |= test_kmalloc(NULL); 376 err |= test_kmalloc_node(NULL); 377 err |= test_kzalloc(NULL); 378 err |= test_kzalloc_node(NULL); 379 err |= test_kvmalloc(NULL); 380 err |= test_kvmalloc_node(NULL); 381 err |= test_kvzalloc(NULL); 382 err |= test_kvzalloc_node(NULL); 383 err |= test_vmalloc(NULL); 384 err |= test_vmalloc_node(NULL); 385 err |= test_vzalloc(NULL); 386 err |= test_vzalloc_node(NULL); 387 err |= test_devm_kmalloc(dev); 388 err |= test_devm_kzalloc(dev); 389 390 device_unregister(dev); 391 392 return err; 393} 394 395static int __init test_module_init(void) 396{ 397 int err = 0; 398 399 err |= test_overflow_calculation(); 400 err |= test_overflow_allocation(); 401 402 if (err) { 403 pr_warn("FAIL!\n"); 404 err = -EINVAL; 405 } else { 406 pr_info("all tests passed\n"); 407 } 408 409 return err; 410} 411 412static void __exit test_module_exit(void) 413{ } 414 415module_init(test_module_init); 416module_exit(test_module_exit); 417MODULE_LICENSE("Dual MIT/GPL");