Commit 89259088 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

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: 8866df92 ("netfilter: nfnetlink_cttimeout: pass default timeout policy to obj_to_nlattr")
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 2a31e4bd
...@@ -21,6 +21,19 @@ struct nf_ct_gre_keymap { ...@@ -21,6 +21,19 @@ struct nf_ct_gre_keymap {
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
}; };
enum grep_conntrack {
GRE_CT_UNREPLIED,
GRE_CT_REPLIED,
GRE_CT_MAX
};
struct netns_proto_gre {
struct nf_proto_net nf;
rwlock_t keymap_lock;
struct list_head keymap_list;
unsigned int gre_timeouts[GRE_CT_MAX];
};
/* add new tuple->key_reply pair to keymap */ /* add new tuple->key_reply pair to keymap */
int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conntrack_tuple *t); struct nf_conntrack_tuple *t);
......
...@@ -43,24 +43,12 @@ ...@@ -43,24 +43,12 @@
#include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <linux/netfilter/nf_conntrack_pptp.h> #include <linux/netfilter/nf_conntrack_pptp.h>
enum grep_conntrack {
GRE_CT_UNREPLIED,
GRE_CT_REPLIED,
GRE_CT_MAX
};
static const unsigned int gre_timeouts[GRE_CT_MAX] = { static const unsigned int gre_timeouts[GRE_CT_MAX] = {
[GRE_CT_UNREPLIED] = 30*HZ, [GRE_CT_UNREPLIED] = 30*HZ,
[GRE_CT_REPLIED] = 180*HZ, [GRE_CT_REPLIED] = 180*HZ,
}; };
static unsigned int proto_gre_net_id __read_mostly; static unsigned int proto_gre_net_id __read_mostly;
struct netns_proto_gre {
struct nf_proto_net nf;
rwlock_t keymap_lock;
struct list_head keymap_list;
unsigned int gre_timeouts[GRE_CT_MAX];
};
static inline struct netns_proto_gre *gre_pernet(struct net *net) static inline struct netns_proto_gre *gre_pernet(struct net *net)
{ {
...@@ -402,6 +390,8 @@ static int __init nf_ct_proto_gre_init(void) ...@@ -402,6 +390,8 @@ static int __init nf_ct_proto_gre_init(void)
{ {
int ret; int ret;
BUILD_BUG_ON(offsetof(struct netns_proto_gre, nf) != 0);
ret = register_pernet_subsys(&proto_gre_net_ops); ret = register_pernet_subsys(&proto_gre_net_ops);
if (ret < 0) if (ret < 0)
goto out_pernet; goto out_pernet;
......
...@@ -455,7 +455,8 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, ...@@ -455,7 +455,8 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
case IPPROTO_TCP: case IPPROTO_TCP:
timeouts = nf_tcp_pernet(net)->timeouts; timeouts = nf_tcp_pernet(net)->timeouts;
break; break;
case IPPROTO_UDP: case IPPROTO_UDP: /* fallthrough */
case IPPROTO_UDPLITE:
timeouts = nf_udp_pernet(net)->timeouts; timeouts = nf_udp_pernet(net)->timeouts;
break; break;
case IPPROTO_DCCP: case IPPROTO_DCCP:
...@@ -469,13 +470,23 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, ...@@ -469,13 +470,23 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
case IPPROTO_SCTP: case IPPROTO_SCTP:
#ifdef CONFIG_NF_CT_PROTO_SCTP #ifdef CONFIG_NF_CT_PROTO_SCTP
timeouts = nf_sctp_pernet(net)->timeouts; timeouts = nf_sctp_pernet(net)->timeouts;
#endif
break;
case IPPROTO_GRE:
#ifdef CONFIG_NF_CT_PROTO_GRE
if (l4proto->net_id) {
struct netns_proto_gre *net_gre;
net_gre = net_generic(net, *l4proto->net_id);
timeouts = net_gre->gre_timeouts;
}
#endif #endif
break; break;
case 255: case 255:
timeouts = &nf_generic_pernet(net)->timeout; timeouts = &nf_generic_pernet(net)->timeout;
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto);
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment