add to, and prioritize the TODO a little.
[trinity.git] / maps.c
blobbe4f9af5b2de4c04535baf3087cc2c86bade06cc
1 #include <stdlib.h>
2 #include <string.h>
3 #include <sys/mman.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include "arch.h"
7 #include "list.h"
8 #include "child.h"
9 #include "maps.h"
10 #include "random.h"
11 #include "shm.h"
12 #include "trinity.h" // page_size
14 /* Walk a list, get a random element */
15 static struct map * __get_map(struct list_head *head, unsigned int max)
17 struct list_head *node;
19 unsigned int i, j = 0;
21 i = rand() % max;
23 list_for_each(node, head) {
24 struct map *m;
26 m = (struct map *) node;
28 if (i == j)
29 return m;
30 j++;
32 return NULL;
35 /* Return a pointer a previous mmap() that we did, either during startup,
36 * or from a fuzz result. */
37 struct map * get_map(void)
39 struct map *map;
40 bool local = FALSE;
42 /* We can get called by child processes, and also during startup by
43 * the main process when it constructs page_rand etc.
44 * If we're not running in child context, just do shared mappings.
45 * because main doesn't have any 'local' mappings.
47 if (this_child != 0) {
48 if (shm->num_mappings[this_child] > 0)
49 local = rand_bool();
52 if (local == TRUE)
53 map = __get_map(&shm->mappings[this_child]->list, shm->num_mappings[this_child]);
54 else
55 map = __get_map(&shared_mappings->list, num_shared_mappings);
57 return map;
60 static void delete_local_mapping(int childno, struct map *map)
62 list_del(&map->list);
63 shm->num_mappings[childno]--;
66 /* Called from munmap()'s ->post routine. */
67 void delete_mapping(int childno, struct map *map)
69 if (map->type == MAP_LOCAL)
70 delete_local_mapping(childno, map);
72 /* Right now, we don't want to delete MAP_GLOBAL mappings */
75 /* used in several sanitise_* functions. */
76 struct map * common_set_mmap_ptr_len(int childno)
78 struct map *map;
80 map = (struct map *) shm->syscall[childno].a1;
81 shm->scratch[childno] = (unsigned long) map; /* Save this for ->post */
82 if (map == NULL) {
83 shm->syscall[childno].a1 = 0;
84 shm->syscall[childno].a2 = 0;
85 return NULL;
88 shm->syscall[childno].a1 = (unsigned long) map->ptr;
89 shm->syscall[childno].a2 = map->size; //TODO: Munge this.
91 return map;
95 * Routine to perform various kinds of write operations to a mapping
96 * that we created.
98 void dirty_mapping(struct map *map)
100 char *p = map->ptr;
101 unsigned int i;
102 unsigned int num_pages = map->size / page_size;
104 /* Check mapping is writable, or we'll segv.
105 * TODO: Perhaps we should do that, and trap it, mark it writable,
106 * then reprotect after we dirtied it ? */
107 if (!(map->prot & PROT_WRITE))
108 return;
110 switch (rand() % 6) {
111 case 0:
112 /* Just fault in one page. */
113 p[rand() % map->size] = rand();
114 break;
116 case 1:
117 /* fault in the whole mapping. */
118 for (i = 0; i < map->size; i += page_size)
119 p[i] = rand();
120 break;
122 case 2:
123 /* every other page. */
124 for (i = 0; i < map->size; i += (page_size * 2))
125 p[i] = rand();
126 break;
128 case 3:
129 /* whole mapping in reverse */
130 for (i = (map->size - page_size); i > 0; i -= page_size)
131 p[i] = rand();
132 break;
134 case 4:
135 /* fault in a random set of map->size pages. (some may be faulted >once) */
136 for (i = 0; i < num_pages; i++)
137 p[(rand() % (num_pages + 1)) * page_size] = rand();
138 break;
140 case 5:
141 /* fault in the last page in a mapping
142 * Fill it with ascii, in the hope we do something like
143 * a strlen and go off the end. */
144 memset((void *) p + (map->size - page_size), 'A', page_size);
145 break;