diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2016-10-24 22:11:26 +0300 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2016-11-24 18:23:52 +0300 |
commit | 9b3ae9969e68ca4b19e475869dd425d21973524e (patch) | |
tree | 34ef166e8ea9e911d6d4fa21f75722e196c3135a /net/can | |
parent | 2cc109fc7bc51a3593924302bd87f393d6b95f06 (diff) | |
download | linux-9b3ae9969e68ca4b19e475869dd425d21973524e.tar.xz |
can: bcm: fix warning in bcm_connect/proc_register
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: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'net/can')
-rw-r--r-- | net/can/bcm.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c index b57452a65fb9..392a687d3ca6 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1500,24 +1500,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; @@ -1528,17 +1535,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, |