move_pages: just use calloc
[trinity.git] / syscalls / setsockopt.c
blob37def307a74d5f296be1345c748104313790c09e
1 /*
2 * SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, char __user *, optval, int, optlen)
3 */
5 #include <errno.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <linux/types.h>
11 #include "sanitise.h"
12 #include "compat.h"
13 #include "maps.h"
14 #include "log.h"
15 #include "shm.h"
16 #include "net.h"
17 #include "config.h"
18 #include "random.h"
19 #include "utils.h"
21 struct sso_funcptr {
22 void (*func)(struct sockopt *so);
25 static const struct sso_funcptr ssoptrs[] = {
26 { .func = &ip_setsockopt },
27 { .func = &socket_setsockopt },
28 { .func = &tcp_setsockopt },
29 { .func = &udp_setsockopt },
30 { .func = &inet6_setsockopt },
31 { .func = &icmpv6_setsockopt },
32 { .func = &sctp_setsockopt },
33 { .func = &udplite_setsockopt },
34 { .func = &raw_setsockopt },
35 { .func = &ipx_setsockopt },
36 { .func = &ax25_setsockopt },
37 { .func = &atalk_setsockopt },
38 { .func = &netrom_setsockopt },
39 { .func = &rose_setsockopt },
40 { .func = &decnet_setsockopt },
41 { .func = &x25_setsockopt },
42 { .func = &packet_setsockopt },
43 { .func = &atm_setsockopt },
44 { .func = &aal_setsockopt },
45 { .func = &irda_setsockopt },
46 { .func = &netbeui_setsockopt },
47 { .func = &llc_setsockopt },
48 { .func = &dccp_setsockopt },
49 { .func = &netlink_setsockopt },
50 { .func = &tipc_setsockopt },
51 { .func = &rxrpc_setsockopt },
52 { .func = &pppol2tp_setsockopt },
53 { .func = &bluetooth_setsockopt },
54 { .func = &pnpipe_setsockopt },
55 { .func = &rds_setsockopt },
56 { .func = &iucv_setsockopt },
57 { .func = &caif_setsockopt },
58 { .func = &alg_setsockopt },
59 { .func = &nfc_setsockopt },
63 * Call a proto specific setsockopt routine from the table above.
65 static void do_setsockopt(struct sockopt *so)
67 so->optval = (unsigned long) get_non_null_address();
69 // pick a size for optlen. At the minimum, we want an int (overridden below)
70 if (rand_bool())
71 so->optlen = sizeof(int);
72 else
73 so->optlen = rand() % 256;
75 if (rand() % 100 > 0) {
76 ssoptrs[rand() % ARRAY_SIZE(ssoptrs)].func(so);
77 } else {
78 so->level = rand();
79 so->optname = (rand() % 0x100); /* random operation. */
83 * 10% of the time, mangle the options.
84 * This should catch new options we don't know about, and also maybe some missing bounds checks.
86 if ((rand() % 100) < 10)
87 so->optname |= (1 << (rand() % 32));
89 /* optval should be nonzero to enable a boolean option, or zero if the option is to be disabled.
90 * Let's disable it half the time.
92 if (rand_bool())
93 so->optval = 0;
97 * This is called during socket creation at startup, on each socket,
98 * and also periodically from regenerate()
100 void sso_socket(struct socket_triplet *triplet, struct sockopt *so, int fd)
102 int ret;
103 unsigned int tries = 0;
105 /* skip over bluetooth due to weird linger bug */
106 if (triplet->family == PF_BLUETOOTH)
107 return;
109 retry:
110 do_setsockopt(so);
112 ret = setsockopt(fd, so->level, so->optname, (void *)so->optval, so->optlen);
113 if (ret == 0) {
114 output(2, "Setsockopt(%lx %lx %lx %lx) on fd %d [%d:%d:%d]\n",
115 so->level, so->optname, so->optval, so->optlen, fd,
116 triplet->family, triplet->type, triplet->protocol);
117 } else {
118 tries++;
119 if (tries == 100) {
120 return;
122 goto retry;
126 static void sanitise_setsockopt(int childno)
128 struct sockopt so = { 0, 0, 0, 0 };
130 do_setsockopt(&so);
132 /* copy the generated values to the shm. */
133 shm->syscall[childno].a2 = so.level;
134 shm->syscall[childno].a3 = so.optname;
135 shm->syscall[childno].a4 = so.optval;
136 shm->syscall[childno].a5 = so.optlen;
139 struct syscallentry syscall_setsockopt = {
140 .name = "setsockopt",
141 .num_args = 5,
142 .arg1name = "fd",
143 .arg1type = ARG_FD,
144 .arg2name = "level",
145 .arg3name = "optname",
146 .arg4name = "optval",
147 .arg4type = ARG_ADDRESS,
148 .arg5name = "optlen",
149 .sanitise = sanitise_setsockopt,
150 .flags = NEED_ALARM,