hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/arch/um/drivers/vector_user.c
....@@ -1,6 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3
- * Licensed under the GPL
44 */
55
66 #include <stdio.h>
....@@ -16,36 +16,46 @@
1616 #include <sys/types.h>
1717 #include <sys/stat.h>
1818 #include <fcntl.h>
19
-#include <sys/types.h>
2019 #include <sys/socket.h>
21
-#include <net/ethernet.h>
20
+#include <sys/un.h>
2221 #include <netinet/ip.h>
23
-#include <netinet/ether.h>
2422 #include <linux/if_ether.h>
2523 #include <linux/if_packet.h>
26
-#include <sys/socket.h>
2724 #include <sys/wait.h>
25
+#include <sys/uio.h>
2826 #include <linux/virtio_net.h>
2927 #include <netdb.h>
3028 #include <stdlib.h>
3129 #include <os.h>
30
+#include <limits.h>
3231 #include <um_malloc.h>
33
-#include <sys/uio.h>
3432 #include "vector_user.h"
3533
3634 #define ID_GRE 0
3735 #define ID_L2TPV3 1
38
-#define ID_MAX 1
36
+#define ID_BESS 2
37
+#define ID_MAX 2
3938
4039 #define TOKEN_IFNAME "ifname"
40
+#define TOKEN_SCRIPT "ifup"
4141
4242 #define TRANS_RAW "raw"
4343 #define TRANS_RAW_LEN strlen(TRANS_RAW)
4444
45
+#define TRANS_FD "fd"
46
+#define TRANS_FD_LEN strlen(TRANS_FD)
47
+
4548 #define VNET_HDR_FAIL "could not enable vnet headers on fd %d"
4649 #define TUN_GET_F_FAIL "tapraw: TUNGETFEATURES failed: %s"
4750 #define L2TPV3_BIND_FAIL "l2tpv3_open : could not bind socket err=%i"
48
-#define BPF_ATTACH_FAIL "Failed to attach filter size %d to %d, err %d\n"
51
+#define UNIX_BIND_FAIL "unix_open : could not bind socket err=%i"
52
+#define BPF_ATTACH_FAIL "Failed to attach filter size %d prog %px to %d, err %d\n"
53
+#define BPF_DETACH_FAIL "Failed to detach filter size %d prog %px to %d, err %d\n"
54
+
55
+#define MAX_UN_LEN 107
56
+
57
+static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
58
+static const char *template = "tapXXXXXX";
4959
5060 /* This is very ugly and brute force lookup, but it is done
5161 * only once at initialization so not worth doing hashes or
....@@ -116,19 +126,88 @@
116126
117127 #define PATH_NET_TUN "/dev/net/tun"
118128
119
-static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
129
+
130
+static int create_tap_fd(char *iface)
131
+{
132
+ struct ifreq ifr;
133
+ int fd = -1;
134
+ int err = -ENOMEM, offload;
135
+
136
+ fd = open(PATH_NET_TUN, O_RDWR);
137
+ if (fd < 0) {
138
+ printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
139
+ goto tap_fd_cleanup;
140
+ }
141
+ memset(&ifr, 0, sizeof(ifr));
142
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
143
+ strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
144
+
145
+ err = ioctl(fd, TUNSETIFF, (void *) &ifr);
146
+ if (err != 0) {
147
+ printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
148
+ goto tap_fd_cleanup;
149
+ }
150
+
151
+ offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
152
+ ioctl(fd, TUNSETOFFLOAD, offload);
153
+ return fd;
154
+tap_fd_cleanup:
155
+ if (fd >= 0)
156
+ os_close_file(fd);
157
+ return err;
158
+}
159
+
160
+static int create_raw_fd(char *iface, int flags, int proto)
120161 {
121162 struct ifreq ifr;
122163 int fd = -1;
123164 struct sockaddr_ll sock;
124
- int err = -ENOMEM, offload;
165
+ int err = -ENOMEM;
166
+
167
+ fd = socket(AF_PACKET, SOCK_RAW, flags);
168
+ if (fd == -1) {
169
+ err = -errno;
170
+ goto raw_fd_cleanup;
171
+ }
172
+ memset(&ifr, 0, sizeof(ifr));
173
+ strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
174
+ if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
175
+ err = -errno;
176
+ goto raw_fd_cleanup;
177
+ }
178
+
179
+ sock.sll_family = AF_PACKET;
180
+ sock.sll_protocol = htons(proto);
181
+ sock.sll_ifindex = ifr.ifr_ifindex;
182
+
183
+ if (bind(fd,
184
+ (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
185
+ err = -errno;
186
+ goto raw_fd_cleanup;
187
+ }
188
+ return fd;
189
+raw_fd_cleanup:
190
+ printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
191
+ if (fd >= 0)
192
+ os_close_file(fd);
193
+ return err;
194
+}
195
+
196
+
197
+static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
198
+{
199
+ int fd = -1, i;
125200 char *iface;
126201 struct vector_fds *result = NULL;
202
+ bool dynamic = false;
203
+ char dynamic_ifname[IFNAMSIZ];
204
+ char *argv[] = {NULL, NULL, NULL, NULL};
127205
128206 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
129207 if (iface == NULL) {
130
- printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n");
131
- goto tap_cleanup;
208
+ dynamic = true;
209
+ iface = dynamic_ifname;
210
+ srand(getpid());
132211 }
133212
134213 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
....@@ -142,118 +221,240 @@
142221 result->remote_addr_size = 0;
143222
144223 /* TAP */
224
+ do {
225
+ if (dynamic) {
226
+ strcpy(iface, template);
227
+ for (i = 0; i < strlen(iface); i++) {
228
+ if (iface[i] == 'X') {
229
+ iface[i] = padchar[rand() % strlen(padchar)];
230
+ }
231
+ }
232
+ }
233
+ fd = create_tap_fd(iface);
234
+ if ((fd < 0) && (!dynamic)) {
235
+ printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n");
236
+ goto tap_cleanup;
237
+ }
238
+ result->tx_fd = fd;
239
+ result->rx_fd = fd;
240
+ } while (fd < 0);
145241
146
- fd = open(PATH_NET_TUN, O_RDWR);
147
- if (fd < 0) {
148
- printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
149
- goto tap_cleanup;
150
- }
151
- result->tx_fd = fd;
152
- memset(&ifr, 0, sizeof(ifr));
153
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
154
- strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
155
-
156
- err = ioctl(fd, TUNSETIFF, (void *) &ifr);
157
- if (err != 0) {
158
- printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
159
- goto tap_cleanup;
242
+ argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT);
243
+ if (argv[0]) {
244
+ argv[1] = iface;
245
+ run_helper(NULL, NULL, argv);
160246 }
161247
162
- offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
163
- ioctl(fd, TUNSETOFFLOAD, offload);
164
-
165
- /* RAW */
166
-
167
- fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
168
- if (fd == -1) {
169
- printk(UM_KERN_ERR
170
- "uml_tap: failed to create socket: %i\n", -errno);
171
- goto tap_cleanup;
172
- }
173
- result->rx_fd = fd;
174
- memset(&ifr, 0, sizeof(ifr));
175
- strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
176
- if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
177
- printk(UM_KERN_ERR
178
- "uml_tap: failed to set interface: %i\n", -errno);
179
- goto tap_cleanup;
180
- }
181
-
182
- sock.sll_family = AF_PACKET;
183
- sock.sll_protocol = htons(ETH_P_ALL);
184
- sock.sll_ifindex = ifr.ifr_ifindex;
185
-
186
- if (bind(fd,
187
- (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
188
- printk(UM_KERN_ERR
189
- "user_init_tap: failed to bind raw pair, err %d\n",
190
- -errno);
191
- goto tap_cleanup;
192
- }
193248 return result;
194249 tap_cleanup:
195
- printk(UM_KERN_ERR "user_init_tap: init failed, error %d", err);
196
- if (result != NULL) {
197
- if (result->rx_fd >= 0)
198
- os_close_file(result->rx_fd);
199
- if (result->tx_fd >= 0)
200
- os_close_file(result->tx_fd);
201
- kfree(result);
202
- }
250
+ printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd);
251
+ kfree(result);
203252 return NULL;
204253 }
205254
255
+static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
256
+{
257
+ char *iface;
258
+ struct vector_fds *result = NULL;
259
+ char *argv[] = {NULL, NULL, NULL, NULL};
260
+
261
+ iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
262
+ if (iface == NULL) {
263
+ printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n");
264
+ goto hybrid_cleanup;
265
+ }
266
+
267
+ result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
268
+ if (result == NULL) {
269
+ printk(UM_KERN_ERR "uml_tap: failed to allocate file descriptors\n");
270
+ goto hybrid_cleanup;
271
+ }
272
+ result->rx_fd = -1;
273
+ result->tx_fd = -1;
274
+ result->remote_addr = NULL;
275
+ result->remote_addr_size = 0;
276
+
277
+ /* TAP */
278
+
279
+ result->tx_fd = create_tap_fd(iface);
280
+ if (result->tx_fd < 0) {
281
+ printk(UM_KERN_ERR "uml_tap: failed to create tun interface: %i\n", result->tx_fd);
282
+ goto hybrid_cleanup;
283
+ }
284
+
285
+ /* RAW */
286
+
287
+ result->rx_fd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
288
+ if (result->rx_fd == -1) {
289
+ printk(UM_KERN_ERR
290
+ "uml_tap: failed to create paired raw socket: %i\n", result->rx_fd);
291
+ goto hybrid_cleanup;
292
+ }
293
+
294
+ argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT);
295
+ if (argv[0]) {
296
+ argv[1] = iface;
297
+ run_helper(NULL, NULL, argv);
298
+ }
299
+ return result;
300
+hybrid_cleanup:
301
+ printk(UM_KERN_ERR "user_init_hybrid: init failed");
302
+ kfree(result);
303
+ return NULL;
304
+}
305
+
306
+static struct vector_fds *user_init_unix_fds(struct arglist *ifspec, int id)
307
+{
308
+ int fd = -1;
309
+ int socktype;
310
+ char *src, *dst;
311
+ struct vector_fds *result = NULL;
312
+ struct sockaddr_un *local_addr = NULL, *remote_addr = NULL;
313
+
314
+ src = uml_vector_fetch_arg(ifspec, "src");
315
+ dst = uml_vector_fetch_arg(ifspec, "dst");
316
+ result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
317
+ if (result == NULL) {
318
+ printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
319
+ goto unix_cleanup;
320
+ }
321
+ remote_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
322
+ if (remote_addr == NULL) {
323
+ printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
324
+ goto unix_cleanup;
325
+ }
326
+
327
+ switch (id) {
328
+ case ID_BESS:
329
+ socktype = SOCK_SEQPACKET;
330
+ if ((src != NULL) && (strlen(src) <= MAX_UN_LEN)) {
331
+ local_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
332
+ if (local_addr == NULL) {
333
+ printk(UM_KERN_ERR "bess open:cannot allocate local addr");
334
+ goto unix_cleanup;
335
+ }
336
+ local_addr->sun_family = AF_UNIX;
337
+ memcpy(local_addr->sun_path, src, strlen(src) + 1);
338
+ }
339
+ if ((dst == NULL) || (strlen(dst) > MAX_UN_LEN))
340
+ goto unix_cleanup;
341
+ remote_addr->sun_family = AF_UNIX;
342
+ memcpy(remote_addr->sun_path, dst, strlen(dst) + 1);
343
+ break;
344
+ default:
345
+ printk(KERN_ERR "Unsupported unix socket type\n");
346
+ return NULL;
347
+ }
348
+
349
+ fd = socket(AF_UNIX, socktype, 0);
350
+ if (fd == -1) {
351
+ printk(UM_KERN_ERR
352
+ "unix open: could not open socket, error = %d",
353
+ -errno
354
+ );
355
+ goto unix_cleanup;
356
+ }
357
+ if (local_addr != NULL) {
358
+ if (bind(fd, (struct sockaddr *) local_addr, sizeof(struct sockaddr_un))) {
359
+ printk(UM_KERN_ERR UNIX_BIND_FAIL, errno);
360
+ goto unix_cleanup;
361
+ }
362
+ }
363
+ switch (id) {
364
+ case ID_BESS:
365
+ if (connect(fd, (const struct sockaddr *) remote_addr, sizeof(struct sockaddr_un)) < 0) {
366
+ printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno);
367
+ goto unix_cleanup;
368
+ }
369
+ break;
370
+ }
371
+ result->rx_fd = fd;
372
+ result->tx_fd = fd;
373
+ result->remote_addr_size = sizeof(struct sockaddr_un);
374
+ result->remote_addr = remote_addr;
375
+ return result;
376
+unix_cleanup:
377
+ if (fd >= 0)
378
+ os_close_file(fd);
379
+ kfree(remote_addr);
380
+ kfree(result);
381
+ return NULL;
382
+}
383
+
384
+static int strtofd(const char *nptr)
385
+{
386
+ long fd;
387
+ char *endptr;
388
+
389
+ if (nptr == NULL)
390
+ return -1;
391
+
392
+ errno = 0;
393
+ fd = strtol(nptr, &endptr, 10);
394
+ if (nptr == endptr ||
395
+ errno != 0 ||
396
+ *endptr != '\0' ||
397
+ fd < 0 ||
398
+ fd > INT_MAX) {
399
+ return -1;
400
+ }
401
+ return fd;
402
+}
403
+
404
+static struct vector_fds *user_init_fd_fds(struct arglist *ifspec)
405
+{
406
+ int fd = -1;
407
+ char *fdarg = NULL;
408
+ struct vector_fds *result = NULL;
409
+
410
+ fdarg = uml_vector_fetch_arg(ifspec, "fd");
411
+ fd = strtofd(fdarg);
412
+ if (fd == -1) {
413
+ printk(UM_KERN_ERR "fd open: bad or missing fd argument");
414
+ goto fd_cleanup;
415
+ }
416
+
417
+ result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
418
+ if (result == NULL) {
419
+ printk(UM_KERN_ERR "fd open: allocation failed");
420
+ goto fd_cleanup;
421
+ }
422
+
423
+ result->rx_fd = fd;
424
+ result->tx_fd = fd;
425
+ result->remote_addr_size = 0;
426
+ result->remote_addr = NULL;
427
+ return result;
428
+
429
+fd_cleanup:
430
+ if (fd >= 0)
431
+ os_close_file(fd);
432
+ kfree(result);
433
+ return NULL;
434
+}
206435
207436 static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
208437 {
209
- struct ifreq ifr;
210438 int rxfd = -1, txfd = -1;
211
- struct sockaddr_ll sock;
212439 int err = -ENOMEM;
213440 char *iface;
214441 struct vector_fds *result = NULL;
442
+ char *argv[] = {NULL, NULL, NULL, NULL};
215443
216444 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
217445 if (iface == NULL)
218
- goto cleanup;
446
+ goto raw_cleanup;
219447
220
- rxfd = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
448
+ rxfd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
221449 if (rxfd == -1) {
222450 err = -errno;
223
- goto cleanup;
451
+ goto raw_cleanup;
224452 }
225
- txfd = socket(AF_PACKET, SOCK_RAW, 0); /* Turn off RX on this fd */
453
+ txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */
226454 if (txfd == -1) {
227455 err = -errno;
228
- goto cleanup;
456
+ goto raw_cleanup;
229457 }
230
- memset(&ifr, 0, sizeof(ifr));
231
- strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
232
- if (ioctl(rxfd, SIOCGIFINDEX, (void *) &ifr) < 0) {
233
- err = -errno;
234
- goto cleanup;
235
- }
236
-
237
- sock.sll_family = AF_PACKET;
238
- sock.sll_protocol = htons(ETH_P_ALL);
239
- sock.sll_ifindex = ifr.ifr_ifindex;
240
-
241
- if (bind(rxfd,
242
- (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
243
- err = -errno;
244
- goto cleanup;
245
- }
246
-
247
- sock.sll_family = AF_PACKET;
248
- sock.sll_protocol = htons(ETH_P_IP);
249
- sock.sll_ifindex = ifr.ifr_ifindex;
250
-
251
- if (bind(txfd,
252
- (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
253
- err = -errno;
254
- goto cleanup;
255
- }
256
-
257458 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
258459 if (result != NULL) {
259460 result->rx_fd = rxfd;
....@@ -261,15 +462,15 @@
261462 result->remote_addr = NULL;
262463 result->remote_addr_size = 0;
263464 }
465
+ argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT);
466
+ if (argv[0]) {
467
+ argv[1] = iface;
468
+ run_helper(NULL, NULL, argv);
469
+ }
264470 return result;
265
-cleanup:
471
+raw_cleanup:
266472 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
267
- if (rxfd >= 0)
268
- os_close_file(rxfd);
269
- if (txfd >= 0)
270
- os_close_file(txfd);
271
- if (result != NULL)
272
- kfree(result);
473
+ kfree(result);
273474 return NULL;
274475 }
275476
....@@ -435,8 +636,7 @@
435636 if (fd >= 0)
436637 os_close_file(fd);
437638 if (result != NULL) {
438
- if (result->remote_addr != NULL)
439
- kfree(result->remote_addr);
639
+ kfree(result->remote_addr);
440640 kfree(result);
441641 }
442642 return NULL;
....@@ -460,12 +660,18 @@
460660 }
461661 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
462662 return user_init_raw_fds(parsed);
663
+ if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
664
+ return user_init_hybrid_fds(parsed);
463665 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
464666 return user_init_tap_fds(parsed);
465667 if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0)
466668 return user_init_socket_fds(parsed, ID_GRE);
467669 if (strncmp(transport, TRANS_L2TPV3, TRANS_L2TPV3_LEN) == 0)
468670 return user_init_socket_fds(parsed, ID_L2TPV3);
671
+ if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0)
672
+ return user_init_unix_fds(parsed, ID_BESS);
673
+ if (strncmp(transport, TRANS_FD, TRANS_FD_LEN) == 0)
674
+ return user_init_fd_fds(parsed);
469675 return NULL;
470676 }
471677
....@@ -486,8 +692,9 @@
486692 int uml_vector_recvmsg(int fd, void *hdr, int flags)
487693 {
488694 int n;
695
+ struct msghdr *msg = (struct msghdr *) hdr;
489696
490
- CATCH_EINTR(n = recvmsg(fd, (struct msghdr *) hdr, flags));
697
+ CATCH_EINTR(n = readv(fd, msg->msg_iov, msg->msg_iovlen));
491698 if ((n < 0) && (errno == EAGAIN))
492699 return 0;
493700 if (n >= 0)
....@@ -501,7 +708,7 @@
501708 int n;
502709
503710 CATCH_EINTR(n = writev(fd, (struct iovec *) hdr, iovcount));
504
- if ((n < 0) && (errno == EAGAIN))
711
+ if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
505712 return 0;
506713 if (n >= 0)
507714 return n;
....@@ -518,7 +725,7 @@
518725 int n;
519726
520727 CATCH_EINTR(n = sendmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags));
521
- if ((n < 0) && (errno == EAGAIN))
728
+ if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
522729 return 0;
523730 if (n >= 0)
524731 return n;
....@@ -543,31 +750,44 @@
543750 else
544751 return -errno;
545752 }
546
-int uml_vector_attach_bpf(int fd, void *bpf, int bpf_len)
753
+int uml_vector_attach_bpf(int fd, void *bpf)
547754 {
548
- int err = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, bpf, bpf_len);
755
+ struct sock_fprog *prog = bpf;
756
+
757
+ int err = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, bpf, sizeof(struct sock_fprog));
549758
550759 if (err < 0)
551
- printk(KERN_ERR BPF_ATTACH_FAIL, bpf_len, fd, -errno);
760
+ printk(KERN_ERR BPF_ATTACH_FAIL, prog->len, prog->filter, fd, -errno);
552761 return err;
553762 }
554763
555
-#define DEFAULT_BPF_LEN 6
764
+int uml_vector_detach_bpf(int fd, void *bpf)
765
+{
766
+ struct sock_fprog *prog = bpf;
556767
557
-void *uml_vector_default_bpf(int fd, void *mac)
768
+ int err = setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, bpf, sizeof(struct sock_fprog));
769
+ if (err < 0)
770
+ printk(KERN_ERR BPF_DETACH_FAIL, prog->len, prog->filter, fd, -errno);
771
+ return err;
772
+}
773
+void *uml_vector_default_bpf(void *mac)
558774 {
559775 struct sock_filter *bpf;
560776 uint32_t *mac1 = (uint32_t *)(mac + 2);
561777 uint16_t *mac2 = (uint16_t *) mac;
562
- struct sock_fprog bpf_prog = {
563
- .len = 6,
564
- .filter = NULL,
565
- };
778
+ struct sock_fprog *bpf_prog;
566779
780
+ bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
781
+ if (bpf_prog) {
782
+ bpf_prog->len = DEFAULT_BPF_LEN;
783
+ bpf_prog->filter = NULL;
784
+ } else {
785
+ return NULL;
786
+ }
567787 bpf = uml_kmalloc(
568788 sizeof(struct sock_filter) * DEFAULT_BPF_LEN, UM_GFP_KERNEL);
569
- if (bpf != NULL) {
570
- bpf_prog.filter = bpf;
789
+ if (bpf) {
790
+ bpf_prog->filter = bpf;
571791 /* ld [8] */
572792 bpf[0] = (struct sock_filter){ 0x20, 0, 0, 0x00000008 };
573793 /* jeq #0xMAC[2-6] jt 2 jf 5*/
....@@ -580,12 +800,58 @@
580800 bpf[4] = (struct sock_filter){ 0x6, 0, 0, 0x00000000 };
581801 /* ret #0x40000 */
582802 bpf[5] = (struct sock_filter){ 0x6, 0, 0, 0x00040000 };
583
- if (uml_vector_attach_bpf(
584
- fd, &bpf_prog, sizeof(struct sock_fprog)) < 0) {
585
- kfree(bpf);
586
- bpf = NULL;
587
- }
803
+ } else {
804
+ kfree(bpf_prog);
805
+ bpf_prog = NULL;
588806 }
589
- return bpf;
807
+ return bpf_prog;
590808 }
591809
810
+/* Note - this function requires a valid mac being passed as an arg */
811
+
812
+void *uml_vector_user_bpf(char *filename)
813
+{
814
+ struct sock_filter *bpf;
815
+ struct sock_fprog *bpf_prog;
816
+ struct stat statbuf;
817
+ int res, ffd = -1;
818
+
819
+ if (filename == NULL)
820
+ return NULL;
821
+
822
+ if (stat(filename, &statbuf) < 0) {
823
+ printk(KERN_ERR "Error %d reading bpf file", -errno);
824
+ return false;
825
+ }
826
+ bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
827
+ if (bpf_prog == NULL) {
828
+ printk(KERN_ERR "Failed to allocate bpf prog buffer");
829
+ return NULL;
830
+ }
831
+ bpf_prog->len = statbuf.st_size / sizeof(struct sock_filter);
832
+ bpf_prog->filter = NULL;
833
+ ffd = os_open_file(filename, of_read(OPENFLAGS()), 0);
834
+ if (ffd < 0) {
835
+ printk(KERN_ERR "Error %d opening bpf file", -errno);
836
+ goto bpf_failed;
837
+ }
838
+ bpf = uml_kmalloc(statbuf.st_size, UM_GFP_KERNEL);
839
+ if (bpf == NULL) {
840
+ printk(KERN_ERR "Failed to allocate bpf buffer");
841
+ goto bpf_failed;
842
+ }
843
+ bpf_prog->filter = bpf;
844
+ res = os_read_file(ffd, bpf, statbuf.st_size);
845
+ if (res < statbuf.st_size) {
846
+ printk(KERN_ERR "Failed to read bpf program %s, error %d", filename, res);
847
+ kfree(bpf);
848
+ goto bpf_failed;
849
+ }
850
+ os_close_file(ffd);
851
+ return bpf_prog;
852
+bpf_failed:
853
+ if (ffd > 0)
854
+ os_close_file(ffd);
855
+ kfree(bpf_prog);
856
+ return NULL;
857
+}