datapath: Hold mutex for DP while userspace is blocking on read.
[openvswitch] / datapath / brcompat.c
index f68b698c47b4d8d95228a1fe42293a9585910ff2..f23db93cefd417529a2cb73804ad2ed24b6c0678 100644 (file)
@@ -6,6 +6,8 @@
  * kernel, by Linus Torvalds and others.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
 #include <linux/completion.h>
@@ -82,6 +84,9 @@ static int brc_add_del_bridge(char __user *uname, int add)
        struct sk_buff *request;
        char name[IFNAMSIZ];
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (copy_from_user(name, uname, IFNAMSIZ))
                return -EFAULT;
 
@@ -194,6 +199,9 @@ static int brc_add_del_port(struct net_device *dev, int port_ifindex, int add)
        struct net_device *port;
        int err;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        port = __dev_get_by_index(&init_net, port_ifindex);
        if (!port)
                return -EINVAL;
@@ -216,14 +224,13 @@ static int brc_get_bridge_info(struct net_device *dev,
                               struct __bridge_info __user *ub)
 {
        struct __bridge_info b;
-       u64 id = 0;
-       int i;
 
        memset(&b, 0, sizeof(struct __bridge_info));
 
-       for (i=0; i<ETH_ALEN; i++)
-               id |= (u64)dev->dev_addr[i] << (8*(ETH_ALEN-1 - i));
-       b.bridge_id = cpu_to_be64(id);
+       /* First two bytes are the priority, which we should skip.  This comes
+        * from struct bridge_id in br_private.h, which is unavailable to us.
+        */
+       memcpy((u8 *)&b.bridge_id + 2, dev->dev_addr, ETH_ALEN);
        b.stp_enabled = 0;
 
        if (copy_to_user(ub, &b, sizeof(struct __bridge_info)))
@@ -481,7 +488,7 @@ static struct sk_buff *brc_send_command(struct sk_buff *request,
        /* Wait for reply. */
        error = -ETIMEDOUT;
        if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT)) {
-               printk(KERN_WARNING "brcompat: timed out waiting for userspace\n");
+               pr_warn("timed out waiting for userspace\n");
                goto error;
     }
 
@@ -551,7 +558,7 @@ static int __init brc_init(void)
 err_unregister:
        genl_unregister_family(&brc_genl_family);
 error:
-       printk(KERN_EMERG "brcompat: failed to install!");
+       pr_emerg("failed to install!\n");
        return err;
 }