Received: by 2002:a05:6358:7058:b0:131:369:b2a3 with SMTP id 24csp2214592rwp; Fri, 14 Jul 2023 02:40:08 -0700 (PDT) X-Google-Smtp-Source: APBJJlGpump+Fv7aewFyqR904IaT2yak8xEobuVuxpJa1jcnj4Mv3Z2j+yKyvBpmliMOtv4jBToz X-Received: by 2002:a05:6402:2037:b0:51d:92bf:e6b9 with SMTP id ay23-20020a056402203700b0051d92bfe6b9mr3714487edb.34.1689327607792; Fri, 14 Jul 2023 02:40:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689327607; cv=none; d=google.com; s=arc-20160816; b=iWY5ANeq4CeWRdFyadqk6PmF+SHZ7Ekncvo/LfSPOaTgKYUL17Zann8i6B5b6LWPF6 Jqe01eL4JLziz6HYr0zaEDFHbUYrzO1arSVrY+OiC7xdmBwFVIFrgf7lu37R2qmDW1sN uxAnJwxBcOKno+iPYcuTuwRlfu9ht/cOvXUeD/OkyQVplbOPJRuZDH8ASQOtTVBoZc+7 KkYSTLZbpw7uRlKbeD6uDa99WXIMfS5Tt5GgjEIuXdGfNsCigINEBnib6lP1ltBKUNjc JPSsxb+0wqzYwtW1OvS2xFa/kwva6LFgIgt4NqgPcJegdkY98q4/LaKi/I3mQV/bhWFu qWBw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=FgvV1xCFwlp4/7NHwDYg7XeyISjl0J5eqJ5gGfRLl9E=; fh=P69duW5QZmRj9b1Pp5XKOSqIgFMUDbjoyFZWqOwQYzw=; b=Cy8PGNFC2ZMId8uK9FdTX+SwcXCCCVM6DW1k79a+LDaEJzERYXIwKX8+hHbxHkEZsB oKty8nluwO1EZd/ZRxAx2INdDG92+FsLYFdhyxODhauXIxAITMeNKfuPSaYpPe0bZqgR a8xsahiiZBg2PJEQKqz9M2zk8Paw3BhVzspGwWdwWoneeGu7gGVAwTSQ/VZ+UA8FUKWY u2s7X2M5uzBIkVRytJ+T908pfo8wTb9YvGRQTMRGAPiucU6i+Lh2SdGCiPeXmwfcezGo mKwr3hvZd17P/sPRK2Ztpwf2+4h1BdDDB24m0nXv8GVMleJDrf7qNcy9UwU0K1vLYnrC qITQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=Phm4cOQp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f2-20020a50ee82000000b0051e24863dd2si8462105edr.377.2023.07.14.02.39.43; Fri, 14 Jul 2023 02:40:07 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@asahilina.net header.s=default header.b=Phm4cOQp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=asahilina.net Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235938AbjGNJcj (ORCPT + 99 others); Fri, 14 Jul 2023 05:32:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235926AbjGNJcH (ORCPT ); Fri, 14 Jul 2023 05:32:07 -0400 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBF163599; Fri, 14 Jul 2023 02:31:44 -0700 (PDT) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: linasend@asahilina.net) by mail.marcansoft.com (Postfix) with ESMTPSA id A6D035BC4B; Fri, 14 Jul 2023 09:14:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=asahilina.net; s=default; t=1689326083; bh=YQMECCDF0tMPqG41YW5GqgPmtn/MWGEIPI5Q1NaQYSY=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Phm4cOQp7dNly6KdM+1WaFltuLRCCccAdmrNa2mW1HaP5xISZ8QVF9w5oH4EHsF29 nBxlu8nN92foqpEy/Cqv9V+Z0UGM5pwEJjyWj1AD56aOJGcMUuhaPldP1A2JDaALE7 dux48++7nyiMgJ45pEG9vtiIG7qKSCHawDzfhorMgjmbMApa6ydxNSWmBV/ldFv5T8 d8tQdycNmmNXKi/iBFjfT2Or5qtatxPOK2ZTOz+Q3o5CN0Z8Z3rUOqFHKepPBgcyVZ bG27LPWiYfpBp4XRcdTNwbPU85BHVPyqxXrRlYa9QOTsyn2R5VJHIShiaQIVkFfp40 0l8klm95ruhRQ== From: Asahi Lina Date: Fri, 14 Jul 2023 18:13:58 +0900 Subject: [PATCH RFC 06/11] rust: sync: Replace static LockClassKey refs with a pointer wrapper MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230714-classless_lockdep-v1-6-229b9671ce31@asahilina.net> References: <20230714-classless_lockdep-v1-0-229b9671ce31@asahilina.net> In-Reply-To: <20230714-classless_lockdep-v1-0-229b9671ce31@asahilina.net> To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Masahiro Yamada , Nathan Chancellor , Nick Desaulniers , Nicolas Schier , Tom Rix , Daniel Vetter Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , asahi@lists.linux.dev, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, llvm@lists.linux.dev, Asahi Lina X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1689326040; l=6618; i=lina@asahilina.net; s=20230221; h=from:subject:message-id; bh=YQMECCDF0tMPqG41YW5GqgPmtn/MWGEIPI5Q1NaQYSY=; b=DHnofK17mNqOsVKbC7EuDKWPrgQt8WOHKWeRP7sUdWZGE9Ed0qlD+ubbbZ1HJJjrCebrQ8Ru5 qfpFd+NvfkgBrKIeVDgO1ojTXJ3jFyt0CJxGcsLXh5mTChXqp5XtkUM X-Developer-Key: i=lina@asahilina.net; a=ed25519; pk=Qn8jZuOtR1m5GaiDfTrAoQ4NE1XoYVZ/wmt5YtXWFC4= X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We want to be able to handle dynamic lock class creation and using pointers to things that aren't a real lock_class_key as lock classes. Doing this by casting around Rust references is difficult without accidentally invoking UB. Instead, switch LockClassKey to being a raw pointer wrapper around a lock_class_key, which means there is no UB possible on the Rust side just by creating and consuming these objects. The C code also should never actually dereference lock classes, only use their address (possibly with an offset). We still provide a dummy ZST version of this wrapper, to be used when lockdep is disabled. Signed-off-by: Asahi Lina --- rust/kernel/sync.rs | 6 +++--- rust/kernel/sync/condvar.rs | 2 +- rust/kernel/sync/lock.rs | 4 ++-- rust/kernel/sync/lockdep.rs | 27 ++++++++++++++++++++++----- rust/kernel/sync/no_lockdep.rs | 15 +++++++++++++-- rust/kernel/types.rs | 2 +- 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 352472c6b77a..49286c3e0ff3 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -20,7 +20,7 @@ pub use arc::{Arc, ArcBorrow, UniqueArc}; pub use condvar::CondVar; pub use lock::{mutex::Mutex, spinlock::SpinLock}; -pub use lockdep::LockClassKey; +pub use lockdep::{LockClassKey, StaticLockClassKey}; pub use locked_by::LockedBy; /// Defines a new static lock class and returns a pointer to it. @@ -28,8 +28,8 @@ #[macro_export] macro_rules! static_lock_class { () => {{ - static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new(); - &CLASS + static CLASS: $crate::sync::StaticLockClassKey = $crate::sync::StaticLockClassKey::new(); + CLASS.key() }}; } diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs index ed353399c4e5..3bccb2c6ef84 100644 --- a/rust/kernel/sync/condvar.rs +++ b/rust/kernel/sync/condvar.rs @@ -92,7 +92,7 @@ unsafe impl Sync for CondVar {} impl CondVar { /// Constructs a new condvar initialiser. #[allow(clippy::new_ret_no_self)] - pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pub fn new(name: &'static CStr, key: LockClassKey) -> impl PinInit { pin_init!(Self { _pin: PhantomPinned, // SAFETY: `slot` is valid while the closure is called and both `name` and `key` have diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index d493c5d19104..8e71e7aa2cc1 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -103,7 +103,7 @@ unsafe impl Sync for Lock {} impl Lock { /// Constructs a new lock initialiser. #[allow(clippy::new_ret_no_self)] - pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pub fn new(t: T, name: &'static CStr, key: LockClassKey) -> impl PinInit { pin_init!(Self { data: UnsafeCell::new(t), _pin: PhantomPinned, @@ -119,7 +119,7 @@ pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinIni pub fn pin_init( t: impl PinInit, name: &'static CStr, - key: &'static LockClassKey, + key: LockClassKey, ) -> impl PinInit where E: core::convert::From, diff --git a/rust/kernel/sync/lockdep.rs b/rust/kernel/sync/lockdep.rs index cb68b18dc0ad..d8328f4275fb 100644 --- a/rust/kernel/sync/lockdep.rs +++ b/rust/kernel/sync/lockdep.rs @@ -9,19 +9,36 @@ /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. #[repr(transparent)] -pub struct LockClassKey(Opaque); +pub struct StaticLockClassKey(Opaque); -impl LockClassKey { +impl StaticLockClassKey { /// Creates a new lock class key. pub const fn new() -> Self { Self(Opaque::uninit()) } + /// Returns the lock class key reference for this static lock class. + pub const fn key(&self) -> LockClassKey { + LockClassKey(self.0.get()) + } +} + +// SAFETY: `bindings::lock_class_key` just represents an opaque memory location, and is never +// actually dereferenced. +unsafe impl Sync for StaticLockClassKey {} + +/// A reference to a lock class key. This is a raw pointer to a lock_class_key, +/// which is required to have a static lifetime. +#[derive(Copy, Clone)] +pub struct LockClassKey(*mut bindings::lock_class_key); + +impl LockClassKey { pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { - self.0.get() + self.0 } } -// SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and -// provides its own synchronization. +// SAFETY: `bindings::lock_class_key` just represents an opaque memory location, and is never +// actually dereferenced. +unsafe impl Send for LockClassKey {} unsafe impl Sync for LockClassKey {} diff --git a/rust/kernel/sync/no_lockdep.rs b/rust/kernel/sync/no_lockdep.rs index 69d42e8d9801..518ec0bf9a7d 100644 --- a/rust/kernel/sync/no_lockdep.rs +++ b/rust/kernel/sync/no_lockdep.rs @@ -5,14 +5,25 @@ //! Takes the place of the `lockdep` module when lockdep is disabled. /// A dummy, zero-sized lock class. -pub struct LockClassKey(); +pub struct StaticLockClassKey(); -impl LockClassKey { +impl StaticLockClassKey { /// Creates a new dummy lock class key. pub const fn new() -> Self { Self() } + /// Returns the lock class key reference for this static lock class. + pub const fn key(&self) -> LockClassKey { + LockClassKey() + } +} + +/// A dummy reference to a lock class key. +#[derive(Copy, Clone)] +pub struct LockClassKey(); + +impl LockClassKey { pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { core::ptr::null_mut() } diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 185d3493857e..91739bf71cc3 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -262,7 +262,7 @@ pub fn ffi_init(init_func: impl FnOnce(*mut T)) -> impl PinInit { } /// Returns a raw pointer to the opaque data. - pub fn get(&self) -> *mut T { + pub const fn get(&self) -> *mut T { UnsafeCell::raw_get(self.0.as_ptr()) } -- 2.40.1