lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 27 Nov 2016 19:09:30 -0700
From:   David Ahern <dsa@...ulusnetworks.com>
To:     Zhang Shengju <zhangshengju@...s.chinamobile.com>,
        netdev@...r.kernel.org
Subject: Re: [net,v2] neigh: fix the loop index error in neigh dump

On 11/27/16 6:32 PM, Zhang Shengju wrote:
> Loop index in neigh dump function is not updated correctly under some
> circumstances, this patch will fix it.

What's an example?

> 
> Fixes: 16660f0bd9 ("net: Add support for filtering neigh dump by device index")
> Fixes: 21fdd092ac ("net: Add support for filtering neigh dump by master device")
> 
> Signed-off-by: Zhang Shengju <zhangshengju@...s.chinamobile.com>
> ---
>  net/core/neighbour.c | 39 ++++++++++++++++++---------------------
>  1 file changed, 18 insertions(+), 21 deletions(-)
> 
> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index 2ae929f..ce32e9c 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -2256,6 +2256,16 @@ static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
>  	return false;
>  }
>  
> +static bool neigh_dump_filtered(struct net_device *dev, int filter_idx,
> +		int filter_master_idx)
> +{
> +	if (neigh_ifindex_filtered(dev, filter_idx) ||
> +	    neigh_master_filtered(dev, filter_master_idx))
> +		return true;
> +
> +	return false;
> +}
> +
>  static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
>  			    struct netlink_callback *cb)
>  {
> @@ -2285,20 +2295,15 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
>  	rcu_read_lock_bh();
>  	nht = rcu_dereference_bh(tbl->nht);
>  
> -	for (h = s_h; h < (1 << nht->hash_shift); h++) {
> -		if (h > s_h)
> -			s_idx = 0;
> +	for (h = s_h; h < (1 << nht->hash_shift); h++, s_idx = 0) {
>  		for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
>  		     n != NULL;
> -		     n = rcu_dereference_bh(n->next)) {
> -			if (!net_eq(dev_net(n->dev), net))
> -				continue;
> -			if (neigh_ifindex_filtered(n->dev, filter_idx))
> +		     n = rcu_dereference_bh(n->next), idx++) {
> +			if (idx < s_idx || !net_eq(dev_net(n->dev), net))
>  				continue;
> -			if (neigh_master_filtered(n->dev, filter_master_idx))
> +			if (neigh_dump_filtered(n->dev, filter_idx,
> +						filter_master_idx))
>  				continue;
> -			if (idx < s_idx)
> -				goto next;
>  			if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
>  					    cb->nlh->nlmsg_seq,
>  					    RTM_NEWNEIGH,
> @@ -2306,8 +2311,6 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
>  				rc = -1;
>  				goto out;
>  			}
> -next:
> -			idx++;
>  		}
>  	}
>  	rc = skb->len;
> @@ -2328,14 +2331,10 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
>  
>  	read_lock_bh(&tbl->lock);
>  
> -	for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
> -		if (h > s_h)
> -			s_idx = 0;
> -		for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
> -			if (pneigh_net(n) != net)
> +	for (h = s_h; h <= PNEIGH_HASHMASK; h++, s_idx = 0) {
> +		for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next, idx++) {
> +			if (idx < s_idx || pneigh_net(n) != net)
>  				continue;
> -			if (idx < s_idx)
> -				goto next;
>  			if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
>  					    cb->nlh->nlmsg_seq,
>  					    RTM_NEWNEIGH,
> @@ -2344,8 +2343,6 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
>  				rc = -1;
>  				goto out;
>  			}
> -		next:
> -			idx++;
>  		}
>  	}
>  

This fix is way to be complicated to be fixing anything related to 16660f0bd9 or 21fdd092ac. Both of those commits added a continue:

                        if (neigh_ifindex_filtered(n->dev, filter_idx))
                                continue;
                        if (neigh_master_filtered(n->dev, filter_master_idx))
                                continue;

At best the continue is replaced by 'goto next;' and I am not convinced that is right.

You are completely rewriting the dump loops.

Powered by blists - more mailing lists