• 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 
6 /*\
7  * [Description]
8  *
9  * CVE-2016-8655
10  *
11  * Check for race condition between packet_set_ring() and tp_version. On some
12  * kernels, this may lead to use-after-free.
13  *
14  * Kernel crash fixed in 4.9
15  * 84ac7260236a ("packet: fix race condition in packet_set_ring")
16  */
17 
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 
22 #include "tst_test.h"
23 #include "tst_fuzzy_sync.h"
24 #include "lapi/if_packet.h"
25 #include "lapi/if_ether.h"
26 
27 static int sock = -1;
28 static unsigned int pagesize;
29 static struct tst_fzsync_pair fzsync_pair;
30 
setup(void)31 static void setup(void)
32 {
33 	pagesize = SAFE_SYSCONF(_SC_PAGESIZE);
34 	tst_setup_netns();
35 
36 	fzsync_pair.exec_loops = 100000;
37 	tst_fzsync_pair_init(&fzsync_pair);
38 }
39 
thread_run(void * arg)40 static void *thread_run(void *arg)
41 {
42 	int ret;
43 	struct tpacket_req3 req = {
44 		.tp_block_size = pagesize,
45 		.tp_block_nr = 1,
46 		.tp_frame_size = pagesize,
47 		.tp_frame_nr = 1,
48 		.tp_retire_blk_tov = 100
49 	};
50 
51 	while (tst_fzsync_run_b(&fzsync_pair)) {
52 		tst_fzsync_start_race_b(&fzsync_pair);
53 		ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &req,
54 			sizeof(req));
55 		tst_fzsync_end_race_b(&fzsync_pair);
56 
57 		if (!ret)
58 			tst_fzsync_pair_add_bias(&fzsync_pair, -10);
59 	}
60 
61 	return arg;
62 }
63 
run(void)64 static void run(void)
65 {
66 	int val1 = TPACKET_V1, val3 = TPACKET_V3;
67 
68 	tst_fzsync_pair_reset(&fzsync_pair, thread_run);
69 
70 	while (tst_fzsync_run_a(&fzsync_pair)) {
71 		sock = SAFE_SOCKET(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
72 		TEST(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val3,
73 			sizeof(val3)));
74 
75 		if (TST_RET == -1 && TST_ERR == EINVAL)
76 			tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported");
77 
78 		if (TST_RET) {
79 			tst_brk(TBROK | TTERRNO,
80 				"setsockopt(PACKET_VERSION, TPACKET_V3");
81 		}
82 
83 		tst_fzsync_start_race_a(&fzsync_pair);
84 		setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val1,
85 			sizeof(val1));
86 		tst_fzsync_end_race_a(&fzsync_pair);
87 		SAFE_CLOSE(sock);
88 	}
89 
90 	/* setsockopt(PACKET_RX_RING) created a 100ms timer. Wait for it. */
91 	usleep(300000);
92 
93 	if (tst_taint_check()) {
94 		tst_res(TFAIL, "Kernel is vulnerable");
95 		return;
96 	}
97 
98 	tst_res(TPASS, "Nothing bad happened, probably");
99 }
100 
cleanup(void)101 static void cleanup(void)
102 {
103 	tst_fzsync_pair_cleanup(&fzsync_pair);
104 
105 	if (sock >= 0)
106 		SAFE_CLOSE(sock);
107 }
108 
109 static struct tst_test test = {
110 	.test_all = run,
111 	.setup = setup,
112 	.cleanup = cleanup,
113 	.runtime = 270,
114 	.taint_check = TST_TAINT_W | TST_TAINT_D,
115 	.needs_kconfigs = (const char *[]) {
116 		"CONFIG_USER_NS=y",
117 		"CONFIG_NET_NS=y",
118 		NULL
119 	},
120 	.save_restore = (const struct tst_path_val[]) {
121 		{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
122 		{}
123 	},
124 	.tags = (const struct tst_tag[]) {
125 		{"linux-git", "84ac7260236a"},
126 		{"CVE", "2016-8655"},
127 		{}
128 	}
129 };
130