xref: /aosp_15_r20/external/ltp/testcases/network/iptables/nft02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2023 SUSE LLC
4*49cdfc7eSAndroid Build Coastguard Worker  * Author: Marcos Paulo de Souza <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  * LTP port: Martin Doucha <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker  */
7*49cdfc7eSAndroid Build Coastguard Worker 
8*49cdfc7eSAndroid Build Coastguard Worker /*\
9*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  * CVE-2023-31248
12*49cdfc7eSAndroid Build Coastguard Worker  *
13*49cdfc7eSAndroid Build Coastguard Worker  * Test for use-after-free when adding a new rule to a chain deleted
14*49cdfc7eSAndroid Build Coastguard Worker  * in the same netlink message batch.
15*49cdfc7eSAndroid Build Coastguard Worker  *
16*49cdfc7eSAndroid Build Coastguard Worker  * Kernel bug fixed in:
17*49cdfc7eSAndroid Build Coastguard Worker  *
18*49cdfc7eSAndroid Build Coastguard Worker  *  commit 515ad530795c118f012539ed76d02bacfd426d89
19*49cdfc7eSAndroid Build Coastguard Worker  *  Author: Thadeu Lima de Souza Cascardo <[email protected]>
20*49cdfc7eSAndroid Build Coastguard Worker  *  Date:   Wed Jul 5 09:12:55 2023 -0300
21*49cdfc7eSAndroid Build Coastguard Worker  *
22*49cdfc7eSAndroid Build Coastguard Worker  *  netfilter: nf_tables: do not ignore genmask when looking up chain by id
23*49cdfc7eSAndroid Build Coastguard Worker  */
24*49cdfc7eSAndroid Build Coastguard Worker 
25*49cdfc7eSAndroid Build Coastguard Worker #include <linux/netlink.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <linux/tcp.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <arpa/inet.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include <linux/netfilter.h>
29*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/nf_tables.h"
30*49cdfc7eSAndroid Build Coastguard Worker #include <linux/netfilter/nfnetlink.h>
31*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
32*49cdfc7eSAndroid Build Coastguard Worker #include "tst_netlink.h"
33*49cdfc7eSAndroid Build Coastguard Worker 
34*49cdfc7eSAndroid Build Coastguard Worker #define TABNAME "ltp_table1"
35*49cdfc7eSAndroid Build Coastguard Worker #define SRCCHAIN "ltp_chain_src"
36*49cdfc7eSAndroid Build Coastguard Worker #define DESTCHAIN "ltp_chain_dest"
37*49cdfc7eSAndroid Build Coastguard Worker #define DESTCHAIN_ID 77
38*49cdfc7eSAndroid Build Coastguard Worker 
39*49cdfc7eSAndroid Build Coastguard Worker static uint32_t chain_id;
40*49cdfc7eSAndroid Build Coastguard Worker static uint32_t imm_dreg, imm_verdict;
41*49cdfc7eSAndroid Build Coastguard Worker static struct tst_netlink_context *ctx;
42*49cdfc7eSAndroid Build Coastguard Worker 
43*49cdfc7eSAndroid Build Coastguard Worker /* Table creation config */
44*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list table_config[] = {
45*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
46*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
47*49cdfc7eSAndroid Build Coastguard Worker };
48*49cdfc7eSAndroid Build Coastguard Worker 
49*49cdfc7eSAndroid Build Coastguard Worker /* Chain creation and deletion config */
50*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list destchain_config[] = {
51*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
52*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_CHAIN_NAME, DESTCHAIN, strlen(DESTCHAIN) + 1, NULL},
53*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_CHAIN_ID, &chain_id, sizeof(chain_id), NULL},
54*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
55*49cdfc7eSAndroid Build Coastguard Worker };
56*49cdfc7eSAndroid Build Coastguard Worker 
57*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list delchain_config[] = {
58*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
59*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_CHAIN_NAME, DESTCHAIN, strlen(DESTCHAIN) + 1, NULL},
60*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
61*49cdfc7eSAndroid Build Coastguard Worker };
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list srcchain_config[] = {
64*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_TABLE_NAME, TABNAME, strlen(TABNAME) + 1, NULL},
65*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_CHAIN_NAME, SRCCHAIN, strlen(SRCCHAIN) + 1, NULL},
66*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
67*49cdfc7eSAndroid Build Coastguard Worker };
68*49cdfc7eSAndroid Build Coastguard Worker 
69*49cdfc7eSAndroid Build Coastguard Worker /* Rule creation config */
70*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list rule_verdict_config[] = {
71*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_VERDICT_CODE, &imm_verdict, sizeof(imm_verdict), NULL},
72*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_VERDICT_CHAIN_ID, &chain_id, sizeof(chain_id), NULL},
73*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
74*49cdfc7eSAndroid Build Coastguard Worker };
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list rule_data_config[] = {
77*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_IMMEDIATE_DREG, &imm_dreg, sizeof(imm_dreg), NULL},
78*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_IMMEDIATE_DATA, NULL, 0, (const struct tst_netlink_attr_list[]) {
79*49cdfc7eSAndroid Build Coastguard Worker 		{NFTA_DATA_VERDICT, NULL, 0, rule_verdict_config},
80*49cdfc7eSAndroid Build Coastguard Worker 		{0, NULL, -1, NULL}
81*49cdfc7eSAndroid Build Coastguard Worker 	}},
82*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
83*49cdfc7eSAndroid Build Coastguard Worker };
84*49cdfc7eSAndroid Build Coastguard Worker 
85*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list rule_expr_config[] = {
86*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_LIST_ELEM, NULL, 0, (const struct tst_netlink_attr_list[]) {
87*49cdfc7eSAndroid Build Coastguard Worker 		{NFTA_EXPR_NAME, "immediate", 10, NULL},
88*49cdfc7eSAndroid Build Coastguard Worker 		{NFTA_EXPR_DATA, NULL, 0, rule_data_config},
89*49cdfc7eSAndroid Build Coastguard Worker 		{0, NULL, -1, NULL}
90*49cdfc7eSAndroid Build Coastguard Worker 	}},
91*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
92*49cdfc7eSAndroid Build Coastguard Worker };
93*49cdfc7eSAndroid Build Coastguard Worker 
94*49cdfc7eSAndroid Build Coastguard Worker static const struct tst_netlink_attr_list rule_config[] = {
95*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_RULE_EXPRESSIONS, NULL, 0, rule_expr_config},
96*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_RULE_TABLE, TABNAME, strlen(TABNAME) + 1, NULL},
97*49cdfc7eSAndroid Build Coastguard Worker 	{NFTA_RULE_CHAIN, SRCCHAIN, strlen(SRCCHAIN) + 1, NULL},
98*49cdfc7eSAndroid Build Coastguard Worker 	{0, NULL, -1, NULL}
99*49cdfc7eSAndroid Build Coastguard Worker };
100*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)101*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
102*49cdfc7eSAndroid Build Coastguard Worker {
103*49cdfc7eSAndroid Build Coastguard Worker 	tst_setup_netns();
104*49cdfc7eSAndroid Build Coastguard Worker 
105*49cdfc7eSAndroid Build Coastguard Worker 	chain_id = htonl(DESTCHAIN_ID);
106*49cdfc7eSAndroid Build Coastguard Worker 	imm_dreg = htonl(NFT_REG_VERDICT);
107*49cdfc7eSAndroid Build Coastguard Worker 	imm_verdict = htonl(NFT_GOTO);
108*49cdfc7eSAndroid Build Coastguard Worker }
109*49cdfc7eSAndroid Build Coastguard Worker 
run(void)110*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
111*49cdfc7eSAndroid Build Coastguard Worker {
112*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
113*49cdfc7eSAndroid Build Coastguard Worker 	struct nlmsghdr header;
114*49cdfc7eSAndroid Build Coastguard Worker 	struct nfgenmsg nfpayload;
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	memset(&header, 0, sizeof(header));
117*49cdfc7eSAndroid Build Coastguard Worker 	memset(&nfpayload, 0, sizeof(nfpayload));
118*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.version = NFNETLINK_V0;
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	ctx = NETLINK_CREATE_CONTEXT(NETLINK_NETFILTER);
121*49cdfc7eSAndroid Build Coastguard Worker 
122*49cdfc7eSAndroid Build Coastguard Worker 	/* Start netfilter batch */
123*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = NFNL_MSG_BATCH_BEGIN;
124*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST;
125*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = AF_UNSPEC;
126*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(NFNL_SUBSYS_NFTABLES);
127*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
128*49cdfc7eSAndroid Build Coastguard Worker 
129*49cdfc7eSAndroid Build Coastguard Worker 	/* Add table */
130*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWTABLE;
131*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
132*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = NFPROTO_IPV4;
133*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(0);
134*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
135*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_ATTR_LIST(ctx, table_config);
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	/* Add destination chain */
138*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWCHAIN;
139*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
140*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = NFPROTO_IPV4;
141*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(0);
142*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
143*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_ATTR_LIST(ctx, destchain_config);
144*49cdfc7eSAndroid Build Coastguard Worker 
145*49cdfc7eSAndroid Build Coastguard Worker 	/* Delete destination chain */
146*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_DELCHAIN;
147*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST;
148*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = NFPROTO_IPV4;
149*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(0);
150*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
151*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_ATTR_LIST(ctx, delchain_config);
152*49cdfc7eSAndroid Build Coastguard Worker 
153*49cdfc7eSAndroid Build Coastguard Worker 	/* Add source chain */
154*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWCHAIN;
155*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
156*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = NFPROTO_IPV4;
157*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(0);
158*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
159*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_ATTR_LIST(ctx, srcchain_config);
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker 	/* Add rule to source chain. Require ACK and check for ENOENT error. */
162*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWRULE;
163*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST | NLM_F_APPEND | NLM_F_CREATE |
164*49cdfc7eSAndroid Build Coastguard Worker 		NLM_F_ACK;
165*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = NFPROTO_IPV4;
166*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(0);
167*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
168*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_ATTR_LIST(ctx, rule_config);
169*49cdfc7eSAndroid Build Coastguard Worker 
170*49cdfc7eSAndroid Build Coastguard Worker 	/* End batch */
171*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_type = NFNL_MSG_BATCH_END;
172*49cdfc7eSAndroid Build Coastguard Worker 	header.nlmsg_flags = NLM_F_REQUEST;
173*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.nfgen_family = AF_UNSPEC;
174*49cdfc7eSAndroid Build Coastguard Worker 	nfpayload.res_id = htons(NFNL_SUBSYS_NFTABLES);
175*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_ADD_MESSAGE(ctx, &header, &nfpayload, sizeof(nfpayload));
176*49cdfc7eSAndroid Build Coastguard Worker 
177*49cdfc7eSAndroid Build Coastguard Worker 	ret = NETLINK_SEND_VALIDATE(ctx);
178*49cdfc7eSAndroid Build Coastguard Worker 	TST_ERR = tst_netlink_errno;
179*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_DESTROY_CONTEXT(ctx);
180*49cdfc7eSAndroid Build Coastguard Worker 	ctx = NULL;
181*49cdfc7eSAndroid Build Coastguard Worker 
182*49cdfc7eSAndroid Build Coastguard Worker 	if (ret)
183*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "Netfilter chain list is corrupted");
184*49cdfc7eSAndroid Build Coastguard Worker 	else if (TST_ERR == ENOENT)
185*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "Deleted netfilter chain cannot be referenced");
186*49cdfc7eSAndroid Build Coastguard Worker 	else if (TST_ERR == EOPNOTSUPP || TST_ERR == EINVAL)
187*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "Test requires unavailable netfilter features");
188*49cdfc7eSAndroid Build Coastguard Worker 	else
189*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TTERRNO, "Unknown nfnetlink error");
190*49cdfc7eSAndroid Build Coastguard Worker }
191*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)192*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
193*49cdfc7eSAndroid Build Coastguard Worker {
194*49cdfc7eSAndroid Build Coastguard Worker 	NETLINK_DESTROY_CONTEXT(ctx);
195*49cdfc7eSAndroid Build Coastguard Worker }
196*49cdfc7eSAndroid Build Coastguard Worker 
197*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
198*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
199*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
200*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
201*49cdfc7eSAndroid Build Coastguard Worker 	.taint_check = TST_TAINT_W | TST_TAINT_D,
202*49cdfc7eSAndroid Build Coastguard Worker 	.needs_kconfigs = (const char *[]) {
203*49cdfc7eSAndroid Build Coastguard Worker 		"CONFIG_USER_NS=y",
204*49cdfc7eSAndroid Build Coastguard Worker 		"CONFIG_NF_TABLES",
205*49cdfc7eSAndroid Build Coastguard Worker 		NULL
206*49cdfc7eSAndroid Build Coastguard Worker 	},
207*49cdfc7eSAndroid Build Coastguard Worker 	.save_restore = (const struct tst_path_val[]) {
208*49cdfc7eSAndroid Build Coastguard Worker 		{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
209*49cdfc7eSAndroid Build Coastguard Worker 		{}
210*49cdfc7eSAndroid Build Coastguard Worker 	},
211*49cdfc7eSAndroid Build Coastguard Worker 	.tags = (const struct tst_tag[]) {
212*49cdfc7eSAndroid Build Coastguard Worker 		{"linux-git", "515ad530795c"},
213*49cdfc7eSAndroid Build Coastguard Worker 		{"CVE", "2023-31248"},
214*49cdfc7eSAndroid Build Coastguard Worker 		{}
215*49cdfc7eSAndroid Build Coastguard Worker 	}
216*49cdfc7eSAndroid Build Coastguard Worker };
217