Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit 4cdc55e

Browse files
Florian Westphalgregkh
Florian Westphal
authored andcommittedOct 17, 2024
netfilter: xtables: avoid NFPROTO_UNSPEC where needed
[ Upstream commit 0bfcb7b ] syzbot managed to call xt_cluster match via ebtables: WARNING: CPU: 0 PID: 11 at net/netfilter/xt_cluster.c:72 xt_cluster_mt+0x196/0x780 [..] ebt_do_table+0x174b/0x2a40 Module registers to NFPROTO_UNSPEC, but it assumes ipv4/ipv6 packet processing. As this is only useful to restrict locally terminating TCP/UDP traffic, register this for ipv4 and ipv6 family only. Pablo points out that this is a general issue, direct users of the set/getsockopt interface can call into targets/matches that were only intended for use with ip(6)tables. Check all UNSPEC matches and targets for similar issues: - matches and targets are fine except if they assume skb_network_header() is valid -- this is only true when called from inet layer: ip(6) stack pulls the ip/ipv6 header into linear data area. - targets that return XT_CONTINUE or other xtables verdicts must be restricted too, they are incompatbile with the ebtables traverser, e.g. EBT_CONTINUE is a completely different value than XT_CONTINUE. Most matches/targets are changed to register for NFPROTO_IPV4/IPV6, as they are provided for use by ip(6)tables. The MARK target is also used by arptables, so register for NFPROTO_ARP too. While at it, bail out if connbytes fails to enable the corresponding conntrack family. This change passes the selftests in iptables.git. Reported-by: syzbot+256c348558aa5cf611a9@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netfilter-devel/66fec2e2.050a0220.9ec68.0047.GAE@google.com/ Fixes: 0269ea4 ("netfilter: xtables: add cluster match") Signed-off-by: Florian Westphal <fw@strlen.de> Co-developed-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 32dfba7 commit 4cdc55e

16 files changed

+422
-165
lines changed
 

‎net/netfilter/xt_CHECKSUM.c

+23-10
Original file line numberDiff line numberDiff line change
@@ -63,24 +63,37 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
6363
return 0;
6464
}
6565

66-
static struct xt_target checksum_tg_reg __read_mostly = {
67-
.name = "CHECKSUM",
68-
.family = NFPROTO_UNSPEC,
69-
.target = checksum_tg,
70-
.targetsize = sizeof(struct xt_CHECKSUM_info),
71-
.table = "mangle",
72-
.checkentry = checksum_tg_check,
73-
.me = THIS_MODULE,
66+
static struct xt_target checksum_tg_reg[] __read_mostly = {
67+
{
68+
.name = "CHECKSUM",
69+
.family = NFPROTO_IPV4,
70+
.target = checksum_tg,
71+
.targetsize = sizeof(struct xt_CHECKSUM_info),
72+
.table = "mangle",
73+
.checkentry = checksum_tg_check,
74+
.me = THIS_MODULE,
75+
},
76+
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
77+
{
78+
.name = "CHECKSUM",
79+
.family = NFPROTO_IPV6,
80+
.target = checksum_tg,
81+
.targetsize = sizeof(struct xt_CHECKSUM_info),
82+
.table = "mangle",
83+
.checkentry = checksum_tg_check,
84+
.me = THIS_MODULE,
85+
},
86+
#endif
7487
};
7588

7689
static int __init checksum_tg_init(void)
7790
{
78-
return xt_register_target(&checksum_tg_reg);
91+
return xt_register_targets(checksum_tg_reg, ARRAY_SIZE(checksum_tg_reg));
7992
}
8093

8194
static void __exit checksum_tg_exit(void)
8295
{
83-
xt_unregister_target(&checksum_tg_reg);
96+
xt_unregister_targets(checksum_tg_reg, ARRAY_SIZE(checksum_tg_reg));
8497
}
8598

8699
module_init(checksum_tg_init);

‎net/netfilter/xt_CLASSIFY.c

+14-2
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ static struct xt_target classify_tg_reg[] __read_mostly = {
3838
{
3939
.name = "CLASSIFY",
4040
.revision = 0,
41-
.family = NFPROTO_UNSPEC,
41+
.family = NFPROTO_IPV4,
4242
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
43-
(1 << NF_INET_POST_ROUTING),
43+
(1 << NF_INET_POST_ROUTING),
4444
.target = classify_tg,
4545
.targetsize = sizeof(struct xt_classify_target_info),
4646
.me = THIS_MODULE,
@@ -54,6 +54,18 @@ static struct xt_target classify_tg_reg[] __read_mostly = {
5454
.targetsize = sizeof(struct xt_classify_target_info),
5555
.me = THIS_MODULE,
5656
},
57+
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
58+
{
59+
.name = "CLASSIFY",
60+
.revision = 0,
61+
.family = NFPROTO_IPV6,
62+
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
63+
(1 << NF_INET_POST_ROUTING),
64+
.target = classify_tg,
65+
.targetsize = sizeof(struct xt_classify_target_info),
66+
.me = THIS_MODULE,
67+
},
68+
#endif
5769
};
5870

5971
static int __init classify_tg_init(void)

‎net/netfilter/xt_CONNSECMARK.c

+25-11
Original file line numberDiff line numberDiff line change
@@ -114,25 +114,39 @@ static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
114114
nf_ct_netns_put(par->net, par->family);
115115
}
116116

117-
static struct xt_target connsecmark_tg_reg __read_mostly = {
118-
.name = "CONNSECMARK",
119-
.revision = 0,
120-
.family = NFPROTO_UNSPEC,
121-
.checkentry = connsecmark_tg_check,
122-
.destroy = connsecmark_tg_destroy,
123-
.target = connsecmark_tg,
124-
.targetsize = sizeof(struct xt_connsecmark_target_info),
125-
.me = THIS_MODULE,
117+
static struct xt_target connsecmark_tg_reg[] __read_mostly = {
118+
{
119+
.name = "CONNSECMARK",
120+
.revision = 0,
121+
.family = NFPROTO_IPV4,
122+
.checkentry = connsecmark_tg_check,
123+
.destroy = connsecmark_tg_destroy,
124+
.target = connsecmark_tg,
125+
.targetsize = sizeof(struct xt_connsecmark_target_info),
126+
.me = THIS_MODULE,
127+
},
128+
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
129+
{
130+
.name = "CONNSECMARK",
131+
.revision = 0,
132+
.family = NFPROTO_IPV6,
133+
.checkentry = connsecmark_tg_check,
134+
.destroy = connsecmark_tg_destroy,
135+
.target = connsecmark_tg,
136+
.targetsize = sizeof(struct xt_connsecmark_target_info),
137+
.me = THIS_MODULE,
138+
},
139+
#endif
126140
};
127141

128142
static int __init connsecmark_tg_init(void)
129143
{
130-
return xt_register_target(&connsecmark_tg_reg);
144+
return xt_register_targets(connsecmark_tg_reg, ARRAY_SIZE(connsecmark_tg_reg));
131145
}
132146

133147
static void __exit connsecmark_tg_exit(void)
134148
{
135-
xt_unregister_target(&connsecmark_tg_reg);
149+
xt_unregister_targets(connsecmark_tg_reg, ARRAY_SIZE(connsecmark_tg_reg));
136150
}
137151

138152
module_init(connsecmark_tg_init);

‎net/netfilter/xt_CT.c

+69-37
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,30 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
313313
xt_ct_tg_destroy(par, par->targinfo);
314314
}
315315

316+
static unsigned int
317+
notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
318+
{
319+
/* Previously seen (loopback)? Ignore. */
320+
if (skb->_nfct != 0)
321+
return XT_CONTINUE;
322+
323+
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
324+
325+
return XT_CONTINUE;
326+
}
327+
316328
static struct xt_target xt_ct_tg_reg[] __read_mostly = {
329+
{
330+
.name = "NOTRACK",
331+
.revision = 0,
332+
.family = NFPROTO_IPV4,
333+
.target = notrack_tg,
334+
.table = "raw",
335+
.me = THIS_MODULE,
336+
},
317337
{
318338
.name = "CT",
319-
.family = NFPROTO_UNSPEC,
339+
.family = NFPROTO_IPV4,
320340
.targetsize = sizeof(struct xt_ct_target_info),
321341
.usersize = offsetof(struct xt_ct_target_info, ct),
322342
.checkentry = xt_ct_tg_check_v0,
@@ -327,7 +347,7 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
327347
},
328348
{
329349
.name = "CT",
330-
.family = NFPROTO_UNSPEC,
350+
.family = NFPROTO_IPV4,
331351
.revision = 1,
332352
.targetsize = sizeof(struct xt_ct_target_info_v1),
333353
.usersize = offsetof(struct xt_ct_target_info, ct),
@@ -339,7 +359,7 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
339359
},
340360
{
341361
.name = "CT",
342-
.family = NFPROTO_UNSPEC,
362+
.family = NFPROTO_IPV4,
343363
.revision = 2,
344364
.targetsize = sizeof(struct xt_ct_target_info_v1),
345365
.usersize = offsetof(struct xt_ct_target_info, ct),
@@ -349,49 +369,61 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
349369
.table = "raw",
350370
.me = THIS_MODULE,
351371
},
352-
};
353-
354-
static unsigned int
355-
notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
356-
{
357-
/* Previously seen (loopback)? Ignore. */
358-
if (skb->_nfct != 0)
359-
return XT_CONTINUE;
360-
361-
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
362-
363-
return XT_CONTINUE;
364-
}
365-
366-
static struct xt_target notrack_tg_reg __read_mostly = {
367-
.name = "NOTRACK",
368-
.revision = 0,
369-
.family = NFPROTO_UNSPEC,
370-
.target = notrack_tg,
371-
.table = "raw",
372-
.me = THIS_MODULE,
372+
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
373+
{
374+
.name = "NOTRACK",
375+
.revision = 0,
376+
.family = NFPROTO_IPV6,
377+
.target = notrack_tg,
378+
.table = "raw",
379+
.me = THIS_MODULE,
380+
},
381+
{
382+
.name = "CT",
383+
.family = NFPROTO_IPV6,
384+
.targetsize = sizeof(struct xt_ct_target_info),
385+
.usersize = offsetof(struct xt_ct_target_info, ct),
386+
.checkentry = xt_ct_tg_check_v0,
387+
.destroy = xt_ct_tg_destroy_v0,
388+
.target = xt_ct_target_v0,
389+
.table = "raw",
390+
.me = THIS_MODULE,
391+
},
392+
{
393+
.name = "CT",
394+
.family = NFPROTO_IPV6,
395+
.revision = 1,
396+
.targetsize = sizeof(struct xt_ct_target_info_v1),
397+
.usersize = offsetof(struct xt_ct_target_info, ct),
398+
.checkentry = xt_ct_tg_check_v1,
399+
.destroy = xt_ct_tg_destroy_v1,
400+
.target = xt_ct_target_v1,
401+
.table = "raw",
402+
.me = THIS_MODULE,
403+
},
404+
{
405+
.name = "CT",
406+
.family = NFPROTO_IPV6,
407+
.revision = 2,
408+
.targetsize = sizeof(struct xt_ct_target_info_v1),
409+
.usersize = offsetof(struct xt_ct_target_info, ct),
410+
.checkentry = xt_ct_tg_check_v2,
411+
.destroy = xt_ct_tg_destroy_v1,
412+
.target = xt_ct_target_v1,
413+
.table = "raw",
414+
.me = THIS_MODULE,
415+
},
416+
#endif
373417
};
374418

375419
static int __init xt_ct_tg_init(void)
376420
{
377-
int ret;
378-
379-
ret = xt_register_target(&notrack_tg_reg);
380-
if (ret < 0)
381-
return ret;
382-
383-
ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
384-
if (ret < 0) {
385-
xt_unregister_target(&notrack_tg_reg);
386-
return ret;
387-
}
388-
return 0;
421+
return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
389422
}
390423

391424
static void __exit xt_ct_tg_exit(void)
392425
{
393426
xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
394-
xt_unregister_target(&notrack_tg_reg);
395427
}
396428

397429
module_init(xt_ct_tg_init);

‎net/netfilter/xt_IDLETIMER.c

+40-19
Original file line numberDiff line numberDiff line change
@@ -458,28 +458,49 @@ static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par)
458458

459459
static struct xt_target idletimer_tg[] __read_mostly = {
460460
{
461-
.name = "IDLETIMER",
462-
.family = NFPROTO_UNSPEC,
463-
.target = idletimer_tg_target,
464-
.targetsize = sizeof(struct idletimer_tg_info),
465-
.usersize = offsetof(struct idletimer_tg_info, timer),
466-
.checkentry = idletimer_tg_checkentry,
467-
.destroy = idletimer_tg_destroy,
468-
.me = THIS_MODULE,
461+
.name = "IDLETIMER",
462+
.family = NFPROTO_IPV4,
463+
.target = idletimer_tg_target,
464+
.targetsize = sizeof(struct idletimer_tg_info),
465+
.usersize = offsetof(struct idletimer_tg_info, timer),
466+
.checkentry = idletimer_tg_checkentry,
467+
.destroy = idletimer_tg_destroy,
468+
.me = THIS_MODULE,
469469
},
470470
{
471-
.name = "IDLETIMER",
472-
.family = NFPROTO_UNSPEC,
473-
.revision = 1,
474-
.target = idletimer_tg_target_v1,
475-
.targetsize = sizeof(struct idletimer_tg_info_v1),
476-
.usersize = offsetof(struct idletimer_tg_info_v1, timer),
477-
.checkentry = idletimer_tg_checkentry_v1,
478-
.destroy = idletimer_tg_destroy_v1,
479-
.me = THIS_MODULE,
471+
.name = "IDLETIMER",
472+
.family = NFPROTO_IPV4,
473+
.revision = 1,
474+
.target = idletimer_tg_target_v1,
475+
.targetsize = sizeof(struct idletimer_tg_info_v1),
476+
.usersize = offsetof(struct idletimer_tg_info_v1, timer),
477+
.checkentry = idletimer_tg_checkentry_v1,
478+
.destroy = idletimer_tg_destroy_v1,
479+
.me = THIS_MODULE,
480480
},
481-
482-
481+
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
482+
{
483+
.name = "IDLETIMER",
484+
.family = NFPROTO_IPV6,
485+
.target = idletimer_tg_target,
486+
.targetsize = sizeof(struct idletimer_tg_info),
487+
.usersize = offsetof(struct idletimer_tg_info, timer),
488+
.checkentry = idletimer_tg_checkentry,
489+
.destroy = idletimer_tg_destroy,
490+
.me = THIS_MODULE,
491+
},
492+
{
493+
.name = "IDLETIMER",
494+
.family = NFPROTO_IPV6,
495+
.revision = 1,
496+
.target = idletimer_tg_target_v1,
497+
.targetsize = sizeof(struct idletimer_tg_info_v1),
498+
.usersize = offsetof(struct idletimer_tg_info_v1, timer),
499+
.checkentry = idletimer_tg_checkentry_v1,
500+
.destroy = idletimer_tg_destroy_v1,
501+
.me = THIS_MODULE,
502+
},
503+
#endif
483504
};
484505

485506
static struct class *idletimer_tg_class;

‎net/netfilter/xt_LED.c

+27-12
Original file line numberDiff line numberDiff line change
@@ -175,26 +175,41 @@ static void led_tg_destroy(const struct xt_tgdtor_param *par)
175175
kfree(ledinternal);
176176
}
177177

178-
static struct xt_target led_tg_reg __read_mostly = {
179-
.name = "LED",
180-
.revision = 0,
181-
.family = NFPROTO_UNSPEC,
182-
.target = led_tg,
183-
.targetsize = sizeof(struct xt_led_info),
184-
.usersize = offsetof(struct xt_led_info, internal_data),
185-
.checkentry = led_tg_check,
186-
.destroy = led_tg_destroy,
187-
.me = THIS_MODULE,
178+
static struct xt_target led_tg_reg[] __read_mostly = {
179+
{
180+
.name = "LED",
181+
.revision = 0,
182+
.family = NFPROTO_IPV4,
183+
.target = led_tg,
184+
.targetsize = sizeof(struct xt_led_info),
185+
.usersize = offsetof(struct xt_led_info, internal_data),
186+
.checkentry = led_tg_check,
187+
.destroy = led_tg_destroy,
188+
.me = THIS_MODULE,
189+
},
190+
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
191+
{
192+
.name = "LED",
193+
.revision = 0,
194+
.family = NFPROTO_IPV6,
195+
.target = led_tg,
196+
.targetsize = sizeof(struct xt_led_info),
197+
.usersize = offsetof(struct xt_led_info, internal_data),
198+
.checkentry = led_tg_check,
199+
.destroy = led_tg_destroy,
200+
.me = THIS_MODULE,
201+
},
202+
#endif
188203
};
189204

190205
static int __init led_tg_init(void)
191206
{
192-
return xt_register_target(&led_tg_reg);
207+
return xt_register_targets(led_tg_reg, ARRAY_SIZE(led_tg_reg));
193208
}
194209

195210
static void __exit led_tg_exit(void)
196211
{
197-
xt_unregister_target(&led_tg_reg);
212+
xt_unregister_targets(led_tg_reg, ARRAY_SIZE(led_tg_reg));
198213
}
199214

200215
module_init(led_tg_init);

0 commit comments

Comments
 (0)