static void nfc_rand_socket(struct socket_triplet *st) { if (RAND_BOOL()) { st->protocol = NFC_SOCKPROTO_LLCP; if (RAND_BOOL()) st->type = SOCK_DGRAM; else st->type = SOCK_STREAM; return; } st->protocol = NFC_SOCKPROTO_RAW; st->type = SOCK_SEQPACKET; }
unsigned long get_interesting_value(void) { unsigned long low = 0; switch (rand() % 3) { case 0: low = get_interesting_8bit_value(); break; case 1: low = get_interesting_16bit_value(); break; case 2: low = get_interesting_32bit_value(); break; } low = (rand() & 0xf) ? low : plus_minus_two(low); // 1 in 16 call plus_minus_two #if __WORDSIZE != 32 if (RAND_BOOL()) { // FIXME: This should likely be less aggressive than 50/50 switch (rand() % 11) { case 0: return 0x0000000100000000UL | low; case 1: return 0x7fffffff00000000UL | low; case 2: return 0x8000000000000000UL | low; case 3: return 0xffffffff00000000UL | low; case 4: return 0xffffffffffffff00UL | RAND_BYTE(); case 5: return 0xffffffffffffffffUL - page_size; case 6: return PAGE_OFFSET | (low << 4); case 7: return KERNEL_ADDR | (low & 0xffffff); case 8: return MODULE_ADDR | (low & 0xffffff); case 9: return per_arch_interesting_addr(low); case 10: return (low << 32); } } #endif /* __WORDSIZE */ return low; }
static void inet6_setsockopt(struct sockopt *so, __unused__ struct socket_triplet *triplet) { unsigned char val; so->level = SOL_IPV6; val = rnd() % ARRAY_SIZE(inet6_opts); so->optname = inet6_opts[val].name; so->optlen = sockoptlen(inet6_opts[val].len); switch (so->optname) { case IPV6_HOPOPTS: case IPV6_RTHDRDSTOPTS: case IPV6_RTHDR: case IPV6_DSTOPTS: so->optlen = sizeof(struct ipv6_opt_hdr); so->optlen += rnd() % ((8 * 255) - so->optlen); so->optlen &= ~0x7; break; case IPV6_2292PKTOPTIONS: if (RAND_BOOL()) so->optlen = 0; // update else so->optlen = rnd() % 64*1024; break; case IPV6_IPSEC_POLICY: case IPV6_XFRM_POLICY: so->optlen = rnd() % page_size; break; } }
static unsigned long handle_arg_address(struct syscallrecord *rec, unsigned int argnum) { unsigned long addr = 0; if (argnum == 1) return (unsigned long) get_address(); if (RAND_BOOL()) return (unsigned long) get_address(); /* Half the time, we look to see if earlier args were also ARG_ADDRESS, * and munge that instead of returning a new one from get_address() */ addr = find_previous_arg_address(rec, argnum); switch (rnd() % 4) { case 0: break; /* return unmodified */ case 1: addr++; break; case 2: addr+= sizeof(int); break; case 3: addr+= sizeof(long); break; } return addr; }
static void caif_rand_socket(struct socket_triplet *st) { st->protocol = rnd() % _CAIFPROTO_MAX; if (RAND_BOOL()) st->type = SOCK_SEQPACKET; else st->type = SOCK_STREAM; }
static void ioctl_mangle_arg(struct syscallrecord *rec) { /* the argument could mean anything, because ioctl sucks like that. */ if (RAND_BOOL()) rec->a3 = rand32(); else rec->a3 = (unsigned long) get_non_null_address(); }
void llc_rand_socket(struct socket_triplet *st) { st->protocol = rand() % PROTO_MAX; if (RAND_BOOL()) st->type = SOCK_STREAM; else st->type = SOCK_DGRAM; }
static int open_socket(unsigned int domain, unsigned int type, unsigned int protocol) { struct object *obj; struct sockaddr *sa = NULL; const struct netproto *proto; socklen_t salen; struct sockopt so = { 0, 0, 0, 0 }; int fd; fd = socket(domain, type, protocol); if (fd == -1) return fd; obj = add_socket(fd, domain, type, protocol); proto = net_protocols[domain].proto; if (proto != NULL) if (proto->socket_setup != NULL) proto->socket_setup(fd); // FIXME: // All of this needs to be broken out into child ops instead of // special casing it all at creation time. /* Set some random socket options. */ sso_socket(&obj->sockinfo.triplet, &so, fd); nr_sockets++; /* Sometimes, listen on created sockets. */ if (RAND_BOOL()) { int ret, one = 1; /* fake a sockaddr. */ generate_sockaddr((struct sockaddr **) &sa, (socklen_t *) &salen, domain); ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (ret != -1) goto skip_bind; ret = bind(fd, sa, salen); if (ret != -1) (void) listen(fd, RAND_RANGE(1, 128)); // ret = accept4(fd, sa, &salen, SOCK_NONBLOCK); // if (ret != -1) { // obj = add_socket(ret, domain, type, protocol); // nr_sockets++; // } } skip_bind: if (sa != NULL) free(sa); return fd; }
void generate_rand_bytes(unsigned char *ptr, unsigned int len) { unsigned int i; unsigned char choice = rand() % 3; unsigned int startoffset = 0, remain; unsigned char separators[3] = { ' ', '-', '\0' }; unsigned char separator; switch (choice) { case 0: /* Complete garbage. */ for (i = 0; i < len; i++) ptr[i] = RAND_BYTE(); break; case 1: /* printable text strings. */ for (i = 0; i < len; i++) ptr[i] = 32 + rand() % (0x7f - 32); break; case 2: /* numbers (for now, decimal only) */ separator = separators[rand() % 3]; remain = len; while (remain > 0) { unsigned int runlen; /* Sometimes make the numbers be negative. */ if (RAND_BOOL()) { ptr[startoffset++] = '-'; remain--; if (remain == 0) break; } /* At most make this run 10 chars. */ runlen = min(remain, (unsigned int) rand() % 10); for (i = startoffset; i < startoffset + runlen; i++) ptr[i] = '0' + rand() % 10; startoffset += runlen; remain -= runlen; /* insert commas and/or spaces */ if (remain > 0) { ptr[i++] = separator; startoffset++; remain--; } } break; } }
/* * Generate and munge a 64bit number. */ u64 rand64(void) { unsigned long r = 0; if (RAND_BOOL()) { /* 32-bit ranges. */ r = rand32(); } else { /* 33:64-bit ranges. */ switch (rand() % 5) { case 0: r = rand_single_bit(64); break; case 1: r = randbits(64); break; case 2: r = RAND_64(); break; case 3: r = rept_byte(); break; /* Sometimes pick a not-so-random number. */ case 4: return get_interesting_value(); } /* limit the size */ switch (rand() % 4) { case 0: r &= 0x000000ffffffffffULL; break; case 1: r &= 0x0000ffffffffffffULL; break; case 2: r &= 0x00ffffffffffffffULL; break; default: /* no limiting. */ break; } } /* Sometimes invert the generated number. */ if (ONE_IN(25)) r = ~r; /* increase distribution in MSB */ if (ONE_IN(10)) { unsigned int i; unsigned int rounds; rounds = rand() % 4; for (i = 0; i < rounds; i++) r |= (1UL << ((__WORDSIZE - 1) - (rand() % 8))); } /* Sometimes flip sign */ if (ONE_IN(25)) r = ~r + 1; return r; }
static void sanitise_mlockall(struct syscallrecord *rec) { if (rec->a1 != 0) return; if (RAND_BOOL()) rec->a1 = MCL_CURRENT; else rec->a1 = MCL_FUTURE; }
void random_map_readfn(struct map *map) { if (map->size == page_size) read_one_page(map); else { if (RAND_BOOL()) read_one_page(map); else read_faultfns[rnd() % ARRAY_SIZE(read_faultfns)].func(map); } }
/* * SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) */ static void sanitise_sendmsg(struct syscallrecord *rec) { struct socketinfo *si = (struct socketinfo *) rec->a1; struct msghdr *msg; struct sockaddr *sa = NULL; socklen_t salen = 0; if (si == NULL) // handle --disable-fds=sockets goto skip_si; rec->a1 = fd_from_socketinfo((struct socketinfo *) rec->a1); generate_sockaddr((struct sockaddr **) &sa, (socklen_t *) &salen, si->triplet.family); skip_si: msg = zmalloc(sizeof(struct msghdr)); msg->msg_name = sa; msg->msg_namelen = salen; if (RAND_BOOL()) { unsigned int num_entries; num_entries = RAND_RANGE(1, 3); msg->msg_iov = alloc_iovec(num_entries); msg->msg_iovlen = num_entries; } if (RAND_BOOL()) { msg->msg_controllen = rand32() % 20480; // /proc/sys/net/core/optmem_max msg->msg_control = get_address(); } else { msg->msg_controllen = 0; } if (ONE_IN(100)) msg->msg_flags = rand32(); else msg->msg_flags = 0; rec->a2 = (unsigned long) msg; }
static void dirty_every_other_page(struct map *map) { char *p = map->ptr; unsigned int i, nr, first; nr = nr_pages(map); first = RAND_BOOL(); for (i = first; i < nr; i+=2) p[i * page_size] = rnd(); }
void netlink_rand_socket(struct socket_triplet *st) { if (RAND_BOOL()) st->type = SOCK_RAW; else st->type = SOCK_DGRAM; st->protocol = rnd() % (_NETLINK_MAX + 1); if (st->protocol == NETLINK_SOCK_DIAG) st->type = rnd() % 136; }
void random_map_writefn(struct map *map) { if (map->size == page_size) { write_faultfns_single[rnd() % ARRAY_SIZE(write_faultfns_single)].func(map); } else { if (RAND_BOOL()) { write_faultfns[rnd() % ARRAY_SIZE(write_faultfns)].func(map); } else { write_faultfns_single[rnd() % ARRAY_SIZE(write_faultfns_single)].func(map); } } }
static int fallbackseed(void) { struct timeval t; unsigned int r; //printf("Fell back to gtod seed! errno:%s\n", strerror(errno)); r = rnd(); if (!(RAND_BOOL())) { gettimeofday(&t, NULL); r |= t.tv_usec; } return r; }
static unsigned long random_ioctl_arg(void) { if (RAND_BOOL()) { return (unsigned long) rand64(); } else { void *page; page = get_writable_address(page_size); generate_random_page(page); return (unsigned long) page; } }
static void read_every_other_page(struct map *map) { char *p = map->ptr; unsigned int i, nr, first; char buf[page_size]; nr = nr_pages(map); first = RAND_BOOL(); for (i = first; i < nr; i+=2) memcpy(buf, p + (i * page_size), page_size); }
static void sanitise_remap_file_pages(struct syscallrecord *rec) { struct map *map; size_t size, offset; size_t start = 0; map = common_set_mmap_ptr_len(); if (RAND_BOOL()) { start = rnd() % map->size; start &= PAGE_MASK; rec->a1 += start; } /* We just want to remap a part of the mapping. */ if (RAND_BOOL()) size = page_size; else { size = rnd() % map->size; /* if we screwed with the start, we need to take it * into account so we don't go off the end. */ if (start != 0) size -= start; } rec->a2 = size; /* "The prot argument must be specified as 0" */ rec->a3 = 0; /* Pick a random pgoff. */ if (RAND_BOOL()) offset = rnd() & (size / page_size); else offset = 0; rec->a4 = offset; }
static void dirty_every_other_page(struct map *map) { unsigned int i, nr, first; nr = nr_pages(map); first = RAND_BOOL(); for (i = first; i < nr; i+=2) { char *p = map->ptr + (i * page_size); mark_page_rw(map, p); *p = rnd(); } }
/* * OR a random number of bits from the list of values into a bitmask, and return it. */ static unsigned long handle_arg_list(struct syscallentry *entry, unsigned int argnum) { unsigned long mask = 0; unsigned int num = 0; const unsigned long *values = NULL; get_num_and_values(entry, argnum, &num, &values); if (RAND_BOOL()) num = min(num, 3U); mask = set_rand_bitmask(num, values); return mask; }
void random_map_writefn(struct map *map) { if (map->size == page_size) { mprotect(map->ptr, page_size, PROT_READ|PROT_WRITE); write_faultfns_single[rnd() % ARRAY_SIZE(write_faultfns_single)].func(map); } else { if (RAND_BOOL()) { mprotect(map->ptr, map->size, PROT_READ|PROT_WRITE); write_faultfns[rnd() % ARRAY_SIZE(write_faultfns)].func(map); } else { mprotect(map->ptr, page_size, PROT_READ|PROT_WRITE); write_faultfns_single[rnd() % ARRAY_SIZE(write_faultfns_single)].func(map); } } }
static void autofs_sanitise(const struct ioctl_group *grp, struct syscallrecord *rec) { struct autofs_dev_ioctl *arg; pick_random_ioctl(grp, rec); rec->a3 = (unsigned long) get_address(); switch (rec->a2) { case AUTOFS_DEV_IOCTL_VERSION: case AUTOFS_DEV_IOCTL_PROTOVER: case AUTOFS_DEV_IOCTL_PROTOSUBVER: case AUTOFS_DEV_IOCTL_OPENMOUNT: case AUTOFS_DEV_IOCTL_CLOSEMOUNT: case AUTOFS_DEV_IOCTL_READY: case AUTOFS_DEV_IOCTL_FAIL: case AUTOFS_DEV_IOCTL_SETPIPEFD: case AUTOFS_DEV_IOCTL_CATATONIC: case AUTOFS_DEV_IOCTL_TIMEOUT: case AUTOFS_DEV_IOCTL_REQUESTER: case AUTOFS_DEV_IOCTL_EXPIRE: case AUTOFS_DEV_IOCTL_ASKUMOUNT: case AUTOFS_DEV_IOCTL_ISMOUNTPOINT: arg = (struct autofs_dev_ioctl *) rec->a3; init_autofs_dev_ioctl(arg); arg->ioctlfd = get_random_fd(); arg->fail.token = rand(); arg->fail.status = rand(); if (RAND_BOOL()) { arg->size += 5; arg->path[0] = '/'; arg->path[1] = rand(); arg->path[2] = rand(); arg->path[3] = rand(); arg->path[4] = 0; } else { int i; arg->size += rand(); for (i=0; i < 10; ++i) arg->path[i] = rand(); } break; default: break; } }
void ipx_gen_sockaddr(struct sockaddr **addr, socklen_t *addrlen) { struct sockaddr_ipx *ipx; unsigned int i; ipx = zmalloc(sizeof(struct sockaddr_ipx)); ipx->sipx_family = PF_IPX; ipx->sipx_port = rnd(); ipx->sipx_network = rnd(); for (i = 0; i < 6; i++) ipx->sipx_node[i] = rnd(); ipx->sipx_type = rnd(); ipx->sipx_zero = RAND_BOOL(); *addr = (struct sockaddr *) ipx; *addrlen = sizeof(struct sockaddr_ipx); }
unsigned int new_seed(void) { int fd; struct timeval t; unsigned int r; if ((fd = open("/dev/urandom", O_RDONLY)) < 0 || read(fd, &r, sizeof(r)) != sizeof(r)) { r = rand(); if (!(RAND_BOOL())) { gettimeofday(&t, NULL); r |= t.tv_usec; } } if (fd >= 0) close(fd); return r; }
bool read_all_files(__unused__ struct childdata *child) { struct stat sb; char *buffer; unsigned int i; int fd; for (i = 0; i < files_in_index; i++) { int ret; const char *filename; filename = fileindex[i]; fd = open(filename, O_RDONLY | O_NONBLOCK); if (fd == -1) continue; ret = (fstat(fd, &sb)); if (ret == -1) goto closeout; if (sb.st_size == 0) sb.st_size = page_size; buffer = malloc(sb.st_size); if (!buffer) goto closeout; memset(buffer, 0, sb.st_size); ret = read(fd, buffer, sb.st_size); // if (ret != -1) // output(0, "%s:%s\n", filename, buffer); if (RAND_BOOL()) sleep(1); free(buffer); closeout: close(fd); } return TRUE; }
static int open_socket(unsigned int domain, unsigned int type, unsigned int protocol) { int fd; struct sockaddr *sa = NULL; socklen_t salen; struct sockopt so = { 0, 0, 0, 0 }; fd = socket(domain, type, protocol); if (fd == -1) return fd; shm->sockets[nr_sockets].fd = fd; shm->sockets[nr_sockets].triplet.family = domain; shm->sockets[nr_sockets].triplet.type = type; shm->sockets[nr_sockets].triplet.protocol = protocol; output(2, "fd[%i] = domain:%i (%s) type:0x%x protocol:%i\n", fd, domain, get_domain_name(domain), type, protocol); /* Set some random socket options. */ sso_socket(&shm->sockets[nr_sockets].triplet, &so, fd); nr_sockets++; /* Sometimes, listen on created sockets. */ if (RAND_BOOL()) { int ret; /* fake a sockaddr. */ generate_sockaddr((struct sockaddr **) &sa, (socklen_t *) &salen, domain); ret = bind(fd, sa, salen); if (ret != -1) { (void) listen(fd, RAND_RANGE(1, 128)); } } if (sa != NULL) free(sa); return fd; }
static void gen_random_ipv6_address(struct in6_addr *v6) { const char *p; /* 90% of the time, just do localhost */ if (!(ONE_IN(10))) { inet_pton(AF_INET6, "::1", v6); return; } if (RAND_BOOL()) { /* v4 in v6 somehow. */ in_addr_t v4; const struct addrtext v4_in_v6_addresses[] = { { "::" }, /* deprecated ipv4 style ::v4 */ { "::ffff:0:0" }, /* v4 in v6 ::ffff:0:0/96 */ { "::ffff:0:0:0" }, /* stateless IP/ICMP translation (SIIT) ::ffff:0:0:0/96 */ { "2002::" }, /* 2002::/16 "6to4" */ }; p = RAND_ELEMENT(v4_in_v6_addresses, name); inet_pton(AF_INET6, p, v6); v4 = random_ipv4_address(); v6->s6_addr32[3] = htonl(v4); } else { /* actual v6 addresses. */ const struct addrtext v6_addresses[] = { { "::" }, /* ::/128 unspecified */ { "fe80::" }, /* fe80::/10 link-local */ { "fc00::" }, /* fc00::/7 unique local address (ULA) */ { "64:ff9b::" }, /* 64:ff9b::/96 "Well known" prefix */ { "0100::" }, /* 0100::/64 remotely triggered blackhole */ }; p = RAND_ELEMENT(v6_addresses, name); inet_pton(AF_INET6, p, v6); } }
static void sanitise_send(struct syscallrecord *rec) { struct socketinfo *si = (struct socketinfo *) rec->a1; const struct netproto *proto; void *ptr; size_t size; rec->a1 = fd_from_socketinfo(si); if (si == NULL) // handle --disable-fds=sockets goto skip_si; proto = net_protocols[si->triplet.family].proto; if (proto != NULL) { if (proto->gen_packet != NULL) { ptr = &rec->a2; proto->gen_packet(&si->triplet, ptr, &rec->a3); // printf("Sending to family:%d type:%d proto:%d\n", // si->triplet.family, si->triplet.type, si->triplet.protocol); return; } } skip_si: /* The rest of this function is only used as a fallback, if the per-proto * send()'s aren't implemented. */ if (RAND_BOOL()) size = 1; else size = rnd() % page_size; ptr = malloc(size); rec->a2 = (unsigned long) ptr; if (ptr == NULL) return; rec->a3 = size; generate_rand_bytes(ptr, size); }