• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2020 SUSE LLC <mdoucha@suse.cz>
4  *
5  * CVE-2018-18559
6  *
7  * Test for race condition vulnerability in bind() on AF_PACKET socket.
8  * Fixed in:
9  *
10  *  commit 15fe076edea787807a7cdc168df832544b58eba6
11  *  Author: Eric Dumazet <edumazet@google.com>
12  *  Date:   Tue Nov 28 08:03:30 2017 -0800
13  *
14  *  net/packet: fix a race in packet_bind() and packet_notifier()
15  */
16 
17 #define _GNU_SOURCE
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
20 #include <linux/if_packet.h>
21 #include <net/ethernet.h>
22 #include <net/if.h>
23 #include <sched.h>
24 #include "tst_test.h"
25 #include "tst_fuzzy_sync.h"
26 
27 static volatile int fd = -1;
28 static struct sockaddr_ll addr1, addr2;
29 static struct tst_fzsync_pair fzsync_pair;
30 
setup(void)31 static void setup(void)
32 {
33 	int real_uid = getuid();
34 	int real_gid = getgid();
35 	struct ifreq ifr;
36 
37 	SAFE_TRY_FILE_PRINTF("/proc/sys/user/max_user_namespaces", "%d", 10);
38 
39 	SAFE_UNSHARE(CLONE_NEWUSER);
40 	SAFE_UNSHARE(CLONE_NEWNET);
41 	SAFE_FILE_PRINTF("/proc/self/setgroups", "deny");
42 	SAFE_FILE_PRINTF("/proc/self/uid_map", "0 %d 1\n", real_uid);
43 	SAFE_FILE_PRINTF("/proc/self/gid_map", "0 %d 1\n", real_gid);
44 
45 	fd = SAFE_SOCKET(AF_PACKET, SOCK_DGRAM, PF_PACKET);
46 	strcpy(ifr.ifr_name, "lo");
47 	SAFE_IOCTL(fd, SIOCGIFINDEX, &ifr);
48 	SAFE_CLOSE(fd);
49 
50 	addr1.sll_family = AF_PACKET;
51 	addr1.sll_ifindex = ifr.ifr_ifindex;
52 	addr2.sll_family = AF_PACKET;
53 
54 	fzsync_pair.exec_loops = 10000;
55 	tst_fzsync_pair_init(&fzsync_pair);
56 }
57 
cleanup(void)58 static void cleanup(void)
59 {
60 	tst_fzsync_pair_cleanup(&fzsync_pair);
61 }
62 
do_bind(void)63 static void do_bind(void)
64 {
65 	SAFE_BIND(fd, (struct sockaddr *)&addr1, sizeof(addr1));
66 	SAFE_BIND(fd, (struct sockaddr *)&addr2, sizeof(addr2));
67 }
68 
thread_run(void * arg)69 static void *thread_run(void *arg)
70 {
71 	while (tst_fzsync_run_b(&fzsync_pair)) {
72 		tst_fzsync_start_race_b(&fzsync_pair);
73 		do_bind();
74 		tst_fzsync_end_race_b(&fzsync_pair);
75 	}
76 
77 	return arg;
78 }
79 
run(void)80 static void run(void)
81 {
82 	struct ifreq ifr;
83 
84 	tst_fzsync_pair_reset(&fzsync_pair, thread_run);
85 	strcpy(ifr.ifr_name, "lo");
86 
87 	while (tst_fzsync_run_a(&fzsync_pair)) {
88 		fd = SAFE_SOCKET(AF_PACKET, SOCK_DGRAM, PF_PACKET);
89 		ifr.ifr_flags = 0;
90 		ioctl(fd, SIOCSIFFLAGS, &ifr);
91 		ifr.ifr_flags = IFF_UP;
92 		tst_fzsync_start_race_a(&fzsync_pair);
93 		ioctl(fd, SIOCSIFFLAGS, &ifr);
94 		tst_fzsync_end_race_a(&fzsync_pair);
95 		SAFE_CLOSE(fd);
96 	}
97 
98 	tst_res(TPASS, "Nothing bad happened (yet)");
99 }
100 
101 static struct tst_test test = {
102 	.test_all = run,
103 	.setup = setup,
104 	.cleanup = cleanup,
105 	.timeout = 600,
106 	.taint_check = TST_TAINT_W | TST_TAINT_D,
107 	.needs_kconfigs = (const char *[]) {
108 		"CONFIG_USER_NS=y",
109 		"CONFIG_NET_NS=y",
110 		NULL
111 	},
112 	.save_restore = (const char * const[]) {
113 		"?/proc/sys/user/max_user_namespaces",
114 		NULL,
115 	},
116 	.tags = (const struct tst_tag[]) {
117 		{"linux-git", "15fe076edea7"},
118 		{"CVE", "2018-18559"},
119 		{}
120 	}
121 };
122