Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp3052609pxb; Sun, 26 Sep 2021 04:03:52 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxZME1QGiuYf1HlvlZU9q5ud58AQbuw5aREp3tfU+bPa16PwTKmOQtRFZaQRsIoCJQjH5Wr X-Received: by 2002:a6b:fe05:: with SMTP id x5mr15743979ioh.26.1632654232754; Sun, 26 Sep 2021 04:03:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1632654232; cv=none; d=google.com; s=arc-20160816; b=yJnQpMMl7l3PSMmh77detO5Ys8RI12yPYEqnWZs0Lorl8zjwubiu0prRL9gXSW1sLu aat88vrszRZaiNkexNbhiMnCUGjwlgcOrnE8zl+PXFrxqJctB7w+FETj4RdWV4T6F25v dTWxj5wsLCCrmGLlD9+8I5dT9n3wz5KpJkPi1b3p7iFqhFzU28oDgTdzsfsjIsVcTBDQ fv2yHv/OF6sSZmASG8H+TVOC8qY5Hh9jdTLVMXb6+B4GEWaNB0BXIcIvI6HFLEiLhKJr 4mwVBYv1ogr3m5nbdGP72M4UyV6bCpVkbVDxZLhyb9gHzsbTIk3jMs+6fWW3W4EOg9EQ XVwA== 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 :references:in-reply-to:message-id:date:subject:cc:to:from; bh=sVzukJexYMwrjRSQZ3OpsvYa5KlQjaDym5Y3LR4nhzQ=; b=GNfPxpvhMQYj0UZkFaJES2jMQSqWLZHdwVQ+hRVIEgMj1BVhaZdjWpab9iTIYr8PFY LPXQxABLsoxPHRqH5AgEZbvDhvJvfnnmmDU31WPG7QW9LnJTZIm+B7aZ833AmaspkgsY zgLSm1bPd+6bxSXNVuRTKw0qyRD9UlBMjJFk/AT9/DYXcsmD257yDNwgItyhP9QfSRRc jUcJBLVwYHjbzlrl7WHUU+ZzMLMM14FL/FmpUTlde1iVYQnjpnyY60TjUq6xNQHnDD0R Zv9HBsnar96sd2I5XAI+mkq2NlgIOdQS+7CwBBIgkXoDMLVNxST2XnOI3mWOBQhBkz8V eqOQ== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m82si15344111ioa.74.2021.09.26.04.03.40; Sun, 26 Sep 2021 04:03:52 -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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230228AbhIZLEX (ORCPT + 99 others); Sun, 26 Sep 2021 07:04:23 -0400 Received: from szxga01-in.huawei.com ([45.249.212.187]:23957 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230498AbhIZLES (ORCPT ); Sun, 26 Sep 2021 07:04:18 -0400 Received: from dggeml757-chm.china.huawei.com (unknown [172.30.72.54]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4HHN6V1xMszY4QF; Sun, 26 Sep 2021 18:58:26 +0800 (CST) Received: from localhost.localdomain (10.175.104.82) by dggeml757-chm.china.huawei.com (10.1.199.137) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2308.8; Sun, 26 Sep 2021 19:02:40 +0800 From: Ziyang Xuan To: CC: , , , , , Subject: [PATCH net 2/2] can: isotp: fix tx buffer concurrent access in isotp_sendmsg() Date: Sun, 26 Sep 2021 19:01:42 +0800 Message-ID: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.175.104.82] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggeml757-chm.china.huawei.com (10.1.199.137) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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") Signed-off-by: Ziyang Xuan --- net/can/isotp.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/net/can/isotp.c b/net/can/isotp.c index 2ac29c2b2ca6..506e16623c84 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -848,6 +848,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) { struct sock *sk = sock->sk; struct isotp_sock *so = isotp_sk(sk); + u8 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 *sock, struct msghdr *msg, size_t size) 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 *sock, struct msghdr *msg, size_t size) 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) { @@ -965,6 +974,13 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) } 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, -- 2.25.1