Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp3708703ybl; Tue, 21 Jan 2020 05:45:39 -0800 (PST) X-Google-Smtp-Source: APXvYqxSuqkAxZg8ooURxjbzgL2Bv1820Pp0mgri6ukKZUxtxYFLMSw6NS9wvuBCjBN5K8bs768d X-Received: by 2002:aca:ad47:: with SMTP id w68mr2941221oie.63.1579614339864; Tue, 21 Jan 2020 05:45:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579614339; cv=none; d=google.com; s=arc-20160816; b=stYOi42EIznwGKE7OJiV8d6VJOlOvsShqqXfqyk1Zm4W+mr85HmnDiXYysiOrjQUfl jaIzNzkzXNwxfPFPiFVWAZLlKa9evtGjE+6TnsIU2qR1WXos0EkTj9KL95WbhIqJnrIp EB7vFm+cV4ZzTJ/mlkkbsqZhbMELNnELo7/nxiWRKODTKltvl0kEIKS0DZyH7vyc7A2i Ypap/S1Ia9nHh203gblSk26Yl4eCZWRLZq5DHMMKbj5LLsD72eSFyL2WVImmR9bTX+x8 KLlgubVTmvNFSbjQfugU68ahzhJ+3ohfP2tFXKFBzxkgSquog2gVGBihDp/1xx9sYkmD I9jg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=/JvsirxSLuxmWJsXkuMQJlClXSN1V0FfOfl3dWDLPDw=; b=O/2dZRypJZXwrLXz9+7C8QRdet/JcwYkjsIfV8itv/fhVreDQB3OVwr+uDqkV9x3e8 ejbWKgYGo+rgcoU/jiMtNhgZGtmHNZQNoSmSXC4lRdafjpJaaemzACZau4KDAInmoskb RcYdXFOc4uOVkBLQuTkgA+XixYu2r6/wsy7gpOvrpeSqs09aZiGud3J9g/yfM1Tnm1a3 pgYyp4MJlhGMja7QnXn61HNpNlIK4sSprsqDUpHpz+Yvflv+At5ZdOL390bzJa7FJK2g sl9fzbU441xNrFmGuwIkrX/iNQbJCXcZbaEqPlJ6022dbTT2aOsnMLbKG7zUp8QyRasH ZEQw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q127si20269391oic.99.2020.01.21.05.45.28; Tue, 21 Jan 2020 05:45:39 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729336AbgAUNnf (ORCPT + 99 others); Tue, 21 Jan 2020 08:43:35 -0500 Received: from mx2.suse.de ([195.135.220.15]:47976 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729098AbgAUNnf (ORCPT ); Tue, 21 Jan 2020 08:43:35 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 415FEAE85; Tue, 21 Jan 2020 13:43:32 +0000 (UTC) From: Richard Palethorpe To: linux-can@vger.kernel.org Cc: Richard Palethorpe , syzbot+017e491ae13c0068598a@syzkaller.appspotmail.com, Wolfgang Grandegger , Marc Kleine-Budde , "David S. Miller" , Tyler Hall , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, syzkaller@googlegroups.com Subject: [PATCH v3] can, slip: Protect tty->disc_data in write_wakeup and close with RCU Date: Tue, 21 Jan 2020 14:42:58 +0100 Message-Id: <20200121134258.18013-1-rpalethorpe@suse.com> X-Mailer: git-send-email 2.24.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org write_wakeup can happen in parallel with close/hangup where tty->disc_data is set to NULL and the netdevice is freed thus also freeing disc_data. write_wakeup accesses disc_data so we must prevent close from freeing the netdev while write_wakeup has a non-NULL view of tty->disc_data. We also need to make sure that accesses to disc_data are atomic. Which can all be done with RCU. This problem was found by Syzkaller on SLCAN, but the same issue is reproducible with the SLIP line discipline using an LTP test based on the Syzkaller reproducer. A fix which didn't use RCU was posted by Hillf Danton. Fixes: 661f7fda21b1 ("slip: Fix deadlock in write_wakeup") Fixes: a8e83b17536a ("slcan: Port write_wakeup deadlock fix from slip") Reported-by: syzbot+017e491ae13c0068598a@syzkaller.appspotmail.com Signed-off-by: Richard Palethorpe Cc: Wolfgang Grandegger Cc: Marc Kleine-Budde Cc: "David S. Miller" Cc: Tyler Hall Cc: linux-can@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: syzkaller@googlegroups.com --- V2: Added proper RCU grace period V3: Changed commit description This patch creates a Sparse warning concerning the RCU address space. I'm not sure what to do about that. drivers/net/can/slcan.c | 12 ++++++++++-- drivers/net/slip/slip.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 2e57122f02fb..2f5c287eac95 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -344,9 +344,16 @@ static void slcan_transmit(struct work_struct *work) */ static void slcan_write_wakeup(struct tty_struct *tty) { - struct slcan *sl = tty->disc_data; + struct slcan *sl; + + rcu_read_lock(); + sl = rcu_dereference(tty->disc_data); + if (!sl) + goto out; schedule_work(&sl->tx_work); +out: + rcu_read_unlock(); } /* Send a can_frame to a TTY queue. */ @@ -644,10 +651,11 @@ static void slcan_close(struct tty_struct *tty) return; spin_lock_bh(&sl->lock); - tty->disc_data = NULL; + rcu_assign_pointer(tty->disc_data, NULL); sl->tty = NULL; spin_unlock_bh(&sl->lock); + synchronize_rcu(); flush_work(&sl->tx_work); /* Flush network side */ diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 2a91c192659f..61d7e0d1d77d 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -452,9 +452,16 @@ static void slip_transmit(struct work_struct *work) */ static void slip_write_wakeup(struct tty_struct *tty) { - struct slip *sl = tty->disc_data; + struct slip *sl; + + rcu_read_lock(); + sl = rcu_dereference(tty->disc_data); + if (!sl) + goto out; schedule_work(&sl->tx_work); +out: + rcu_read_unlock(); } static void sl_tx_timeout(struct net_device *dev) @@ -882,10 +889,11 @@ static void slip_close(struct tty_struct *tty) return; spin_lock_bh(&sl->lock); - tty->disc_data = NULL; + rcu_assign_pointer(tty->disc_data, NULL); sl->tty = NULL; spin_unlock_bh(&sl->lock); + synchronize_rcu(); flush_work(&sl->tx_work); /* VSV = very important to remove timers */ -- 2.24.0