forked from mirrors/linux
		
	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:
		
							parent
							
								
									a95a7774d5
								
							
						
					
					
						commit
						8866df9264
					
				
					 1 changed files with 40 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -382,7 +382,8 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl,
 | 
			
		|||
static int
 | 
			
		||||
cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
 | 
			
		||||
			    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 nfgenmsg *nfmsg;
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +409,7 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
 | 
			
		|||
	if (!nest_parms)
 | 
			
		||||
		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)
 | 
			
		||||
		goto nla_put_failure;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -430,6 +431,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
 | 
			
		|||
				 struct netlink_ext_ack *extack)
 | 
			
		||||
{
 | 
			
		||||
	const struct nf_conntrack_l4proto *l4proto;
 | 
			
		||||
	unsigned int *timeouts = NULL;
 | 
			
		||||
	struct sk_buff *skb2;
 | 
			
		||||
	int ret, err;
 | 
			
		||||
	__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]);
 | 
			
		||||
	l4proto = nf_ct_l4proto_find_get(l4num);
 | 
			
		||||
 | 
			
		||||
	/* This protocol is not supported, skip. */
 | 
			
		||||
	if (l4proto->l4proto != l4num) {
 | 
			
		||||
		err = -EOPNOTSUPP;
 | 
			
		||||
	err = -EOPNOTSUPP;
 | 
			
		||||
	if (l4proto->l4proto != l4num)
 | 
			
		||||
		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);
 | 
			
		||||
	if (skb2 == NULL) {
 | 
			
		||||
		err = -ENOMEM;
 | 
			
		||||
| 
						 | 
				
			
			@ -458,8 +492,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
 | 
			
		|||
					  nlh->nlmsg_seq,
 | 
			
		||||
					  NFNL_MSG_TYPE(nlh->nlmsg_type),
 | 
			
		||||
					  IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
 | 
			
		||||
					  l3num,
 | 
			
		||||
					  l4proto);
 | 
			
		||||
					  l3num, l4proto, timeouts);
 | 
			
		||||
	if (ret <= 0) {
 | 
			
		||||
		kfree_skb(skb2);
 | 
			
		||||
		err = -ENOMEM;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue