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