Commit 89259088c1b7fecb43e8e245dc931909132a4e03

Authored by Florian Westphal
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