Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
[sfrench/cifs-2.6.git] / net / core / dev.c
index 7aeefc467ddc575c65934c0bddabce86fec6defd..8f1a47ad6781abc30099dc1de6bd6f0ad5df7135 100644 (file)
@@ -9712,14 +9712,17 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
        struct net_device *dev;
        int err, fd;
 
+       rtnl_lock();
        dev = dev_get_by_index(net, attr->link_create.target_ifindex);
-       if (!dev)
+       if (!dev) {
+               rtnl_unlock();
                return -EINVAL;
+       }
 
        link = kzalloc(sizeof(*link), GFP_USER);
        if (!link) {
                err = -ENOMEM;
-               goto out_put_dev;
+               goto unlock;
        }
 
        bpf_link_init(&link->link, BPF_LINK_TYPE_XDP, &bpf_xdp_link_lops, prog);
@@ -9729,14 +9732,14 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
        err = bpf_link_prime(&link->link, &link_primer);
        if (err) {
                kfree(link);
-               goto out_put_dev;
+               goto unlock;
        }
 
-       rtnl_lock();
        err = dev_xdp_attach_link(dev, NULL, link);
        rtnl_unlock();
 
        if (err) {
+               link->dev = NULL;
                bpf_link_cleanup(&link_primer);
                goto out_put_dev;
        }
@@ -9746,6 +9749,9 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
        dev_put(dev);
        return fd;
 
+unlock:
+       rtnl_unlock();
+
 out_put_dev:
        dev_put(dev);
        return err;