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