Skip to content

Commit

Permalink
can: isotp: fix error path in isotp_sendmsg() to unlock wait queue
Browse files Browse the repository at this point in the history
commit 8375dfa upstream.

Commit 43a08c3 ("can: isotp: isotp_sendmsg(): fix TX buffer concurrent
access in isotp_sendmsg()") introduced a new locking scheme that may render
the userspace application in a locking state when an error is detected.
This issue shows up under high load on simultaneously running isotp channels
with identical configuration which is against the ISO specification and
therefore breaks any reasonable PDU communication anyway.

Fixes: 43a08c3 ("can: isotp: isotp_sendmsg(): fix TX buffer concurrent access in isotp_sendmsg()")
Link: https://lore.kernel.org/all/20220209073601.25728-1-socketcan@hartkopp.net
Cc: stable@vger.kernel.org
Cc: Ziyang Xuan <william.xuanziyang@huawei.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
hartkopp authored and gregkh committed Feb 16, 2022
1 parent 3b10ebe commit 199dab0
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions net/can/isotp.c
Expand Up @@ -885,24 +885,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)

if (!size || size > MAX_MSG_LENGTH) {
err = -EINVAL;
goto err_out;
goto err_out_drop;
}

err = memcpy_from_msg(so->tx.buf, msg, size);
if (err < 0)
goto err_out;
goto err_out_drop;

dev = dev_get_by_index(sock_net(sk), so->ifindex);
if (!dev) {
err = -ENXIO;
goto err_out;
goto err_out_drop;
}

skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv),
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb) {
dev_put(dev);
goto err_out;
goto err_out_drop;
}

can_skb_reserve(skb);
Expand Down Expand Up @@ -967,7 +967,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (err) {
pr_notice_once("can-isotp: %s: can_send_ret %d\n",
__func__, err);
goto err_out;
goto err_out_drop;
}

if (wait_tx_done) {
Expand All @@ -980,6 +980,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)

return size;

err_out_drop:
/* drop this PDU and unlock a potential wait queue */
old_state = ISOTP_IDLE;
err_out:
so->tx.state = old_state;
if (so->tx.state == ISOTP_IDLE)
Expand Down

0 comments on commit 199dab0

Please sign in to comment.