Home | History | Annotate | Download | only in src
      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