Commit 89259088c1b7fecb43e8e245dc931909132a4e03
Committed by
Pablo Neira Ayuso
1 parent
2a31e4bd9a
netfilter: nfnetlink_cttimeout: fetch timeouts for udplite and gre, too
syzbot was able to trigger the WARN in cttimeout_default_get() by passing UDPLITE as l4protocol. Alias UDPLITE to UDP, both use same timeout values. Furthermore, also fetch GRE timeouts. GRE is a bit more complicated, as it still can be a module and its netns_proto_gre struct layout isn't visible outside of the gre module. Can't move timeouts around, it appears conntrack sysctl unregister assumes net_generic() returns nf_proto_net, so we get crash. Expose layout of netns_proto_gre instead. A followup nf-next patch could make gre tracker be built-in as well if needed, its not that large. Last, make the WARN() mention the missing protocol value in case anything else is missing. Reported-by: syzbot+2fae8fa157dd92618cae@syzkaller.appspotmail.com Fixes: 8866df9264a3 ("netfilter: nfnetlink_cttimeout: pass default timeout policy to obj_to_nlattr") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Showing 3 changed files with 28 additions and 14 deletions Side-by-side Diff
include/linux/netfilter/nf_conntrack_proto_gre.h
... | ... | @@ -21,6 +21,19 @@ |
21 | 21 | struct nf_conntrack_tuple tuple; |
22 | 22 | }; |
23 | 23 | |
24 | +enum grep_conntrack { | |
25 | + GRE_CT_UNREPLIED, | |
26 | + GRE_CT_REPLIED, | |
27 | + GRE_CT_MAX | |
28 | +}; | |
29 | + | |
30 | +struct netns_proto_gre { | |
31 | + struct nf_proto_net nf; | |
32 | + rwlock_t keymap_lock; | |
33 | + struct list_head keymap_list; | |
34 | + unsigned int gre_timeouts[GRE_CT_MAX]; | |
35 | +}; | |
36 | + | |
24 | 37 | /* add new tuple->key_reply pair to keymap */ |
25 | 38 | int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, |
26 | 39 | struct nf_conntrack_tuple *t); |
net/netfilter/nf_conntrack_proto_gre.c
... | ... | @@ -43,24 +43,12 @@ |
43 | 43 | #include <linux/netfilter/nf_conntrack_proto_gre.h> |
44 | 44 | #include <linux/netfilter/nf_conntrack_pptp.h> |
45 | 45 | |
46 | -enum grep_conntrack { | |
47 | - GRE_CT_UNREPLIED, | |
48 | - GRE_CT_REPLIED, | |
49 | - GRE_CT_MAX | |
50 | -}; | |
51 | - | |
52 | 46 | static const unsigned int gre_timeouts[GRE_CT_MAX] = { |
53 | 47 | [GRE_CT_UNREPLIED] = 30*HZ, |
54 | 48 | [GRE_CT_REPLIED] = 180*HZ, |
55 | 49 | }; |
56 | 50 | |
57 | 51 | static unsigned int proto_gre_net_id __read_mostly; |
58 | -struct netns_proto_gre { | |
59 | - struct nf_proto_net nf; | |
60 | - rwlock_t keymap_lock; | |
61 | - struct list_head keymap_list; | |
62 | - unsigned int gre_timeouts[GRE_CT_MAX]; | |
63 | -}; | |
64 | 52 | |
65 | 53 | static inline struct netns_proto_gre *gre_pernet(struct net *net) |
66 | 54 | { |
... | ... | @@ -401,6 +389,8 @@ |
401 | 389 | static int __init nf_ct_proto_gre_init(void) |
402 | 390 | { |
403 | 391 | int ret; |
392 | + | |
393 | + BUILD_BUG_ON(offsetof(struct netns_proto_gre, nf) != 0); | |
404 | 394 | |
405 | 395 | ret = register_pernet_subsys(&proto_gre_net_ops); |
406 | 396 | if (ret < 0) |
net/netfilter/nfnetlink_cttimeout.c
... | ... | @@ -455,7 +455,8 @@ |
455 | 455 | case IPPROTO_TCP: |
456 | 456 | timeouts = nf_tcp_pernet(net)->timeouts; |
457 | 457 | break; |
458 | - case IPPROTO_UDP: | |
458 | + case IPPROTO_UDP: /* fallthrough */ | |
459 | + case IPPROTO_UDPLITE: | |
459 | 460 | timeouts = nf_udp_pernet(net)->timeouts; |
460 | 461 | break; |
461 | 462 | case IPPROTO_DCCP: |
462 | 463 | |
... | ... | @@ -471,11 +472,21 @@ |
471 | 472 | timeouts = nf_sctp_pernet(net)->timeouts; |
472 | 473 | #endif |
473 | 474 | break; |
475 | + case IPPROTO_GRE: | |
476 | +#ifdef CONFIG_NF_CT_PROTO_GRE | |
477 | + if (l4proto->net_id) { | |
478 | + struct netns_proto_gre *net_gre; | |
479 | + | |
480 | + net_gre = net_generic(net, *l4proto->net_id); | |
481 | + timeouts = net_gre->gre_timeouts; | |
482 | + } | |
483 | +#endif | |
484 | + break; | |
474 | 485 | case 255: |
475 | 486 | timeouts = &nf_generic_pernet(net)->timeout; |
476 | 487 | break; |
477 | 488 | default: |
478 | - WARN_ON_ONCE(1); | |
489 | + WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto); | |
479 | 490 | break; |
480 | 491 | } |
481 | 492 |