netfilter: nfnetlink_cttimeout: pass default timeout policy to obj_to_nlattr
Otherwise, we hit a NULL pointer deference since handlers always assume
default timeout policy is passed.
netlink: 24 bytes leftover after parsing attributes in process `syz-executor2'.
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN
CPU: 0 PID: 9575 Comm: syz-executor1 Not tainted 4.19.0+ #312
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:icmp_timeout_obj_to_nlattr+0x77/0x170 net/netfilter/nf_conntrack_proto_icmp.c:297
Fixes: c779e84960
("netfilter: conntrack: remove get_timeout() indirection")
Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Родитель
a95a7774d5
Коммит
8866df9264
|
@ -382,7 +382,8 @@ err:
|
||||||
static int
|
static int
|
||||||
cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
|
cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
|
||||||
u32 seq, u32 type, int event, u16 l3num,
|
u32 seq, u32 type, int event, u16 l3num,
|
||||||
const struct nf_conntrack_l4proto *l4proto)
|
const struct nf_conntrack_l4proto *l4proto,
|
||||||
|
const unsigned int *timeouts)
|
||||||
{
|
{
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
struct nfgenmsg *nfmsg;
|
struct nfgenmsg *nfmsg;
|
||||||
|
@ -408,7 +409,7 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
|
||||||
if (!nest_parms)
|
if (!nest_parms)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, NULL);
|
ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
@ -430,6 +431,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
|
||||||
struct netlink_ext_ack *extack)
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
const struct nf_conntrack_l4proto *l4proto;
|
const struct nf_conntrack_l4proto *l4proto;
|
||||||
|
unsigned int *timeouts = NULL;
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
int ret, err;
|
int ret, err;
|
||||||
__u16 l3num;
|
__u16 l3num;
|
||||||
|
@ -442,12 +444,44 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
|
||||||
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
|
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
|
||||||
l4proto = nf_ct_l4proto_find_get(l4num);
|
l4proto = nf_ct_l4proto_find_get(l4num);
|
||||||
|
|
||||||
/* This protocol is not supported, skip. */
|
err = -EOPNOTSUPP;
|
||||||
if (l4proto->l4proto != l4num) {
|
if (l4proto->l4proto != l4num)
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
switch (l4proto->l4proto) {
|
||||||
|
case IPPROTO_ICMP:
|
||||||
|
timeouts = &nf_icmp_pernet(net)->timeout;
|
||||||
|
break;
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
timeouts = nf_tcp_pernet(net)->timeouts;
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
timeouts = nf_udp_pernet(net)->timeouts;
|
||||||
|
break;
|
||||||
|
case IPPROTO_DCCP:
|
||||||
|
#ifdef CONFIG_NF_CT_PROTO_DCCP
|
||||||
|
timeouts = nf_dccp_pernet(net)->dccp_timeout;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case IPPROTO_ICMPV6:
|
||||||
|
timeouts = &nf_icmpv6_pernet(net)->timeout;
|
||||||
|
break;
|
||||||
|
case IPPROTO_SCTP:
|
||||||
|
#ifdef CONFIG_NF_CT_PROTO_SCTP
|
||||||
|
timeouts = nf_sctp_pernet(net)->timeouts;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
timeouts = &nf_generic_pernet(net)->timeout;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!timeouts)
|
||||||
|
goto err;
|
||||||
|
|
||||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (skb2 == NULL) {
|
if (skb2 == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
@ -458,8 +492,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
|
||||||
nlh->nlmsg_seq,
|
nlh->nlmsg_seq,
|
||||||
NFNL_MSG_TYPE(nlh->nlmsg_type),
|
NFNL_MSG_TYPE(nlh->nlmsg_type),
|
||||||
IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
|
IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
|
||||||
l3num,
|
l3num, l4proto, timeouts);
|
||||||
l4proto);
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
kfree_skb(skb2);
|
kfree_skb(skb2);
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче