neigh: disallow un-init_net to change thresh of neigh
[linux-2.6-microblaze.git] / net / core / neighbour.c
index 5c56b21..2569ab2 100644 (file)
@@ -1419,7 +1419,7 @@ static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
 
        for (p = &tbl->parms; p; p = p->next) {
                if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
-                   (!p->dev && !ifindex))
+                   (!p->dev && !ifindex && net_eq(net, &init_net)))
                        return p;
        }
 
@@ -1429,15 +1429,11 @@ static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
 struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                                      struct neigh_table *tbl)
 {
-       struct neigh_parms *p, *ref;
+       struct neigh_parms *p;
        struct net *net = dev_net(dev);
        const struct net_device_ops *ops = dev->netdev_ops;
 
-       ref = lookup_neigh_parms(tbl, net, 0);
-       if (!ref)
-               return NULL;
-
-       p = kmemdup(ref, sizeof(*p), GFP_KERNEL);
+       p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
        if (p) {
                p->tbl            = tbl;
                atomic_set(&p->refcnt, 1);
@@ -2053,6 +2049,12 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
                }
        }
 
+       err = -ENOENT;
+       if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
+            tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
+           !net_eq(net, &init_net))
+               goto errout_tbl_lock;
+
        if (tb[NDTA_THRESH1])
                tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
 
@@ -2765,11 +2767,11 @@ EXPORT_SYMBOL(neigh_app_ns);
 static int zero;
 static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
 
-static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer,
-                          size_t *lenp, loff_t *ppos)
+static int proc_unres_qlen(struct ctl_table *ctl, int write,
+                          void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int size, ret;
-       ctl_table tmp = *ctl;
+       struct ctl_table tmp = *ctl;
 
        tmp.extra1 = &zero;
        tmp.extra2 = &unres_qlen_max;