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 * CVE-2018-18559
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci * Test for race condition vulnerability in bind() on AF_PACKET socket.
8f08c3bdfSopenharmony_ci * Fixed in:
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *  commit 15fe076edea787807a7cdc168df832544b58eba6
11f08c3bdfSopenharmony_ci *  Author: Eric Dumazet <edumazet@google.com>
12f08c3bdfSopenharmony_ci *  Date:   Tue Nov 28 08:03:30 2017 -0800
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci *  net/packet: fix a race in packet_bind() and packet_notifier()
15f08c3bdfSopenharmony_ci */
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#include <sys/socket.h>
18f08c3bdfSopenharmony_ci#include <sys/ioctl.h>
19f08c3bdfSopenharmony_ci#include <linux/if_packet.h>
20f08c3bdfSopenharmony_ci#include <net/ethernet.h>
21f08c3bdfSopenharmony_ci#include <net/if.h>
22f08c3bdfSopenharmony_ci#include "tst_test.h"
23f08c3bdfSopenharmony_ci#include "tst_fuzzy_sync.h"
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_cistatic volatile int fd = -1;
26f08c3bdfSopenharmony_cistatic struct sockaddr_ll addr1, addr2;
27f08c3bdfSopenharmony_cistatic struct tst_fzsync_pair fzsync_pair;
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_cistatic void setup(void)
30f08c3bdfSopenharmony_ci{
31f08c3bdfSopenharmony_ci	struct ifreq ifr;
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci	tst_setup_netns();
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci	fd = SAFE_SOCKET(AF_PACKET, SOCK_DGRAM, PF_PACKET);
36f08c3bdfSopenharmony_ci	strcpy(ifr.ifr_name, "lo");
37f08c3bdfSopenharmony_ci	SAFE_IOCTL(fd, SIOCGIFINDEX, &ifr);
38f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci	addr1.sll_family = AF_PACKET;
41f08c3bdfSopenharmony_ci	addr1.sll_ifindex = ifr.ifr_ifindex;
42f08c3bdfSopenharmony_ci	addr2.sll_family = AF_PACKET;
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci	fzsync_pair.exec_loops = 10000;
45f08c3bdfSopenharmony_ci	tst_fzsync_pair_init(&fzsync_pair);
46f08c3bdfSopenharmony_ci}
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cistatic void cleanup(void)
49f08c3bdfSopenharmony_ci{
50f08c3bdfSopenharmony_ci	tst_fzsync_pair_cleanup(&fzsync_pair);
51f08c3bdfSopenharmony_ci}
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_cistatic void do_bind(void)
54f08c3bdfSopenharmony_ci{
55f08c3bdfSopenharmony_ci	SAFE_BIND(fd, (struct sockaddr *)&addr1, sizeof(addr1));
56f08c3bdfSopenharmony_ci	SAFE_BIND(fd, (struct sockaddr *)&addr2, sizeof(addr2));
57f08c3bdfSopenharmony_ci}
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_cistatic void *thread_run(void *arg)
60f08c3bdfSopenharmony_ci{
61f08c3bdfSopenharmony_ci	while (tst_fzsync_run_b(&fzsync_pair)) {
62f08c3bdfSopenharmony_ci		tst_fzsync_start_race_b(&fzsync_pair);
63f08c3bdfSopenharmony_ci		do_bind();
64f08c3bdfSopenharmony_ci		tst_fzsync_end_race_b(&fzsync_pair);
65f08c3bdfSopenharmony_ci	}
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_ci	return arg;
68f08c3bdfSopenharmony_ci}
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cistatic void run(void)
71f08c3bdfSopenharmony_ci{
72f08c3bdfSopenharmony_ci	struct ifreq ifr;
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci	tst_fzsync_pair_reset(&fzsync_pair, thread_run);
75f08c3bdfSopenharmony_ci	strcpy(ifr.ifr_name, "lo");
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	while (tst_fzsync_run_a(&fzsync_pair)) {
78f08c3bdfSopenharmony_ci		fd = SAFE_SOCKET(AF_PACKET, SOCK_DGRAM, PF_PACKET);
79f08c3bdfSopenharmony_ci		ifr.ifr_flags = 0;
80f08c3bdfSopenharmony_ci		ioctl(fd, SIOCSIFFLAGS, &ifr);
81f08c3bdfSopenharmony_ci		ifr.ifr_flags = IFF_UP;
82f08c3bdfSopenharmony_ci		tst_fzsync_start_race_a(&fzsync_pair);
83f08c3bdfSopenharmony_ci		ioctl(fd, SIOCSIFFLAGS, &ifr);
84f08c3bdfSopenharmony_ci		tst_fzsync_end_race_a(&fzsync_pair);
85f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd);
86f08c3bdfSopenharmony_ci	}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci	tst_res(TPASS, "Nothing bad happened (yet)");
89f08c3bdfSopenharmony_ci}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_cistatic struct tst_test test = {
92f08c3bdfSopenharmony_ci	.test_all = run,
93f08c3bdfSopenharmony_ci	.setup = setup,
94f08c3bdfSopenharmony_ci	.cleanup = cleanup,
95f08c3bdfSopenharmony_ci	.max_runtime = 300,
96f08c3bdfSopenharmony_ci	.taint_check = TST_TAINT_W | TST_TAINT_D,
97f08c3bdfSopenharmony_ci	.needs_kconfigs = (const char *[]) {
98f08c3bdfSopenharmony_ci		"CONFIG_USER_NS=y",
99f08c3bdfSopenharmony_ci		"CONFIG_NET_NS=y",
100f08c3bdfSopenharmony_ci		NULL
101f08c3bdfSopenharmony_ci	},
102f08c3bdfSopenharmony_ci	.save_restore = (const struct tst_path_val[]) {
103f08c3bdfSopenharmony_ci		{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
104f08c3bdfSopenharmony_ci		{}
105f08c3bdfSopenharmony_ci	},
106f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
107f08c3bdfSopenharmony_ci		{"linux-git", "15fe076edea7"},
108f08c3bdfSopenharmony_ci		{"CVE", "2018-18559"},
109f08c3bdfSopenharmony_ci		{}
110f08c3bdfSopenharmony_ci	}
111f08c3bdfSopenharmony_ci};
112