Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp721706pxb; Mon, 25 Oct 2021 17:26:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzfF7bamCWlpkfgztBlXkNtrE6QXXhxYbOX0Yvwky7VpqX6Q/I7y0RGxMQLKrBIXU+yDsaL X-Received: by 2002:a17:90b:224e:: with SMTP id hk14mr24811557pjb.224.1635207985785; Mon, 25 Oct 2021 17:26:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635207985; cv=none; d=google.com; s=arc-20160816; b=mijELw0tKQmz56VBaRuRRqTeJ74mWa3kXVYqfds9aeo0H4g7s35A96JVEYyolFgCE1 Ng851fcrbDa/A1+o09QRgL3DoA7cu1p29j2AlTjROhdIZpwOyHRwMzpAOrkA/oRl8dkx yrQ4A5jgnMmeI9/Y31KY2IErtFbBAwCQzbVZSXkskzCyVeE+i7TTTDOA1W+auuLphwAq aJcCaZ+dRBtc1aKNz2MDWPmqFosAASNqRnBTjxRff1OxWmCLLhYgEQwHAC4BgV9ZfcdE IanbwRUdcrKrFQjBPbmAJcxng1BVlsozxxs0ExO5m9nC86oz/W4/C8r91xRXmftQ+XDZ GSIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=iRN1Y/75dlXN1Bibc7Tl1brxr+svf7tEPcV13+pVyWU=; b=vC/1iaKwBoRKJg9U6N9jJHCJvbbpijHh3nFT3offFz6hsu8q9HqPvG46QYh//N+Sgy GeqAciZeAiHTLFInodRhT8XGw55DstoP0QzW2l3f20QIz6N/efYGNpM266bZcuXe/Z8k tg0e6ovhMiDCv66tpU+ZJ8AP8rQEzvhvlQal7UAZyu/LxGC7AymIHCs64h4j2goENuEG bhO/0THIKnihxX4ckP/SP1bXjwEdi7VshmgnxkxPfjUhBboDjRv/4f1PCrEvq7StUHZF kV/PEaR4ItzkXa41oL6yTfoxLAXH3aKr6pLRVjTNCd07gidqX8+jr3sjLUhA7FbsvsMI PrOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=BVklzFx2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a15si28870111pgw.185.2021.10.25.17.26.13; Mon, 25 Oct 2021 17:26:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=BVklzFx2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237331AbhJYTvr (ORCPT + 99 others); Mon, 25 Oct 2021 15:51:47 -0400 Received: from mail.kernel.org ([198.145.29.99]:37930 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237884AbhJYTqk (ORCPT ); Mon, 25 Oct 2021 15:46:40 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 646F8611C1; Mon, 25 Oct 2021 19:39:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1635190786; bh=h9NcphN82hRB/YW97j9KUPQ/d5eoeyBJyyVP4zbjNMU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BVklzFx2KIZ/Lpymk01YvhEa3FzhhaQNBivPl34yWdjhrCJhhvzqC+MTZDZzac4It p643mt2r0t3eKzqWd11SMwPHuhYKnwhirz+9cryL7qAMEB6fectGeH/KT8pfipObuW zudza5ViMVHL4J2fHNRPIW8U/LscY390rLthUUTU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ziyang Xuan , Oliver Hartkopp , Marc Kleine-Budde Subject: [PATCH 5.14 070/169] can: isotp: isotp_sendmsg(): fix TX buffer concurrent access in isotp_sendmsg() Date: Mon, 25 Oct 2021 21:14:11 +0200 Message-Id: <20211025191026.335737563@linuxfoundation.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211025191017.756020307@linuxfoundation.org> References: <20211025191017.756020307@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ziyang Xuan commit 43a08c3bdac4cb42eff8fe5e2278bffe0c5c3daa upstream. When isotp_sendmsg() concurrent, tx.state of all TX processes can be ISOTP_IDLE. The conditions so->tx.state != ISOTP_IDLE and wq_has_sleeper(&so->wait) can not protect TX buffer from being accessed by multiple TX processes. We can use cmpxchg() to try to modify tx.state to ISOTP_SENDING firstly. If the modification of the previous process succeed, the later process must wait tx.state to ISOTP_IDLE firstly. Thus, we can ensure TX buffer is accessed by only one process at the same time. And we should also restore the original tx.state at the subsequent error processes. Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol") Link: https://lore.kernel.org/all/c2517874fbdf4188585cf9ddf67a8fa74d5dbde5.1633764159.git.william.xuanziyang@huawei.com Cc: stable@vger.kernel.org Signed-off-by: Ziyang Xuan Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- net/can/isotp.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -121,7 +121,7 @@ enum { struct tpcon { int idx; int len; - u8 state; + u32 state; u8 bs; u8 sn; u8 ll_dl; @@ -848,6 +848,7 @@ static int isotp_sendmsg(struct socket * { struct sock *sk = sock->sk; struct isotp_sock *so = isotp_sk(sk); + u32 old_state = so->tx.state; struct sk_buff *skb; struct net_device *dev; struct canfd_frame *cf; @@ -860,47 +861,55 @@ static int isotp_sendmsg(struct socket * return -EADDRNOTAVAIL; /* we do not support multiple buffers - for now */ - if (so->tx.state != ISOTP_IDLE || wq_has_sleeper(&so->wait)) { - if (msg->msg_flags & MSG_DONTWAIT) - return -EAGAIN; + if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE || + wq_has_sleeper(&so->wait)) { + if (msg->msg_flags & MSG_DONTWAIT) { + err = -EAGAIN; + goto err_out; + } /* wait for complete transmission of current pdu */ err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); if (err) - return err; + goto err_out; } - if (!size || size > MAX_MSG_LENGTH) - return -EINVAL; + if (!size || size > MAX_MSG_LENGTH) { + err = -EINVAL; + goto err_out; + } /* take care of a potential SF_DL ESC offset for TX_DL > 8 */ off = (so->tx.ll_dl > CAN_MAX_DLEN) ? 1 : 0; /* does the given data fit into a single frame for SF_BROADCAST? */ if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) && - (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) - return -EINVAL; + (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) { + err = -EINVAL; + goto err_out; + } err = memcpy_from_msg(so->tx.buf, msg, size); if (err < 0) - return err; + goto err_out; dev = dev_get_by_index(sock_net(sk), so->ifindex); - if (!dev) - return -ENXIO; + if (!dev) { + err = -ENXIO; + goto err_out; + } 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); - return err; + goto err_out; } can_skb_reserve(skb); can_skb_prv(skb)->ifindex = dev->ifindex; can_skb_prv(skb)->skbcnt = 0; - so->tx.state = ISOTP_SENDING; so->tx.len = size; so->tx.idx = 0; @@ -956,7 +965,7 @@ static int isotp_sendmsg(struct socket * if (err) { pr_notice_once("can-isotp: %s: can_send_ret %pe\n", __func__, ERR_PTR(err)); - return err; + goto err_out; } if (wait_tx_done) { @@ -968,6 +977,13 @@ static int isotp_sendmsg(struct socket * } return size; + +err_out: + so->tx.state = old_state; + if (so->tx.state == ISOTP_IDLE) + wake_up_interruptible(&so->wait); + + return err; } static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,