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 <zhangshen...@cmss.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.

Reply via email to