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