1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 SUSE LLC <[email protected]>
4 */
5
6 /*
7 * CVE-2017-1000112
8 *
9 * Check that UDP fragmentation offload doesn't cause memory corruption
10 * if the userspace process turns off UFO in between two send() calls.
11 * Kernel crash fixed in:
12 *
13 * commit 85f1bd9a7b5a79d5baa8bf44af19658f7bf77bfa
14 * Author: Willem de Bruijn <[email protected]>
15 * Date: Thu Aug 10 12:29:19 2017 -0400
16 *
17 * udp: consistently apply ufo or fragmentation
18 */
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <sys/ioctl.h>
24 #include <net/if.h>
25
26 #include "tst_test.h"
27 #include "tst_net.h"
28
29 #define BUFSIZE 4000
30
31 static struct sockaddr_in addr;
32 static int dst_sock = -1;
33
setup(void)34 static void setup(void)
35 {
36 struct ifreq ifr;
37 socklen_t addrlen = sizeof(addr);
38
39 tst_setup_netns();
40
41 tst_init_sockaddr_inet_bin(&addr, INADDR_LOOPBACK, 0);
42 dst_sock = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
43
44 strcpy(ifr.ifr_name, "lo");
45 ifr.ifr_mtu = 1500;
46 SAFE_IOCTL(dst_sock, SIOCSIFMTU, &ifr);
47 ifr.ifr_flags = IFF_UP;
48 SAFE_IOCTL(dst_sock, SIOCSIFFLAGS, &ifr);
49
50 SAFE_BIND(dst_sock, (struct sockaddr *)&addr, addrlen);
51 SAFE_GETSOCKNAME(dst_sock, (struct sockaddr*)&addr, &addrlen);
52 }
53
cleanup(void)54 static void cleanup(void)
55 {
56 if (dst_sock != -1)
57 SAFE_CLOSE(dst_sock);
58 }
59
run(void)60 static void run(void)
61 {
62 int sock, i;
63 char buf[BUFSIZE];
64
65 memset(buf, 0x42, BUFSIZE);
66
67 for (i = 0; i < 1000; i++) {
68 sock = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
69 SAFE_CONNECT(sock, (struct sockaddr *)&addr, sizeof(addr));
70 SAFE_SEND(1, sock, buf, BUFSIZE, MSG_MORE);
71 SAFE_SETSOCKOPT_INT(sock, SOL_SOCKET, SO_NO_CHECK, 1);
72 send(sock, buf, 1, 0);
73 SAFE_CLOSE(sock);
74
75 if (tst_taint_check()) {
76 tst_res(TFAIL, "Kernel is vulnerable");
77 return;
78 }
79 }
80
81 tst_res(TPASS, "Nothing bad happened, probably");
82 }
83
84 static struct tst_test test = {
85 .test_all = run,
86 .setup = setup,
87 .cleanup = cleanup,
88 .taint_check = TST_TAINT_W | TST_TAINT_D,
89 .needs_kconfigs = (const char *[]) {
90 "CONFIG_USER_NS=y",
91 "CONFIG_NET_NS=y",
92 NULL
93 },
94 .save_restore = (const struct tst_path_val[]) {
95 {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
96 {}
97 },
98 .tags = (const struct tst_tag[]) {
99 {"linux-git", "85f1bd9a7b5a"},
100 {"CVE", "2017-1000112"},
101 {}
102 }
103 };
104