can: bcm: fix warning in bcm_connect/proc_register
authorOliver Hartkopp <socketcan@hartkopp.net>
Mon, 24 Oct 2016 19:11:26 +0000 (21:11 +0200)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 23 Feb 2017 03:50:57 +0000 (03:50 +0000)
commit deb507f91f1adbf64317ad24ac46c56eeccfb754 upstream.

Andrey Konovalov reported an issue with proc_register in bcm.c.
As suggested by Cong Wang this patch adds a lock_sock() protection and
a check for unsuccessful proc_create_data() in bcm_connect().

Reference: http://marc.info/?l=linux-netdev&m=147732648731237

Reported-by: Andrey Konovalov <andreyknvl@google.com>
Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Tested-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
net/can/bcm.c

index 3910c1f..c297974 100644 (file)
@@ -1494,24 +1494,31 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
        struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
        struct sock *sk = sock->sk;
        struct bcm_sock *bo = bcm_sk(sk);
+       int ret = 0;
 
        if (len < sizeof(*addr))
                return -EINVAL;
 
-       if (bo->bound)
-               return -EISCONN;
+       lock_sock(sk);
+
+       if (bo->bound) {
+               ret = -EISCONN;
+               goto fail;
+       }
 
        /* bind a device to this socket */
        if (addr->can_ifindex) {
                struct net_device *dev;
 
                dev = dev_get_by_index(&init_net, addr->can_ifindex);
-               if (!dev)
-                       return -ENODEV;
-
+               if (!dev) {
+                       ret = -ENODEV;
+                       goto fail;
+               }
                if (dev->type != ARPHRD_CAN) {
                        dev_put(dev);
-                       return -ENODEV;
+                       ret = -ENODEV;
+                       goto fail;
                }
 
                bo->ifindex = dev->ifindex;
@@ -1522,17 +1529,24 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
                bo->ifindex = 0;
        }
 
-       bo->bound = 1;
-
        if (proc_dir) {
                /* unique socket address as filename */
                sprintf(bo->procname, "%lu", sock_i_ino(sk));
                bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
                                                     proc_dir,
                                                     &bcm_proc_fops, sk);
+               if (!bo->bcm_proc_read) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
        }
 
-       return 0;
+       bo->bound = 1;
+
+fail:
+       release_sock(sk);
+
+       return ret;
 }
 
 static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock,