xref: /aosp_15_r20/external/ltp/testcases/cve/tcindex01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2023 SUSE LLC
4  * Author: Marcos Paulo de Souza <[email protected]>
5  * LTP port: Martin Doucha <[email protected]>
6  */
7 
8 /*\
9  * CVE-2023-1829
10  *
11  * Test for use-after-free after removing tcindex traffic filter with certain
12  * parameters.
13  *
14  * Tcindex filter removed in:
15  *
16  *  commit 8c710f75256bb3cf05ac7b1672c82b92c43f3d28
17  *  Author: Jamal Hadi Salim <[email protected]>
18  *  Date:   Tue Feb 14 08:49:14 2023 -0500
19  *
20  *  net/sched: Retire tcindex classifier
21  */
22 
23 #include <linux/netlink.h>
24 #include <linux/pkt_sched.h>
25 #include <linux/pkt_cls.h>
26 #include "tst_test.h"
27 #include "tst_netlink.h"
28 #include "tst_netdevice.h"
29 #include "lapi/sched.h"
30 #include "lapi/if_ether.h"
31 #include "lapi/rtnetlink.h"
32 
33 #define DEVNAME "ltp_dummy1"
34 
35 #ifndef TCA_TCINDEX_MAX
36 enum {
37        TCA_TCINDEX_UNSPEC,
38        TCA_TCINDEX_HASH,
39        TCA_TCINDEX_MASK,
40        TCA_TCINDEX_SHIFT,
41        TCA_TCINDEX_FALL_THROUGH,
42        TCA_TCINDEX_CLASSID,
43        TCA_TCINDEX_POLICE,
44        TCA_TCINDEX_ACT,
45        __TCA_TCINDEX_MAX
46 };
47 
48 #define TCA_TCINDEX_MAX     (__TCA_TCINDEX_MAX - 1)
49 #endif
50 
51 
52 static const uint32_t qd_handle = TC_H_MAKE(1 << 16, 0);
53 static const uint32_t clsid = TC_H_MAKE(1 << 16, 1);
54 static const uint32_t shift = 10;
55 static const uint16_t mask = 0xffff;
56 
57 /* rtnetlink payloads */
58 static const struct tc_htb_glob qd_opt = {
59 	.rate2quantum = 10,
60 	.version = 3,
61 	.defcls = 30
62 };
63 static struct tc_htb_opt cls_opt = {};
64 
65 /* htb qdisc and class options */
66 static const struct tst_netlink_attr_list qd_config[] = {
67 	{TCA_OPTIONS, NULL, 0, (const struct tst_netlink_attr_list[]){
68 		{TCA_HTB_INIT, &qd_opt, sizeof(qd_opt), NULL},
69 		{0, NULL, -1, NULL}
70 	}},
71 	{0, NULL, -1, NULL}
72 };
73 static const struct tst_netlink_attr_list cls_config[] = {
74 	{TCA_OPTIONS, NULL, 0, (const struct tst_netlink_attr_list[]){
75 		{TCA_HTB_PARMS, &cls_opt, sizeof(cls_opt), NULL},
76 		{0, NULL, -1, NULL}
77 	}},
78 	{0, NULL, -1, NULL}
79 };
80 
81 /* tcindex filter options */
82 static const struct tst_netlink_attr_list f_config[] = {
83 	{TCA_OPTIONS, NULL, 0, (const struct tst_netlink_attr_list[]){
84 		{TCA_TCINDEX_MASK, &mask, sizeof(mask), NULL},
85 		{TCA_TCINDEX_SHIFT, &shift, sizeof(shift), NULL},
86 		{TCA_TCINDEX_CLASSID, &clsid, sizeof(clsid), NULL},
87 		{0, NULL, -1, NULL}
88 	}},
89 	{0, NULL, -1, NULL}
90 };
91 
setup(void)92 static void setup(void)
93 {
94 	tst_setup_netns();
95 	NETDEV_ADD_DEVICE(DEVNAME, "dummy");
96 
97 	cls_opt.rate.rate = cls_opt.ceil.rate = 256000;
98 	cls_opt.buffer = 1000000 * 1600 / cls_opt.rate.rate;
99 	cls_opt.cbuffer = 1000000 * 1600 / cls_opt.ceil.rate;
100 }
101 
run(void)102 static void run(void)
103 {
104 	int ret;
105 
106 	NETDEV_ADD_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle, "htb",
107 		qd_config);
108 	NETDEV_ADD_TRAFFIC_CLASS(DEVNAME, qd_handle, clsid, "htb", cls_config);
109 	ret = NETDEV_ADD_TRAFFIC_FILTER_RET(DEVNAME, qd_handle, 10, ETH_P_IP,
110 		1, "tcindex", f_config);
111 	TST_ERR = tst_netlink_errno;
112 
113 	if (!ret && TST_ERR == ENOENT) {
114 		tst_res(TPASS | TTERRNO,
115 			"tcindex module is blacklisted or unavailable");
116 		return;
117 	}
118 
119 	if (!ret)
120 		tst_brk(TBROK | TTERRNO, "Cannot add tcindex filter");
121 
122 	NETDEV_REMOVE_TRAFFIC_FILTER(DEVNAME, qd_handle, 10, ETH_P_IP,
123 		1, "tcindex");
124 	ret = NETDEV_ADD_TRAFFIC_FILTER_RET(DEVNAME, qd_handle, 10, ETH_P_IP,
125 		1, "tcindex", f_config);
126 	TST_ERR = tst_netlink_errno;
127 	NETDEV_REMOVE_QDISC(DEVNAME, AF_UNSPEC, TC_H_ROOT, qd_handle, "htb");
128 
129 	if (ret)
130 		tst_res(TPASS, "Removing tcindex filter works correctly");
131 	else if (TST_ERR == EEXIST)
132 		tst_res(TFAIL, "Kernel traffic filter list is corrupted");
133 	else
134 		tst_brk(TBROK | TTERRNO, "Unexpected rtnetlink error");
135 }
136 
cleanup(void)137 static void cleanup(void)
138 {
139 	NETDEV_REMOVE_DEVICE(DEVNAME);
140 }
141 
142 static struct tst_test test = {
143 	.test_all = run,
144 	.setup = setup,
145 	.cleanup = cleanup,
146 	.taint_check = TST_TAINT_W | TST_TAINT_D,
147 	.needs_kconfigs = (const char *[]) {
148 		"CONFIG_VETH",
149 		"CONFIG_USER_NS=y",
150 		"CONFIG_NET_NS=y",
151 		"CONFIG_NET_SCH_HTB",
152 		"CONFIG_NET_CLS_TCINDEX",
153 		NULL
154 	},
155 	.save_restore = (const struct tst_path_val[]) {
156 		{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
157 		{}
158 	},
159 	.needs_drivers = (const char *const []) {
160 		"dummy",
161 		NULL
162 	},
163 	.tags = (const struct tst_tag[]) {
164 		{"linux-git", "8c710f75256b"},
165 		{"CVE", "2023-1829"},
166 		{}
167 	}
168 };
169