1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2022 SUSE LLC
4f08c3bdfSopenharmony_ci * Author: Marcos Paulo de Souza <mpdesouza@suse.com>
5f08c3bdfSopenharmony_ci * LTP port: Martin Doucha <mdoucha@suse.cz>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Check for possible double free of rx_owner_map after switching packet
12f08c3bdfSopenharmony_ci * interface versions aka CVE-2021-22600.
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * Kernel crash fixed in:
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci *  commit ec6af094ea28f0f2dda1a6a33b14cd57e36a9755
17f08c3bdfSopenharmony_ci *  Author: Willem de Bruijn <willemb@google.com>
18f08c3bdfSopenharmony_ci *  Date:   Wed Dec 15 09:39:37 2021 -0500
19f08c3bdfSopenharmony_ci *
20f08c3bdfSopenharmony_ci *  net/packet: rx_owner_map depends on pg_vec
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci *  commit c800aaf8d869f2b9b47b10c5c312fe19f0a94042
23f08c3bdfSopenharmony_ci *  Author: WANG Cong <xiyou.wangcong@gmail.com>
24f08c3bdfSopenharmony_ci *  Date:   Mon Jul 24 10:07:32 2017 -0700
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci *  packet: fix use-after-free in prb_retire_rx_blk_timer_expired()
27f08c3bdfSopenharmony_ci */
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci#include <unistd.h>
30f08c3bdfSopenharmony_ci#include <sys/types.h>
31f08c3bdfSopenharmony_ci#include <sys/socket.h>
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci#include "tst_test.h"
34f08c3bdfSopenharmony_ci#include "lapi/if_packet.h"
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic int sock = -1;
37f08c3bdfSopenharmony_cistatic unsigned int pagesize;
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_cistatic void setup(void)
40f08c3bdfSopenharmony_ci{
41f08c3bdfSopenharmony_ci	pagesize = SAFE_SYSCONF(_SC_PAGESIZE);
42f08c3bdfSopenharmony_ci	tst_setup_netns();
43f08c3bdfSopenharmony_ci}
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_cistatic void run(void)
46f08c3bdfSopenharmony_ci{
47f08c3bdfSopenharmony_ci	unsigned int i, version = TPACKET_V3;
48f08c3bdfSopenharmony_ci	struct tpacket_req3 req = {
49f08c3bdfSopenharmony_ci		.tp_block_size = 4 * pagesize,
50f08c3bdfSopenharmony_ci		.tp_frame_size = TPACKET_ALIGNMENT << 7,
51f08c3bdfSopenharmony_ci		.tp_retire_blk_tov = 64,
52f08c3bdfSopenharmony_ci		.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH
53f08c3bdfSopenharmony_ci	};
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	for (i = 0; i < 5; i++) {
56f08c3bdfSopenharmony_ci		req.tp_block_nr = 256;
57f08c3bdfSopenharmony_ci		req.tp_frame_nr = req.tp_block_size * req.tp_block_nr;
58f08c3bdfSopenharmony_ci		req.tp_frame_nr /= req.tp_frame_size;
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci		sock = SAFE_SOCKET(AF_PACKET, SOCK_RAW, 0);
61f08c3bdfSopenharmony_ci		TEST(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &version,
62f08c3bdfSopenharmony_ci			sizeof(version)));
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci		if (TST_RET == -1 && TST_ERR == EINVAL)
65f08c3bdfSopenharmony_ci			tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported");
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_ci		if (TST_RET) {
68f08c3bdfSopenharmony_ci			tst_brk(TBROK | TTERRNO,
69f08c3bdfSopenharmony_ci				"setsockopt(PACKET_VERSION, TPACKET_V3)");
70f08c3bdfSopenharmony_ci		}
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci		/* Allocate owner map and then free it again */
73f08c3bdfSopenharmony_ci		SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req,
74f08c3bdfSopenharmony_ci			sizeof(req));
75f08c3bdfSopenharmony_ci		req.tp_block_nr = 0;
76f08c3bdfSopenharmony_ci		req.tp_frame_nr = 0;
77f08c3bdfSopenharmony_ci		SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req,
78f08c3bdfSopenharmony_ci			sizeof(req));
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci		/* Switch packet version and trigger double free of owner map */
81f08c3bdfSopenharmony_ci		SAFE_SETSOCKOPT_INT(sock, SOL_PACKET, PACKET_VERSION,
82f08c3bdfSopenharmony_ci			TPACKET_V2);
83f08c3bdfSopenharmony_ci		SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req,
84f08c3bdfSopenharmony_ci			sizeof(req));
85f08c3bdfSopenharmony_ci		SAFE_CLOSE(sock);
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci		/* Wait for socket timer to expire just in case */
88f08c3bdfSopenharmony_ci		usleep(req.tp_retire_blk_tov * 3000);
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci		if (tst_taint_check()) {
91f08c3bdfSopenharmony_ci			tst_res(TFAIL, "Kernel is vulnerable");
92f08c3bdfSopenharmony_ci			return;
93f08c3bdfSopenharmony_ci		}
94f08c3bdfSopenharmony_ci	}
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	tst_res(TPASS, "Nothing bad happened, probably");
97f08c3bdfSopenharmony_ci}
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_cistatic void cleanup(void)
100f08c3bdfSopenharmony_ci{
101f08c3bdfSopenharmony_ci	if (sock >= 0)
102f08c3bdfSopenharmony_ci		SAFE_CLOSE(sock);
103f08c3bdfSopenharmony_ci}
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_cistatic struct tst_test test = {
106f08c3bdfSopenharmony_ci	.test_all = run,
107f08c3bdfSopenharmony_ci	.setup = setup,
108f08c3bdfSopenharmony_ci	.cleanup = cleanup,
109f08c3bdfSopenharmony_ci	.taint_check = TST_TAINT_W | TST_TAINT_D,
110f08c3bdfSopenharmony_ci	.needs_kconfigs = (const char *[]) {
111f08c3bdfSopenharmony_ci		"CONFIG_USER_NS=y",
112f08c3bdfSopenharmony_ci		"CONFIG_NET_NS=y",
113f08c3bdfSopenharmony_ci		NULL
114f08c3bdfSopenharmony_ci	},
115f08c3bdfSopenharmony_ci	.save_restore = (const struct tst_path_val[]) {
116f08c3bdfSopenharmony_ci		{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
117f08c3bdfSopenharmony_ci		{}
118f08c3bdfSopenharmony_ci	},
119f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
120f08c3bdfSopenharmony_ci		{"linux-git", "ec6af094ea28"},
121f08c3bdfSopenharmony_ci		{"linux-git", "c800aaf8d869"},
122f08c3bdfSopenharmony_ci		{"CVE", "2021-22600"},
123f08c3bdfSopenharmony_ci		{}
124f08c3bdfSopenharmony_ci	}
125f08c3bdfSopenharmony_ci};
126