diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2016-10-24 15:11:26 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2016-10-31 15:48:19 -0400 |
commit | deb507f91f1adbf64317ad24ac46c56eeccfb754 (patch) | |
tree | b8fb378600f3f87550ba29171f0993a1f10fe7b4 | |
parent | 460d2830b00db407be2b72ed792eb3596f245192 (diff) |
can: bcm: fix warning in bcm_connect/proc_register
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>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-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 8e999ffdf28b..8af9d25ff988 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -1549,24 +1549,31 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, | |||
1549 | struct sockaddr_can *addr = (struct sockaddr_can *)uaddr; | 1549 | struct sockaddr_can *addr = (struct sockaddr_can *)uaddr; |
1550 | struct sock *sk = sock->sk; | 1550 | struct sock *sk = sock->sk; |
1551 | struct bcm_sock *bo = bcm_sk(sk); | 1551 | struct bcm_sock *bo = bcm_sk(sk); |
1552 | int ret = 0; | ||
1552 | 1553 | ||
1553 | if (len < sizeof(*addr)) | 1554 | if (len < sizeof(*addr)) |
1554 | return -EINVAL; | 1555 | return -EINVAL; |
1555 | 1556 | ||
1556 | if (bo->bound) | 1557 | lock_sock(sk); |
1557 | return -EISCONN; | 1558 | |
1559 | if (bo->bound) { | ||
1560 | ret = -EISCONN; | ||
1561 | goto fail; | ||
1562 | } | ||
1558 | 1563 | ||
1559 | /* bind a device to this socket */ | 1564 | /* bind a device to this socket */ |
1560 | if (addr->can_ifindex) { | 1565 | if (addr->can_ifindex) { |
1561 | struct net_device *dev; | 1566 | struct net_device *dev; |
1562 | 1567 | ||
1563 | dev = dev_get_by_index(&init_net, addr->can_ifindex); | 1568 | dev = dev_get_by_index(&init_net, addr->can_ifindex); |
1564 | if (!dev) | 1569 | if (!dev) { |
1565 | return -ENODEV; | 1570 | ret = -ENODEV; |
1566 | 1571 | goto fail; | |
1572 | } | ||
1567 | if (dev->type != ARPHRD_CAN) { | 1573 | if (dev->type != ARPHRD_CAN) { |
1568 | dev_put(dev); | 1574 | dev_put(dev); |
1569 | return -ENODEV; | 1575 | ret = -ENODEV; |
1576 | goto fail; | ||
1570 | } | 1577 | } |
1571 | 1578 | ||
1572 | bo->ifindex = dev->ifindex; | 1579 | bo->ifindex = dev->ifindex; |
@@ -1577,17 +1584,24 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, | |||
1577 | bo->ifindex = 0; | 1584 | bo->ifindex = 0; |
1578 | } | 1585 | } |
1579 | 1586 | ||
1580 | bo->bound = 1; | ||
1581 | |||
1582 | if (proc_dir) { | 1587 | if (proc_dir) { |
1583 | /* unique socket address as filename */ | 1588 | /* unique socket address as filename */ |
1584 | sprintf(bo->procname, "%lu", sock_i_ino(sk)); | 1589 | sprintf(bo->procname, "%lu", sock_i_ino(sk)); |
1585 | bo->bcm_proc_read = proc_create_data(bo->procname, 0644, | 1590 | bo->bcm_proc_read = proc_create_data(bo->procname, 0644, |
1586 | proc_dir, | 1591 | proc_dir, |
1587 | &bcm_proc_fops, sk); | 1592 | &bcm_proc_fops, sk); |
1593 | if (!bo->bcm_proc_read) { | ||
1594 | ret = -ENOMEM; | ||
1595 | goto fail; | ||
1596 | } | ||
1588 | } | 1597 | } |
1589 | 1598 | ||
1590 | return 0; | 1599 | bo->bound = 1; |
1600 | |||
1601 | fail: | ||
1602 | release_sock(sk); | ||
1603 | |||
1604 | return ret; | ||
1591 | } | 1605 | } |
1592 | 1606 | ||
1593 | static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | 1607 | static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, |