mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
can: isotp: fix error path in isotp_sendmsg() to unlock wait queue
commit8375dfac4f
upstream. Commit43a08c3bda
("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:43a08c3bda
("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>
This commit is contained in:
parent
f90cc68f9f
commit
540dff311c
@ -887,7 +887,7 @@ 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;
|
||||
}
|
||||
|
||||
/* take care of a potential SF_DL ESC offset for TX_DL > 8 */
|
||||
@ -897,24 +897,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||
if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) &&
|
||||
(size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) {
|
||||
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);
|
||||
@ -976,7 +976,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 %pe\n",
|
||||
__func__, ERR_PTR(err));
|
||||
goto err_out;
|
||||
goto err_out_drop;
|
||||
}
|
||||
|
||||
if (wait_tx_done) {
|
||||
@ -989,6 +989,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)
|
||||
|
Loading…
Reference in New Issue
Block a user