From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pandora.armlinux.org.uk (pandora.armlinux.org.uk [78.32.30.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 091A8287515 for ; Tue, 16 Sep 2025 21:36:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.32.30.218 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758058572; cv=none; b=P4ijU7CKRA1JKt4dlCGOsPtu8Kf8T9OYDf4TguSHjwyaKqxV3sSR/P+PM1Da4vFQkPS5tCIF8VrtUTNqGW/TnpeJT1SJznmfNPOXn9y+/rGojzMNNjZT/bs/DULnYtVm0GZYIl51z6BPDZfV+smwFmbok7Ux7SMXQ7ZSEe/4lpo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758058572; c=relaxed/simple; bh=N56YtZJFoXvsE7cRT1onTi17/fepHuemQoI30iftZh4=; h=In-Reply-To:References:From:To:Cc:Subject:MIME-Version: Content-Disposition:Content-Type:Message-Id:Date; b=iUA/OYe4UvgaHmC8ZTNBw2YI5+Bq03uxFc9L9Mf6+nOZ8/9CsXqNkwP9wrWNOG/4n6/88XLJjz+OUKLl9LVtL07IF/h6N8GMbTLTfHVRvZ5poiDJO1JsTYWNHK9YZvdYjaKZQ+9Ggs3+pwzQjtGNFjLCUfoyIleshLFiILDbs+Q= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=armlinux.org.uk; spf=none smtp.mailfrom=armlinux.org.uk; dkim=pass (2048-bit key) header.d=armlinux.org.uk header.i=@armlinux.org.uk header.b=VZuvD9Vm; arc=none smtp.client-ip=78.32.30.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=armlinux.org.uk Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=armlinux.org.uk Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=armlinux.org.uk header.i=@armlinux.org.uk header.b="VZuvD9Vm" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=armlinux.org.uk; s=pandora-2019; h=Date:Sender:Message-Id:Content-Type: Content-Transfer-Encoding:MIME-Version:Subject:Cc:To:From:References: In-Reply-To:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=kRXoK0A2hBXkU7zBWyuZuw+fxiVrjBZqA9iVdeGMOLk=; b=VZuvD9VmcNDTwAHN7jn2a2HRs4 +b4FqadQcvgxW+fz9bZA1kKt7kx6Zh3iZvTlSOHAINJtUJYNJAi+ImGgf8o4sbI4B0MzHT+KlVMRF FznaiCMNSqQo+9lCziditrXqLCgCi/XQCpF8fRW5GZHYQKfdes3UXALvFMzqx1FDhAS4lWJMr57P+ F96+rJC4qOt9dGhdb2mh5fY1ZHbCTN4O80vSg4cmhjJUUJS9FScN5A0KDky314I3bDU3U0RudxJKB xuovbpNVMsa4JtCv/epI2g/4eRm01ClxQDz/WjJYZS23lj073YSo2j/B67In3zZo5kxX3nytMsr4i 0Aom7Pcw==; Received: from e0022681537dd.dyn.armlinux.org.uk ([fd8f:7570:feb6:1:222:68ff:fe15:37dd]:47242 helo=rmk-PC.armlinux.org.uk) by pandora.armlinux.org.uk with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1uydLI-000000006Lm-1xiv; Tue, 16 Sep 2025 22:36:04 +0100 Received: from rmk by rmk-PC.armlinux.org.uk with local (Exim 4.98.2) (envelope-from ) id 1uydLH-000000061DM-2gcV; Tue, 16 Sep 2025 22:36:03 +0100 In-Reply-To: References: From: "Russell King (Oracle)" To: Richard Cochran Cc: Ajay Kaher , Alexey Makhalov , Andrew Lunn , Broadcom internal kernel review list , Clark Wang , "David S. Miller" , David Woodhouse , Eric Dumazet , imx@lists.linux.dev, Jakub Kicinski , Jonathan Lemon , netdev@vger.kernel.org, Nick Shi , Paolo Abeni , Sven Schnelle , Vadim Fedorenko , Vladimir Oltean , Wei Fang , Yangbo Lu Subject: [PATCH net-next v2 2/2] ptp: rework ptp_clock_unregister() to disable events Precedence: bulk X-Mailing-List: imx@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="utf-8" Message-Id: Sender: Russell King Date: Tue, 16 Sep 2025 22:36:03 +0100 The ordering of ptp_clock_unregister() is not ideal, as the chardev remains published while state is being torn down, which means userspace can race with the kernel teardown. There is also no cleanup of enabled pin settings nor of the internal PPS event, which means enabled events can still forward into the core, dereferencing a free'd pointer. Rework the ordering of cleanup in ptp_clock_unregister() so that we unpublish the posix clock (and user chardev), disable any pins that have EXTTS events enabled, disable the PPS event, and then clean up the aux work and PPS source. This avoids potential use-after-free and races in PTP clock driver teardown. Signed-off-by: Russell King (Oracle) --- drivers/ptp/ptp_chardev.c | 20 ++++++++++++++++++++ drivers/ptp/ptp_clock.c | 15 ++++++++++++++- drivers/ptp/ptp_private.h | 2 ++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index eb4f6d1b1460..8106eb617c8c 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -47,6 +47,26 @@ static int ptp_disable_pinfunc(struct ptp_clock_info *ops, return err; } +void ptp_disable_all_events(struct ptp_clock *ptp) +{ + struct ptp_clock_info *info = ptp->info; + unsigned int i; + + mutex_lock(&ptp->pincfg_mux); + /* Disable any pins that may raise EXTTS events */ + for (i = 0; i < info->n_pins; i++) + if (info->pin_config[i].func == PTP_PF_EXTTS) + ptp_disable_pinfunc(info, info->pin_config[i].func, + info->pin_config[i].chan); + + /* Disable the PPS event if the driver has PPS support */ + if (info->pps) { + struct ptp_clock_request req = { .type = PTP_CLK_REQ_PPS }; + info->enable(info, &req, 0); + } + mutex_unlock(&ptp->pincfg_mux); +} + int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, enum ptp_pin_function func, unsigned int chan) { diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index 1d920f8e20a8..ef020599b771 100644 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@ -498,9 +498,21 @@ int ptp_clock_unregister(struct ptp_clock *ptp) device_for_each_child(&ptp->dev, NULL, unregister_vclock); } + /* Get the device to stop posix_clock_unregister() doing the last put + * and freeing the structure(s) + */ + get_device(&ptp->dev); + + /* Wake up any userspace waiting for an event. */ ptp->defunct = 1; wake_up_interruptible(&ptp->tsev_wq); + /* Tear down the POSIX clock, which removes the user interface. */ + posix_clock_unregister(&ptp->clock); + + /* Disable all sources of event generation. */ + ptp_disable_all_events(ptp); + if (ptp->kworker) { kthread_cancel_delayed_work_sync(&ptp->aux_work); kthread_destroy_worker(ptp->kworker); @@ -510,7 +522,8 @@ int ptp_clock_unregister(struct ptp_clock *ptp) if (ptp->pps_source) pps_unregister_source(ptp->pps_source); - posix_clock_unregister(&ptp->clock); + /* The final put, normally here, will invoke ptp_clock_release(). */ + put_device(&ptp->dev); return 0; } diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h index b352df4cd3f9..76ab9276b588 100644 --- a/drivers/ptp/ptp_private.h +++ b/drivers/ptp/ptp_private.h @@ -141,6 +141,8 @@ extern const struct class ptp_class; * see ptp_chardev.c */ +void ptp_disable_all_events(struct ptp_clock *ptp); + /* caller must hold pincfg_mux */ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, enum ptp_pin_function func, unsigned int chan); -- 2.47.3