]>
Commit | Line | Data |
---|---|---|
eb2c670e SLM |
1 | From f6ba29638407e087751948214419fb695cec8347 Mon Sep 17 00:00:00 2001 |
2 | From: Pablo Neira Ayuso <pablo@netfilter.org> | |
3 | Date: Fri, 12 Apr 2019 10:55:02 -0700 | |
4 | Subject: netfilter: nfnetlink_cttimeout: pass default timeout policy to | |
5 | obj_to_nlattr | |
6 | ||
7 | commit 8866df9264a34e675b4ee8a151db819b87cce2d3 upstream | |
8 | ||
9 | Otherwise, we hit a NULL pointer deference since handlers always assume | |
10 | default timeout policy is passed. | |
11 | ||
12 | netlink: 24 bytes leftover after parsing attributes in process `syz-executor2'. | |
13 | kasan: CONFIG_KASAN_INLINE enabled | |
14 | kasan: GPF could be caused by NULL-ptr deref or user memory access | |
15 | general protection fault: 0000 [#1] PREEMPT SMP KASAN | |
16 | CPU: 0 PID: 9575 Comm: syz-executor1 Not tainted 4.19.0+ #312 | |
17 | Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 | |
18 | RIP: 0010:icmp_timeout_obj_to_nlattr+0x77/0x170 net/netfilter/nf_conntrack_proto_icmp.c:297 | |
19 | ||
20 | Fixes: c779e849608a ("netfilter: conntrack: remove get_timeout() indirection") | |
21 | Reported-by: Eric Dumazet <eric.dumazet@gmail.com> | |
22 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> | |
23 | Signed-off-by: Zubin Mithra <zsm@chromium.org> | |
24 | Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org> | |
25 | --- | |
26 | net/netfilter/nfnetlink_cttimeout.c | 46 +++++++++++++++++++++++++---- | |
27 | 1 file changed, 40 insertions(+), 6 deletions(-) | |
28 | ||
29 | diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c | |
30 | index a30f8ba4b89a..1dc4ea327cbe 100644 | |
31 | --- a/net/netfilter/nfnetlink_cttimeout.c | |
32 | +++ b/net/netfilter/nfnetlink_cttimeout.c | |
33 | @@ -392,7 +392,8 @@ err: | |
34 | static int | |
35 | cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, | |
36 | u32 seq, u32 type, int event, | |
37 | - const struct nf_conntrack_l4proto *l4proto) | |
38 | + const struct nf_conntrack_l4proto *l4proto, | |
39 | + const unsigned int *timeouts) | |
40 | { | |
41 | struct nlmsghdr *nlh; | |
42 | struct nfgenmsg *nfmsg; | |
43 | @@ -421,7 +422,7 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, | |
44 | if (!nest_parms) | |
45 | goto nla_put_failure; | |
46 | ||
47 | - ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, NULL); | |
48 | + ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts); | |
49 | if (ret < 0) | |
50 | goto nla_put_failure; | |
51 | ||
52 | @@ -444,6 +445,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |
53 | struct netlink_ext_ack *extack) | |
54 | { | |
55 | const struct nf_conntrack_l4proto *l4proto; | |
56 | + unsigned int *timeouts = NULL; | |
57 | struct sk_buff *skb2; | |
58 | int ret, err; | |
59 | __u16 l3num; | |
60 | @@ -456,12 +458,44 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |
61 | l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); | |
62 | l4proto = nf_ct_l4proto_find_get(l3num, l4num); | |
63 | ||
64 | - /* This protocol is not supported, skip. */ | |
65 | - if (l4proto->l4proto != l4num) { | |
66 | - err = -EOPNOTSUPP; | |
67 | + err = -EOPNOTSUPP; | |
68 | + if (l4proto->l4proto != l4num) | |
69 | goto err; | |
70 | + | |
71 | + switch (l4proto->l4proto) { | |
72 | + case IPPROTO_ICMP: | |
73 | + timeouts = &net->ct.nf_ct_proto.icmp.timeout; | |
74 | + break; | |
75 | + case IPPROTO_TCP: | |
76 | + timeouts = net->ct.nf_ct_proto.tcp.timeouts; | |
77 | + break; | |
78 | + case IPPROTO_UDP: | |
79 | + timeouts = net->ct.nf_ct_proto.udp.timeouts; | |
80 | + break; | |
81 | + case IPPROTO_DCCP: | |
82 | +#ifdef CONFIG_NF_CT_PROTO_DCCP | |
83 | + timeouts = net->ct.nf_ct_proto.dccp.dccp_timeout; | |
84 | +#endif | |
85 | + break; | |
86 | + case IPPROTO_ICMPV6: | |
87 | + timeouts = &net->ct.nf_ct_proto.icmpv6.timeout; | |
88 | + break; | |
89 | + case IPPROTO_SCTP: | |
90 | +#ifdef CONFIG_NF_CT_PROTO_SCTP | |
91 | + timeouts = net->ct.nf_ct_proto.sctp.timeouts; | |
92 | +#endif | |
93 | + break; | |
94 | + case 255: | |
95 | + timeouts = &net->ct.nf_ct_proto.generic.timeout; | |
96 | + break; | |
97 | + default: | |
98 | + WARN_ON_ONCE(1); | |
99 | + break; | |
100 | } | |
101 | ||
102 | + if (!timeouts) | |
103 | + goto err; | |
104 | + | |
105 | skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | |
106 | if (skb2 == NULL) { | |
107 | err = -ENOMEM; | |
108 | @@ -472,7 +506,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |
109 | nlh->nlmsg_seq, | |
110 | NFNL_MSG_TYPE(nlh->nlmsg_type), | |
111 | IPCTNL_MSG_TIMEOUT_DEFAULT_SET, | |
112 | - l4proto); | |
113 | + l4proto, timeouts); | |
114 | if (ret <= 0) { | |
115 | kfree_skb(skb2); | |
116 | err = -ENOMEM; | |
117 | -- | |
118 | 2.19.1 | |
119 |