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
main(int argc,char ** argv)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