From patchwork Fri Feb 9 11:18:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198818 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780032dyd; Fri, 9 Feb 2024 03:20:58 -0800 (PST) X-Google-Smtp-Source: AGHT+IEj/ziyzmiBYj6HydqmleJzz376K3XsKhAh1TUxx1kBecxJHopb+Xf0MMQLoMbeXrxmztva X-Received: by 2002:a05:6e02:ca8:b0:363:bdb9:72af with SMTP id 8-20020a056e020ca800b00363bdb972afmr1489938ilg.23.1707477657933; Fri, 09 Feb 2024 03:20:57 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477657; cv=pass; d=google.com; s=arc-20160816; b=LlXphE5mRFFbqmclMq4TxWivESnacLt1gOUuOwrQq7CCsvCmd8Ba10Tj+K0clNQRsa mKgTF8fdONjSrWNE30Kh5jICU3X3dU0OivpUyr16cG3k4UgB5GFCM6MzkBgLg2TCQQgl ekvdU2uJlrc9M2Tp7KJKksuDGAnX0bF1zzMC37bfKnsP3d7CX9VbWp4Nte9fQmAixlNX Vr0PEXD5z5pd2nak01lXtN4vdlhjT0AaJsEa6TDixiqFn661FvJKyqjgWXwWc8bTHijS Tx3hG7Ti0fOdl05Q06nXx2vrEA4MWp3isC1yZA7pKAOt7mMYm1fntahQRCeJhVzbUVuC TuNw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=9q54lAKt/gv2rK+yHeXkaQhcn+YG2rdku2rLMO1QR6A=; fh=2t9+2b8ltRwCYKVcpKJ1+2822r2kJnocn87uxeK4csc=; b=WFSlc4a8h897rlIu8Ww4b9/TnF6Z35qge9dOdsKyist/vFLMEEG1I06JYmT88SFfN2 m5mST1evmM15IFNRUfo0yPx50czVf5YCOw/gBdUO5eotci3FJXdO6GgwpmHlkgeGCQZY AaWYDs5Xam2s6ar6WqewW6PbNmFXqvWbdL8yX1v9SjwcroA/kspcB/YQ2wxKU1ysOPRi beD4tijqVRn1EtUG3LRKWLee0aqkv4Vkb9ETuEQ8Jl0JNW6cYqMD3hQc6TkM9/X65rv8 8g98jxLt77THmsiufFPAOWI/XaERHvngzGpRTB931SvixT/Q4pmmJWWM5p0Gug0pi9tT IqRg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=CXjKMt2b; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59278-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59278-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWTMHHXKff1Zocp+NvjBl7dY9Ui1pENazozy57/3whGZu6KimaLsZlGJvOoCiCFpBmE7upsC63tTlgFcJSPeC9IgR68eA== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id d23-20020a637357000000b005d8b59b8da3si1497700pgn.839.2024.02.09.03.20.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:20:57 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59278-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=CXjKMt2b; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59278-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59278-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id BF11128CFB3 for ; Fri, 9 Feb 2024 11:20:01 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 76DEE364CF; Fri, 9 Feb 2024 11:18:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CXjKMt2b" Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5D2ADF57 for ; Fri, 9 Feb 2024 11:18:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477534; cv=none; b=P6L8JHCKUCBWDPCeV9pGQAskjUU09dRZwrsHA3+jGJLg84RF/Lqh8IojIBDJ/btXdtBUsLYTJWFf0biUT7uWRYghMWNfCDWXz980drJlR9BPxUOrNCby4O77u0fjv5BuezNC++McQWB2M/HEaye7eNWCxmp7/beY8n5fnEmdFec= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477534; c=relaxed/simple; bh=Ot5zgSBuhhqw7Lyq5N1K+biVLFlimbZBNuPkWRRLiE4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=elFy6ncMA0zqU05NjfnQQSEAYzWYn8GflRUy1dGdyFnCgxM5/j58tkqM88jDjpDqQf73Dl6MuK+YjiCSmWLN9DvTDliiUb4fVb2oCfWyABqbO+y6mClBbCPClFwzVYvwDztJDHnFfvvrKjNPIXFqeQ18KklPEUsiFF9TEqRpfnA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=CXjKMt2b; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-60492d6bfc0so14868697b3.2 for ; Fri, 09 Feb 2024 03:18:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477531; x=1708082331; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=9q54lAKt/gv2rK+yHeXkaQhcn+YG2rdku2rLMO1QR6A=; b=CXjKMt2bR2duDsCcVo1Ub81PH/W5Pvk5yVCebChy+56ctskn01xc04iX+zwCcPg9Ya mdYwvBO6p9gBa4tAhC3V88XxX3sDmmE3WABuFqk4nLhBF9vtO16rYpGYW4CHcFYYZ0bR esPZ7tLSNm2r7lP7gxmOJ2dvygYXZcU0TcFATUCeXzZn8IFN4VjR87PnVFA7iZQX8D/u e0vsXVL/PTq+tzF3spe1ZcTAcAi1Lzn2rWsNRZ3+/t7gWp9iyuHeWInv/4Mv98m0jsSg IEOydsDLVnyTq68z099N6YFNxJWxzsAQ5CqnpWsJXa6jnTS7JVf8K2INc2+XfiXJiq2s 9yeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477531; x=1708082331; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=9q54lAKt/gv2rK+yHeXkaQhcn+YG2rdku2rLMO1QR6A=; b=ZaXoNjw4y8zerRG/HEs84mAZcrFeKB7QHoLLwH3YR8fzslHkzgNfwFEludCSzwnrLm CfQZ+t42MScuiryVV1OQhqTTQclNXcboF70w5l4pdIHlKOb28t+VJpSRmZb25ClCSbMq ueij6wjwdXj6B6i0nrEKrzOmqRbwIBmcc4aC2QN0guCQZPKEJ933onrWfmQcNYUjEqqJ BhAEg5zt0Tpp4bR1qNIeg9AStynZGTwt1wZcJX672DnQYCHdYJOuusyrjPCsAJec37J9 Bo3+o1x/Wn67xM5cU7g2P6WlVKJQuAUjVkZlp/Tj19qTisaKlbxK0qRmnPCro0ApTVS4 GCxg== X-Gm-Message-State: AOJu0YxqPYb5qgKCySbQD6KkhzuS7cKThDZMLWzLLApTWpUR//gEqYzs q4Vj+i05vFq/vUvnCCrJKWxcaRyJDvBetsZ/P8c/GhNPeXUyHleLXfCsiPZr+kyxGS3guCIqKhn ztZyyhrYv30OFEQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:706:b0:dc2:421d:ee30 with SMTP id k6-20020a056902070600b00dc2421dee30mr18422ybt.6.1707477531683; Fri, 09 Feb 2024 03:18:51 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:14 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5346; i=aliceryhl@google.com; h=from:subject:message-id; bh=Ot5zgSBuhhqw7Lyq5N1K+biVLFlimbZBNuPkWRRLiE4=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoPyGfidEExgGJzTQr4EuqI+P+PF6rccTGHa xqqgMJnVTmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKDwAKCRAEWL7uWMY5 RtXHD/96K2s5KP11BZAzeOUDVG85LrVgPCSeO7vAKxIsG5apeK3QUDwOM/nwagQGS2D4OsaDvSv jY2t+v1f2Jh8kUs/D1JuZs4o+nBB0B56BdMU1pWtEaBeXtPQB9xWHS87Ysi68C0iMUWsxIvI03i KlOXxSXBWQcX/9aPTzbTK18h+/DvTMmUxfDW6I6NhY8r0QxHsGZi8TlWjWUSfaii1kVzi9bC2hI MiOT8PNZAMBGvNsA/O94uIT57I2Dno5iLzD9xmQeiE58UEjQFE51OpKrPt9hEDRUl9biKklGa05 Gpf/Mgg1zgo3xu5+9ERTCQXXfV0qZn263lywYnnA8fhvMeh7WBVqo3TDq6yfYAEeAQwIqxn8Be1 +8MJj1ZScSdEkI73Ig+YUWiyuxZWcO7S10A850Y6I3vAPgMc5nVVPv0Do7zWYr9PxtG/7IcR3zo xcNqe4hV0glN6my3SOZFeopaHnPyGHHdy7PzeBbrvOIsURMUBoV4uswpsmE/yJdaCdSkzraWdjP X3eU6vFFhjE+KGoWfRwT9x4AH7cg2SLC4rHf8aRzqbgA9GeIY+SIJhLPBuCHQnyj6WSIPBCzl3U XOq4n47NHEf7vKsxh+1VoO6X6LP/L2mCtIn1aG6s3YVeMo16ff+2TkRKcO3ZiO4sU+80fwqlD5c eysAhO7o+dHjryQ== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-1-a37886783025@google.com> Subject: [PATCH v5 1/9] rust: types: add `NotThreadSafe` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Trevor Gross , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420092494786732 X-GMAIL-MSGID: 1790420092494786732 This introduces a new marker type for types that shouldn't be thread safe. By adding a field of this type to a struct, it becomes non-Send and non-Sync, which means that it cannot be accessed in any way from threads other than the one it was created on. This is useful for APIs that require globals such as `current` to remain constant while the value exists. We update two existing users in the Kernel to use this helper: * `Task::current()` - moving the return type of this value to a different thread would not be safe as you can no longer be guaranteed that the `current` pointer remains valid. * Lock guards. Mutexes and spinlocks should be unlocked on the same thread as where they were locked, so we enforce this using the Send trait. There are also additional users in later patches of this patchset. See [1] and [2] for the discussion that led to the introduction of this patch. Link: https://lore.kernel.org/all/nFDPJFnzE9Q5cqY7FwSMByRH2OAn_BpI4H53NQfWIlN6I2qfmAqnkp2wRqn0XjMO65OyZY4h6P4K2nAGKJpAOSzksYXaiAK_FoH_8QbgBI4=@proton.me/ [1] Link: https://lore.kernel.org/all/nFDPJFnzE9Q5cqY7FwSMByRH2OAn_BpI4H53NQfWIlN6I2qfmAqnkp2wRqn0XjMO65OyZY4h6P4K2nAGKJpAOSzksYXaiAK_FoH_8QbgBI4=@proton.me/ [2] Suggested-by: Benno Lossin Reviewed-by: Benno Lossin Reviewed-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Alice Ryhl --- rust/kernel/sync/lock.rs | 14 ++++++++++---- rust/kernel/task.rs | 10 ++++++---- rust/kernel/types.rs | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index 149a5259d431..090b9ad63dc6 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -6,8 +6,14 @@ //! spinlocks, raw spinlocks) to be provided with minimal effort. use super::LockClassKey; -use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard}; -use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned}; +use crate::{ + bindings, + init::PinInit, + pin_init, + str::CStr, + types::{NotThreadSafe, ScopeGuard, Opaque}, +}; +use core::{cell::UnsafeCell, marker::PhantomPinned}; use macros::pin_data; pub mod mutex; @@ -132,7 +138,7 @@ pub fn lock(&self) -> Guard<'_, T, B> { pub struct Guard<'a, T: ?Sized, B: Backend> { pub(crate) lock: &'a Lock, pub(crate) state: B::GuardState, - _not_send: PhantomData<*mut ()>, + _not_send: NotThreadSafe, } // SAFETY: `Guard` is sync when the data protected by the lock is also sync. @@ -184,7 +190,7 @@ pub(crate) unsafe fn new(lock: &'a Lock, state: B::GuardState) -> Self { Self { lock, state, - _not_send: PhantomData, + _not_send: NotThreadSafe, } } } diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index a3a4007db682..148a4f4eb7a8 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -4,10 +4,12 @@ //! //! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h). -use crate::{bindings, types::Opaque}; +use crate::{ + bindings, + types::{NotThreadSafe, Opaque}, +}; use core::{ ffi::{c_int, c_long, c_uint}, - marker::PhantomData, ops::Deref, ptr, }; @@ -106,7 +108,7 @@ impl Task { pub unsafe fn current() -> impl Deref { struct TaskRef<'a> { task: &'a Task, - _not_send: PhantomData<*mut ()>, + _not_send: NotThreadSafe, } impl Deref for TaskRef<'_> { @@ -125,7 +127,7 @@ fn deref(&self) -> &Self::Target { // that `TaskRef` is not `Send`, we know it cannot be transferred to another thread // (where it could potentially outlive the caller). task: unsafe { &*ptr.cast() }, - _not_send: PhantomData, + _not_send: NotThreadSafe, } } diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index fdb778e65d79..ee1375d47df0 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -387,3 +387,21 @@ pub enum Either { /// Constructs an instance of [`Either`] containing a value of type `R`. Right(R), } + +/// Zero-sized type to mark types not [`Send`]. +/// +/// Add this type as a field to your struct if your type should not be sent to a different task. +/// Since [`Send`] is an auto trait, adding a single field that is `!Send` will ensure that the +/// whole type is `!Send`. +/// +/// If a type is `!Send` it is impossible to give control over an instance of the type to another +/// task. This is useful to include in types that store or reference task-local information. A file +/// descriptor is an example of such task-local information. +pub type NotThreadSafe = PhantomData<*mut ()>; + +/// Used to construct instances of type [`NotThreadSafe`] similar to how `PhantomData` is +/// constructed. +/// +/// [`NotThreadSafe`]: type@NotThreadSafe +#[allow(non_upper_case_globals)] +pub const NotThreadSafe: NotThreadSafe = PhantomData; From patchwork Fri Feb 9 11:18:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198830 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp789329dyd; Fri, 9 Feb 2024 03:41:41 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXGfgE4N9GyTLVCCGrOrWkqTJBKqbpqB1VoxWFU4V9oSKL6RyDUYjUb0SNKh6vPSy/SuwaBtQt/MCr3Gl+lmpU/L7Gi5g== X-Google-Smtp-Source: AGHT+IEVov6HVqvp2DR8goXOgkcXImbIbeSoEGKxao73fcYu4i7PcZFjmp2BWDcYDIiQXnJ46VHq X-Received: by 2002:a17:902:fc8d:b0:1d9:6cb4:3330 with SMTP id mf13-20020a170902fc8d00b001d96cb43330mr1741486plb.12.1707478901118; Fri, 09 Feb 2024 03:41:41 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707478901; cv=pass; d=google.com; s=arc-20160816; b=a87POCsPQvaVhyhO/tR0k8MVGI8f8d7guUo59qvfCd65UuZ1qqB85x8x1P79F22is7 hyeq2fLRaibaSW2yUBIAU5rKou0sTOoHzF4bazaWP5j1COcIhB2yNdCWQGDc5CJhPS6R s+gQ4xCE9j6u13b3lQvwPjLfZBMdaiN+jW7xT28NWZ3rN/bQQ0F3cqQM1iMSDAjVoN2m tDppsutYUTXczONdrvJ7+QP+H08uxZI+nRqO8qr2vZkAN9ngyePEJnCtqu7s7/OxtMyi VPGNdAhDUcB53KYS9qF8+2gTFGn5534uen+n82InI0qV6TYRikqw2fwIjCUKc1abz2r2 Ukgw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=EJTS0bha4jjy5RqEPvTLKlFyYUs1XDYOnmkfX5fj9c0=; fh=tWTZt33+dC5cu1HM1N3we6JD7UXdaPofR9916b/efCw=; b=FIq5Gn31JywFwBs0wK9Xm/YReYmV5Wa8TrqtyXAWTvLwsnc7z27NfRxjgfWVu1pI2T QCTDKWSXQ1QUK8aL6cigD2KYdEZz2BdAAr0KplP0HGnubh7R9j1FNnXU3F1dZviL+5i1 DtBcUJK2J18derOrjT9s6ZKezvtTNNlvvFzrCAvohDuZpuOHMYSjAEidq/m/NjqV99/D bZ8DKYQFe9NGWWSOmCi1noLggkLjM+c8I1dVdj20VG67/HHcPq4MpgqeIO98WVCqkJSR GlxTS7lqi16bwFn3FKT7c1ugzg27deksipJ5iWHDXKc/a8zrAlVzy0XZuOKbCjIXgKo8 8Kog==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=vQ8nZCQM; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59279-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59279-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCXokRDJfSEVgk+Pwi7Lirf5MUQAsoJHn0ps+grRLJMqdiQcO29NzcExfnEYdjjW2ll0FYoVIA66Zb5b8ah124VW3NlAOg== Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id kd14-20020a17090313ce00b001da105d6a6esi1040527plb.523.2024.02.09.03.41.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:41:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59279-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=vQ8nZCQM; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59279-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59279-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 121D8B26E87 for ; Fri, 9 Feb 2024 11:20:20 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1768C37153; Fri, 9 Feb 2024 11:19:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="vQ8nZCQM" Received: from mail-yb1-f202.google.com (mail-yb1-f202.google.com [209.85.219.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A18531A93 for ; Fri, 9 Feb 2024 11:18:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477537; cv=none; b=K2Ic/i4A3weihjZAJx/eM50z/uHJRIKl1NTpd0Hph+1CfwfJXsIJkHYsnw4zHGBbhxWcbRtnbLsLBRmcieXuGhv9hF65OLo2+gzbSx4lZu5EErfFc+G4VxuVNffisSeNCleqyn7lVjCIAd4aza7wxuHebi8CjZ6H6lwZ28jVfIU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477537; c=relaxed/simple; bh=HqW1OxCqhXgTLw9onxFSixvmxMjeck/nA/121BxSsCU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=SwmoHN0Otr/sWAPlkvPHUz9wkNwZ0IZ2moA5LYG6rYUVnJDFmIw2HDWgwdUjRlss2jjmJRMX0Jh0ESdla0jXjMcDiyaoycwklBEPv1YIzgKpqcuxFfRc0FIYGRjbJM8AISC66/pvhv+xsVqeu5B/KbUPLYj6TFSSYOXVmpBE2Co= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=vQ8nZCQM; arc=none smtp.client-ip=209.85.219.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yb1-f202.google.com with SMTP id 3f1490d57ef6-dc7489c346bso1830544276.0 for ; Fri, 09 Feb 2024 03:18:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477534; x=1708082334; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=EJTS0bha4jjy5RqEPvTLKlFyYUs1XDYOnmkfX5fj9c0=; b=vQ8nZCQMVeD48u13bQNQjhQCvhXFrfJ/317vfjejrwymUGw9YE1sb0VQAGRCz/m42e xfgQXP6HzlLlsikJ/mIMdzmpTEqDKs2JkApF1R28ACgi9UKz12m3UF/1ID3lAw+Wlsxv CTRshJ16/VJwD3SwlFI9u5i7bNAd6FJNtSd5qiG5WIIIVtKd+iEQckaTJS67Lf+vPsm7 +SUowlK2KIjedt5NSV/i3HO9L9SuBQ9KZPxehynwPTHBRZ4GvSgBUSCECjZrYGSy8QXk qPD1jrs1ZUEkYti7OYXqVDEuE583q6HRFhLlzdZSw3r/crzr8JRPLSMAkQCSmH1I/dUv R3MQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477534; x=1708082334; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=EJTS0bha4jjy5RqEPvTLKlFyYUs1XDYOnmkfX5fj9c0=; b=J0Kn1Vmq4lJSHkCyhfj5HyQHOulZxwGglhOFB9S07ogaWqxTsSMNOJotRYtp6qYFR3 Gx0O2QKxZOiPfILtPxdOtbzlWYJv06LrzhSC51ITyD4YaWDkiy2Za519eoHP0Ahmbic8 xR6ZYHIDmXg8mcQsedhTZK732Vk3MAHXMC9BMlsq2ZQJ9cxQJ/41HLCvj8Hn+GenbwmH bFTrJCNAUefOcOLIANMu/dfhkoIJblw3dmpKgfeVFEep+Gkr6gwMR8BNS+i1utbHVpB2 onqaF8jAapNt2KqJ8dMCQxcfhy97aq+gU/QWtz/v8eTJfdTUzeW+lYcSEBxcx0WYH5zT CbEA== X-Forwarded-Encrypted: i=1; AJvYcCURlus473mdxvkFTd9Ja+HqmLYlI6i594tmsHuvGiIz6LwNuR4H5C/dMOGfEnBV9gzEQROt8yAfTPLv3pyz5ZX5RQcI4s3ThfJ5XTgA X-Gm-Message-State: AOJu0YwpL9uYsWtY2ryuHnHyIxog3tSjvO6n61yYNS16SrONoe7vRxgo E89xGGGzFF9Max5+Th2Yt7sJFYWqtSD6tT2AKYQwooyxoOfhn1LdBbp34FnxjpeW9eNm52lnuTD QRoKzEDolia3cuQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:110c:b0:dc6:5396:c0d4 with SMTP id o12-20020a056902110c00b00dc65396c0d4mr269082ybu.1.1707477534562; Fri, 09 Feb 2024 03:18:54 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:15 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=2382; i=aliceryhl@google.com; h=from:subject:message-id; bh=HqW1OxCqhXgTLw9onxFSixvmxMjeck/nA/121BxSsCU=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoQI4IU+W0XW9N3yocqX13mqr0g65bQ44Rqb 1nUM6g4R+mJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEAAKCRAEWL7uWMY5 Rq3kD/9DzCDNzTpPSVxk82we/p3M26mN5s9Nor1fWDRM2D5T90DnGNc5ZcUuaMkmCLQ9AR/HrfK 6XbO48Iv3WM18Hp6Z7L1nmvQpREO9yEfpvEZU0/hp3fm65XQh8sgb8aw/WvPlV9EA/cOUPC1qkU 7UwWimbbAc84kcGfl6OPmwgO7LMDZVaA3ZXpM/gmvTKjNwPbhGlFIgxF1MehroH5V4Xt6ofUjLi uYFI+G2MuhLIP2wCwB0+xCaKTGm0TnCzhFsA6NapX6gYMwSv31ccsF49/VIXpEmTV2aLv3lVNL5 YpEhBLckZM5Ylx88FUkPeitP5jdZy+n6OZSvF+XbiM8WNHq80asSJb68hgUlDdp3g1Rt2U+utLk LCTwZ0sZ+RKVRXfKESJx5l5ixLcrNrVWX128W9LDehxwJNcl32krdgSPmPkSe/0VDDskdDYepLv 5ZXOwuiTaNJAMwrE+llrvF25tSESBAIfhe7j5K04armtVhpZSSmrURMVJhGEduH5AlYSjykfPQe t/nGT71DFZHFGFLRakOEacdTTgdZtLMjvTw9GEs6XX6zOW0ulTPhNuuCLG3SPDFS/VpcyfgeTt2 MaojZYlh1E5R+IjAj3b4v2cYHZcUG2Oq7DlErFTBMYzMJfppFHsFxXN94o6TFiSUiM49HBielUS JQ/rtgBVjbsIgAA== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-2-a37886783025@google.com> Subject: [PATCH v5 2/9] rust: task: add `Task::current_raw` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo , Trevor Gross X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790421396211623475 X-GMAIL-MSGID: 1790421396211623475 Introduces a safe function for getting a raw pointer to the current task. When writing bindings that need to access the current task, it is often more convenient to call a method that directly returns a raw pointer than to use the existing `Task::current` method. However, the only way to do that is `bindings::get_current()` which is unsafe since it calls into C. By introducing `Task::current_raw()`, it becomes possible to obtain a pointer to the current task without using unsafe. Link: https://lore.kernel.org/all/CAH5fLgjT48X-zYtidv31mox3C4_Ogoo_2cBOCmX0Ang3tAgGHA@mail.gmail.com/ Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Trevor Gross Signed-off-by: Alice Ryhl --- rust/kernel/task.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 148a4f4eb7a8..b579367fb923 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -97,6 +97,15 @@ unsafe impl Sync for Task {} type Pid = bindings::pid_t; impl Task { + /// Returns a raw pointer to the current task. + /// + /// It is up to the user to use the pointer correctly. + #[inline] + pub fn current_raw() -> *mut bindings::task_struct { + // SAFETY: Getting the current pointer is always safe. + unsafe { bindings::get_current() } + } + /// Returns a task reference for the currently executing task/thread. /// /// The recommended way to get the current task/thread is to use the @@ -119,14 +128,12 @@ fn deref(&self) -> &Self::Target { } } - // SAFETY: Just an FFI call with no additional safety requirements. - let ptr = unsafe { bindings::get_current() }; - + let current = Task::current_raw(); TaskRef { // SAFETY: If the current thread is still running, the current task is valid. Given // that `TaskRef` is not `Send`, we know it cannot be transferred to another thread // (where it could potentially outlive the caller). - task: unsafe { &*ptr.cast() }, + task: unsafe { &*current.cast() }, _not_send: NotThreadSafe, } } From patchwork Fri Feb 9 11:18:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198831 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp789769dyd; Fri, 9 Feb 2024 03:42:39 -0800 (PST) X-Google-Smtp-Source: AGHT+IHd0MR+SG3Q4xG3b0XLxgWhK6gH3q9VB1G2cvKZKzzZHFyof/a457DHYYWC1HTBgyoeqsuP X-Received: by 2002:a05:6a00:a1e:b0:6e0:69cd:67a2 with SMTP id p30-20020a056a000a1e00b006e069cd67a2mr1549839pfh.2.1707478958813; Fri, 09 Feb 2024 03:42:38 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707478958; cv=pass; d=google.com; s=arc-20160816; b=bha8L8o/Xs/YTd4Yzc7nJ1APdVJLZAwJPbt0gZT3hULANHpAqsOGUBWAFG1mV4vzL2 W2P2G632xPh/Kwz0nqL7uKgQzKt3/0R95T5JrGqGmU4uvw1Q9Z5l0od7pEZsZ3o85kpU XJ9ki2M7PHDrWZTL9ldslHuxPCp3ymn4fLWZ02HTBX4moacyvUIY9mt6UPVSQgGDe5dR vWJdlOtNdJE43XQdQSAdUA/9Pkdd76btczNQ0g+Al4cRw119A9f3h23kjEhn4JDTBpPf v2KOJlf4LqG/yMTA9mZC9XkuVv1YZOMqbGXUytAMyzOkwyiEdfgXG38OjKxCudneLvnH kzYA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=CxjKxa4m271sIt16a08H0uYuoD5D/IuZgZfG/a5xnr8=; fh=+TLTcSzvk9YBUcdggWH18e1wPFoYGF+y/KfwIKCpS1w=; b=shhE6xptEsyEWEtx+7dB1wBqfcCJ8YVoltQy9om+UVUN2VUkxcepdXFuE6YTZoonA4 jD1n6gNYU13COHOAokftCw9o0eZ28WNLr5U/zOqp9fvgM82GS6t/1riAGN9IhoQzKimb /yDHHlYlXobWkvLwOJJmHnFxvGgnehrABVmc4l8B2noaKF8+MNWe1URUwnM0dwMOK0bL SGQHFLArmTE31zeKYvm0IS9CwX5HCb5rVmjY79iOelRADvuQZxAuHAz6sCEyZQrUqARJ hjfU8lW758sR64rH4Ytz+byEWskgSWIMHzNU9xMIoyP7+P04B8ZAgYSLBGQ6AFKGVj7K /UZQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=DKB5JHZl; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59280-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59280-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCVAcUNe6RqZR5lnZ8pOmba12aCB1ydraQoYY9yzsZHuCApck+FfJKIvxJ36RalrBCgnWnBJWsLtHsDxhDKEu8xdzvjmqQ== Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id z4-20020a62d104000000b006e03c0c53d6si174598pfg.206.2024.02.09.03.42.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:42:38 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59280-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=DKB5JHZl; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59280-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59280-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 263F0B2ADCD for ; Fri, 9 Feb 2024 11:21:14 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F17C1376E5; Fri, 9 Feb 2024 11:19:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="DKB5JHZl" Received: from mail-yw1-f201.google.com (mail-yw1-f201.google.com [209.85.128.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3FD14364C0 for ; Fri, 9 Feb 2024 11:18:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477540; cv=none; b=TF7atmuEeUsdEezc72t2PEKEl5frXs0eGrEZUnweYVL9+fJyNwk/fv9J49YeiN6KjttLtxokxRKNS5tQUTIGZZDBVudaEK9Mqy8xXbZe/vTGvTCrscdgJFWOTIn7FWFDlw+xczObZyk1vbMd27j0QBcOJrNYbIZyde+nL0UTYnw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477540; c=relaxed/simple; bh=dVRJj3K1ZTxebz+jNk/ThYfsSj9RYrM0JXdUw2RpoVY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=erSdymbL2U/RkmDoOhLGEeoC/UjeUD9NQme+PFZLtr2tz3J9xN69VjYM1GDUl7YQoroC4A4nDe5+h1q7Lk4JpTblmhk4cm7Zf6GNCrDG+A8qKcxfmUyZOPQNeTIaUoHjJC/eDyaiEgToV0033+pX5vC+8I/FGZZzN/3XCDCRUV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=DKB5JHZl; arc=none smtp.client-ip=209.85.128.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yw1-f201.google.com with SMTP id 00721157ae682-6049520940dso18208507b3.0 for ; Fri, 09 Feb 2024 03:18:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477537; x=1708082337; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=CxjKxa4m271sIt16a08H0uYuoD5D/IuZgZfG/a5xnr8=; b=DKB5JHZlZpBHu6o7/E3rWl2MRq/HuSyK2LZ2CW0D1w4Ezr005anXZM7IHYgIdpq44z 0Ahk6Kq42nOyZ5vTJsgMZiU6nDp8BdS3EP8sZ0VErxS73J34aloof5BIFaizLzc1Jk/0 tb1I97Fy4GjSqrUSDuid3UpGDP/GU91dF54DJUiLkbRE9+MMWkzSWiyUmKdX3WpDBY/Y 7MWdmA53e907BDQbbYh1rhucj5Z7YkMNx/Dw2n0AsD9otJcyrO0Q1Apimsb+AD1YCgxD 2wIosJCpxN/FjX2ViTTHeVof3bxGP+Jwf3ZDnNJ9OInDbCf3+k4S8OcEXhBDpTkK85ee ESYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477537; x=1708082337; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CxjKxa4m271sIt16a08H0uYuoD5D/IuZgZfG/a5xnr8=; b=r0BiUnaoM57AWUVuYDhyagJ3pnrYZslZqODg259D+kgQmiCAfS96Q7pwXaVW7ctsvy 7IQPaqfiOIZV5ty7B2GBKcZkqT8DHszVL6QwUKXliW7yz1SyyRTt782SCDnjDFwV/0Ln rwtcFc2RN0BmyG3XI1v03gGelDlykGadvJSkfEwphsUWHbwBTlgdz3FsT/FweFEzGvXK USQsYNum8a2Fx1kQ0/4PEDxiucxXpiFiEbKtZHt+GEsCv8fIosNOYxeX/+HZ3XQU+jxC 2j9F5ph4yF67SLViJZ4NN7uLzZIfF0Yyq2ho+X46XGGyVFRSEKhVNChkdGc2ZsXxB3k6 Z0TQ== X-Gm-Message-State: AOJu0Yz4WSIZtbBylipnKL5jvarN4tQsQBuMFWcg4/7b/XyDtTSmBY57 QBD/K3+76eSPL2DH4lN0HzwEWknbnkUGqu+mxvymjtKJE16yI6e6D10NaUYvxE3EKOs4W8mwzZz DWs2/45jkspHwbQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a81:a00e:0:b0:602:d83f:bf36 with SMTP id x14-20020a81a00e000000b00602d83fbf36mr189436ywg.0.1707477537373; Fri, 09 Feb 2024 03:18:57 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:16 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=15736; i=aliceryhl@google.com; h=from:subject:message-id; bh=JueeAQ6jOG9u9/V4D1G7VhZ7At8WH2fyAHSp9eM4+Uc=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoRhXhv59BmRspUw4G/kHb3dIZIzl3NYoaWs Kgydf6oOWiJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEQAKCRAEWL7uWMY5 RpYBD/sGgzY+zdM3PKTstyQSOADI9/3FYUFjOIYto9VjsuVzrQ+UmRDT0XUv2zLtwenJ8gR0eBa 88OQ9cHfo9o1rYgovE0z8KXEl0j7b6+jYTRq+uXdRbnLNqUK10rBPn2LYYSFp5f15/ZKaMYnx1z rtFWEafDaBuSxLXLJ3au+EMm9crCUA/MG+v4MYjQt39jh2f0nXUYhYnMNFctN8GkOn0j2nakA0h 6k5hjvw43DGU6EgKncEQWygJAvziTz5t4ln+YRbwYdLtReMofrBS9N4aXIbHh665tvguH8hmjmc Mf1eidr+Ji+IC5ccSsKTimX9zxAgtAZ5ZB9yWunhXlOAsuhDVn4LXMGortbqkffV/JqwL3Zd4lN b4HAk85lbdgP8a8XZzo5gMMsmFnP18e0hKxEUOfhmVMcY6pfDCsS9lt01c7gqyOGBOeuHco4znI hzesDBQ5xaYjNYDtqxbJVkh8832v0vpDRCYfDJEO/mywfLl9HHv3kvVr2skFbemQ60KPywdidp3 UfL7pFGOJQc/DogxQTyTxaj5YN8O5+f/dj9YKoDaLNUlK0hDxiTbT9t/2pXVNHuFjG2WczxF42z QBakwK54cN0GkyDK2gncNFCFIwdwn46llGGoYtF9Ayf0fNKIF5ahygLl61dUmnbS3fvohWTQvhq Wez1M+zI67JtqrA== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-3-a37886783025@google.com> Subject: [PATCH v5 3/9] rust: file: add Rust abstraction for `struct file` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo , Trevor Gross X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790421456686627473 X-GMAIL-MSGID: 1790421456686627473 From: Wedson Almeida Filho This abstraction makes it possible to manipulate the open files for a process. The new `File` struct wraps the C `struct file`. When accessing it using the smart pointer `ARef`, the pointer will own a reference count to the file. When accessing it as `&File`, then the reference does not own a refcount, but the borrow checker will ensure that the reference count does not hit zero while the `&File` is live. Since this is intended to manipulate the open files of a process, we introduce an `fget` constructor that corresponds to the C `fget` method. In future patches, it will become possible to create a new fd in a process and bind it to a `File`. Rust Binder will use these to send fds from one process to another. We also provide a method for accessing the file's flags. Rust Binder will use this to access the flags of the Binder fd to check whether the non-blocking flag is set, which affects what the Binder ioctl does. This introduces a struct for the EBADF error type, rather than just using the Error type directly. This has two advantages: * `File::from_fd` returns a `Result, BadFdError>`, which the compiler will represent as a single pointer, with null being an error. This is possible because the compiler understands that `BadFdError` has only one possible value, and it also understands that the `ARef` smart pointer is guaranteed non-null. * Additionally, we promise to users of the method that the method can only fail with EBADF, which means that they can rely on this promise without having to inspect its implementation. That said, there are also two disadvantages: * Defining additional error types involves boilerplate. * The question mark operator will only utilize the `From` trait once, which prevents you from using the question mark operator on `BadFdError` in methods that return some third error type that the kernel `Error` is convertible into. (However, it works fine in methods that return `Error`.) Signed-off-by: Wedson Almeida Filho Co-developed-by: Daniel Xu Signed-off-by: Daniel Xu Co-developed-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Trevor Gross Reviewed-by: Benno Lossin Signed-off-by: Alice Ryhl --- fs/file.c | 7 ++ rust/bindings/bindings_helper.h | 2 + rust/helpers.c | 7 ++ rust/kernel/file.rs | 254 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 5 files changed, 271 insertions(+) diff --git a/fs/file.c b/fs/file.c index 3b683b9101d8..f2eab5fcb87f 100644 --- a/fs/file.c +++ b/fs/file.c @@ -1127,6 +1127,13 @@ EXPORT_SYMBOL(task_lookup_next_fdget_rcu); * * The fput_needed flag returned by fget_light should be passed to the * corresponding fput_light. + * + * (As an exception to rule 2, you can call filp_close between fget_light and + * fput_light provided that you capture a real refcount with get_file before + * the call to filp_close, and ensure that this real refcount is fput *after* + * the fput_light call.) + * + * See also the documentation in rust/kernel/file.rs. */ static unsigned long __fget_light(unsigned int fd, fmode_t mask) { diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 936651110c39..41fcd2905ed4 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/rust/helpers.c b/rust/helpers.c index 70e59efd92bc..03141a3608a4 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,12 @@ void rust_helper_init_work_with_key(struct work_struct *work, work_func_t func, } EXPORT_SYMBOL_GPL(rust_helper_init_work_with_key); +struct file *rust_helper_get_file(struct file *f) +{ + return get_file(f); +} +EXPORT_SYMBOL_GPL(rust_helper_get_file); + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indices. diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs new file mode 100644 index 000000000000..cf8ebf619379 --- /dev/null +++ b/rust/kernel/file.rs @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Files and file descriptors. +//! +//! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) and +//! [`include/linux/file.h`](srctree/include/linux/file.h) + +use crate::{ + bindings, + error::{code::*, Error, Result}, + types::{ARef, AlwaysRefCounted, Opaque}, +}; +use core::ptr; + +/// Flags associated with a [`File`]. +pub mod flags { + /// File is opened in append mode. + pub const O_APPEND: u32 = bindings::O_APPEND; + + /// Signal-driven I/O is enabled. + pub const O_ASYNC: u32 = bindings::FASYNC; + + /// Close-on-exec flag is set. + pub const O_CLOEXEC: u32 = bindings::O_CLOEXEC; + + /// File was created if it didn't already exist. + pub const O_CREAT: u32 = bindings::O_CREAT; + + /// Direct I/O is enabled for this file. + pub const O_DIRECT: u32 = bindings::O_DIRECT; + + /// File must be a directory. + pub const O_DIRECTORY: u32 = bindings::O_DIRECTORY; + + /// Like [`O_SYNC`] except metadata is not synced. + pub const O_DSYNC: u32 = bindings::O_DSYNC; + + /// Ensure that this file is created with the `open(2)` call. + pub const O_EXCL: u32 = bindings::O_EXCL; + + /// Large file size enabled (`off64_t` over `off_t`). + pub const O_LARGEFILE: u32 = bindings::O_LARGEFILE; + + /// Do not update the file last access time. + pub const O_NOATIME: u32 = bindings::O_NOATIME; + + /// File should not be used as process's controlling terminal. + pub const O_NOCTTY: u32 = bindings::O_NOCTTY; + + /// If basename of path is a symbolic link, fail open. + pub const O_NOFOLLOW: u32 = bindings::O_NOFOLLOW; + + /// File is using nonblocking I/O. + pub const O_NONBLOCK: u32 = bindings::O_NONBLOCK; + + /// File is using nonblocking I/O. + /// + /// This is effectively the same flag as [`O_NONBLOCK`] on all architectures + /// except SPARC64. + pub const O_NDELAY: u32 = bindings::O_NDELAY; + + /// Used to obtain a path file descriptor. + pub const O_PATH: u32 = bindings::O_PATH; + + /// Write operations on this file will flush data and metadata. + pub const O_SYNC: u32 = bindings::O_SYNC; + + /// This file is an unnamed temporary regular file. + pub const O_TMPFILE: u32 = bindings::O_TMPFILE; + + /// File should be truncated to length 0. + pub const O_TRUNC: u32 = bindings::O_TRUNC; + + /// Bitmask for access mode flags. + /// + /// # Examples + /// + /// ``` + /// use kernel::file; + /// # fn do_something() {} + /// # let flags = 0; + /// if (flags & file::flags::O_ACCMODE) == file::flags::O_RDONLY { + /// do_something(); + /// } + /// ``` + pub const O_ACCMODE: u32 = bindings::O_ACCMODE; + + /// File is read only. + pub const O_RDONLY: u32 = bindings::O_RDONLY; + + /// File is write only. + pub const O_WRONLY: u32 = bindings::O_WRONLY; + + /// File can be both read and written. + pub const O_RDWR: u32 = bindings::O_RDWR; +} + +/// Wraps the kernel's `struct file`. +/// +/// This represents an open file rather than a file on a filesystem. Processes generally reference +/// open files using file descriptors. However, file descriptors are not the same as files. A file +/// descriptor is just an integer that corresponds to a file, and a single file may be referenced +/// by multiple file descriptors. +/// +/// # Refcounting +/// +/// Instances of this type are reference-counted. The reference count is incremented by the +/// `fget`/`get_file` functions and decremented by `fput`. The Rust type `ARef` represents a +/// pointer that owns a reference count on the file. +/// +/// Whenever a process opens a file descriptor (fd), it stores a pointer to the file in its `struct +/// files_struct`. This pointer owns a reference count to the file, ensuring the file isn't +/// prematurely deleted while the file descriptor is open. In Rust terminology, the pointers in +/// `struct files_struct` are `ARef` pointers. +/// +/// ## Light refcounts +/// +/// Whenever a process has an fd to a file, it may use something called a "light refcount" as a +/// performance optimization. Light refcounts are acquired by calling `fdget` and released with +/// `fdput`. The idea behind light refcounts is that if the fd is not closed between the calls to +/// `fdget` and `fdput`, then the refcount cannot hit zero during that time, as the `struct +/// files_struct` holds a reference until the fd is closed. This means that it's safe to access the +/// file even if `fdget` does not increment the refcount. +/// +/// The requirement that the fd is not closed during a light refcount applies globally across all +/// threads - not just on the thread using the light refcount. For this reason, light refcounts are +/// only used when the `struct files_struct` is not shared with other threads, since this ensures +/// that other unrelated threads cannot suddenly start using the fd and close it. Therefore, +/// calling `fdget` on a shared `struct files_struct` creates a normal refcount instead of a light +/// refcount. +/// +/// Light reference counts must be released with `fdput` before the system call returns to +/// userspace. This means that if you wait until the current system call returns to userspace, then +/// all light refcounts that existed at the time have gone away. +/// +/// ## Rust references +/// +/// The reference type `&File` is similar to light refcounts: +/// +/// * `&File` references don't own a reference count. They can only exist as long as the reference +/// count stays positive, and can only be created when there is some mechanism in place to ensure +/// this. +/// +/// * The Rust borrow-checker normally ensures this by enforcing that the `ARef` from which +/// a `&File` is created outlives the `&File`. +/// +/// * Using the unsafe [`File::from_ptr`] means that it is up to the caller to ensure that the +/// `&File` only exists while the reference count is positive. +/// +/// * You can think of `fdget` as using an fd to look up an `ARef` in the `struct +/// files_struct` and create an `&File` from it. The "fd cannot be closed" rule is like the Rust +/// rule "the `ARef` must outlive the `&File`". +/// +/// # Invariants +/// +/// * Instances of this type are refcounted using the `f_count` field. +/// * If an fd with active light refcounts is closed, then it must be the case that the file +/// refcount is positive until all light refcounts of the fd have been dropped. +/// * A light refcount must be dropped before returning to userspace. +#[repr(transparent)] +pub struct File(Opaque); + +// SAFETY: +// - `File::dec_ref` can be called from any thread. +// - It is okay to send ownership of `struct file` across thread boundaries. +unsafe impl Send for File {} + +// SAFETY: All methods defined on `File` that take `&self` are safe to call even if other threads +// are concurrently accessing the same `struct file`, because those methods either access immutable +// properties or have proper synchronization to ensure that such accesses are safe. +unsafe impl Sync for File {} + +impl File { + /// Constructs a new `struct file` wrapper from a file descriptor. + /// + /// The file descriptor belongs to the current process. + pub fn fget(fd: u32) -> Result, BadFdError> { + // SAFETY: FFI call, there are no requirements on `fd`. + let ptr = ptr::NonNull::new(unsafe { bindings::fget(fd) }).ok_or(BadFdError)?; + + // SAFETY: `bindings::fget` either returns null or a valid pointer to a file, and we + // checked for null above. + // + // INVARIANT: `bindings::fget` creates a refcount, and we pass ownership of the refcount to + // the new `ARef`. + Ok(unsafe { ARef::from_raw(ptr.cast()) }) + } + + /// Creates a reference to a [`File`] from a valid pointer. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` points at a valid file and that the file's refcount is + /// positive for the duration of 'a. + pub unsafe fn from_ptr<'a>(ptr: *const bindings::file) -> &'a File { + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the + // duration of 'a. The cast is okay because `File` is `repr(transparent)`. + // + // INVARIANT: The safety requirements guarantee that the refcount does not hit zero during + // 'a. + unsafe { &*ptr.cast() } + } + + /// Returns a raw pointer to the inner C struct. + #[inline] + pub fn as_ptr(&self) -> *mut bindings::file { + self.0.get() + } + + /// Returns the flags associated with the file. + /// + /// The flags are a combination of the constants in [`flags`]. + pub fn flags(&self) -> u32 { + // This `read_volatile` is intended to correspond to a READ_ONCE call. + // + // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount. + // + // FIXME(read_once): Replace with `read_once` when available on the Rust side. + unsafe { core::ptr::addr_of!((*self.as_ptr()).f_flags).read_volatile() } + } +} + +// SAFETY: The type invariants guarantee that `File` is always ref-counted. This implementation +// makes `ARef` own a normal refcount. +unsafe impl AlwaysRefCounted for File { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::get_file(self.as_ptr()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we + // may drop it. The cast is okay since `File` has the same representation as `struct file`. + unsafe { bindings::fput(obj.cast().as_ptr()) } + } +} + +/// Represents the `EBADF` error code. +/// +/// Used for methods that can only fail with `EBADF`. +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct BadFdError; + +impl From for Error { + fn from(_: BadFdError) -> Error { + EBADF + } +} + +impl core::fmt::Debug for BadFdError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.pad("EBADF") + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index b89ecf4e97a0..9353dd713a20 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -34,6 +34,7 @@ mod allocator; mod build_assert; pub mod error; +pub mod file; pub mod init; pub mod ioctl; #[cfg(CONFIG_KUNIT)] From patchwork Fri Feb 9 11:18:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198822 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780772dyd; Fri, 9 Feb 2024 03:22:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IGoclYphKjr9JJzxGIi276lcIfn+ufqnTHsd8Jz6M2iYFFBq5y4wTGcj2Mss4UPspC0NQh/ X-Received: by 2002:a17:906:6806:b0:a38:9ff:571d with SMTP id k6-20020a170906680600b00a3809ff571dmr1055559ejr.34.1707477764098; Fri, 09 Feb 2024 03:22:44 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477764; cv=pass; d=google.com; s=arc-20160816; b=khbykcdwYFQ6mNZOe9QpigTzU7QrZYbgN0CaymXL9/sbkxlYrpcx+gjC1ozrQ6YNq2 f6d9idtXeZqCSPyZcRpdike9t+PjcJAOOm2yPe6TOVhm+UpXY2pB/8tOo/Oeo4QWddMf oU0m50iVSc5ZIuqyFywx3eswh5BdqOsgaoyEu5fk1xDhSNpjyEGqBzB6nw14+DKnQ9gT O2UaJRBGOhJlIJ+DMWcJPKFeaxaebdm2bKs+IRaMvD9JR/JCjijMHslgcz9eiBwqnp4+ 66pq7FCP4s9zyeba+RjUQiEcMIxG+tZ2IRNWiIIdJnJzVZQ+N55oz+tMk9fK1lVYkGe3 uI0Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=6FCYANgF4lGfBb0oow1nW4bsB/Fdu+fIcf3p3BOVfZo=; fh=Uz6qLJiDSoTYlriPEgxhi2tOpmevOJKWZHXE1Jond8U=; b=MwAUknC/Lwt0Cifb21bJibw5jNGt8zYVG0OG7Bn2lmAbza6bdLZkZ57flz2HFxRFdc IMwSaZb/k7q4zpYOqRXcdZYTVC3c8XSe66BDCVfL0xLfLOIwwman5Hci1uZ8w0syyHWj F/O0CZ5KegCKFuH1iZAurMVM9xnQgtd507x+j08UD/b+InCe7GMtS7nDqIzG/Lvd30X4 vp4o1ny2bpOFWXKkIrHb+fKDBP30Bwu0OxhzAQ10j3B1O5thHHVmg1Fb0+9fs67zaTzR xDbeM9sER0KTY1iz5n8UFW7K7xj7zeUQjPrVhiXEXW08VXB4hx62aqLFAwENyFsWM+bq G6dw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="bSLV/VQ2"; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59282-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59282-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWNrDoRBJm8REmXHRR12nHMHJ+fIrZ7VNkd+sms5tt+EuMvvN3R1hrAjhqNCTfKeN3rA6zvWeYIiEpb5XXDRS5mg3puRg== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id jj16-20020a170907985000b00a385414b18asi744003ejc.83.2024.02.09.03.22.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:22:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59282-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="bSLV/VQ2"; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59282-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59282-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id A978F1F256FB for ; Fri, 9 Feb 2024 11:21:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4BAF738382; Fri, 9 Feb 2024 11:19:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bSLV/VQ2" Received: from mail-lj1-f202.google.com (mail-lj1-f202.google.com [209.85.208.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73518374D9 for ; Fri, 9 Feb 2024 11:19:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477544; cv=none; b=XpIU+bsWCvAEAsw/o65FNBwDMW8lk5TIBUgSt3q35FbyT8PiTbdV+huuEshAbFkeBnM5DoGrKcDlQRWVvNh+AkZ1LscIuwYtU9n4DGGV1rhECPFyQEeBeD0/VjXNkKcJYlVPnXEwoQZafAgUxrCdmFgz5kP87oN0PFsCed0apS0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477544; c=relaxed/simple; bh=6s2gn0oE8oc/3LtJyrV+uh/JSqxQjhps1bnBqWxXGbI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Cxes9w6aqylvQ0Fx/FQe8eT+mo0CPa0tD+YyX7nvHnklIsCeA9vJYAg+eaD6CckDp5U0nhvBEYl7aseBurBCQxwaCMb9Ywg1GmmxcdrmWgol7kIM2xbS3igHQ2rUVwCAwZVGaTIZO9SqdTDLLrwulLW76uXjKBsd35+6n+6TESs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=bSLV/VQ2; arc=none smtp.client-ip=209.85.208.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-lj1-f202.google.com with SMTP id 38308e7fff4ca-2d0a329e86cso8129211fa.3 for ; Fri, 09 Feb 2024 03:19:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477540; x=1708082340; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=6FCYANgF4lGfBb0oow1nW4bsB/Fdu+fIcf3p3BOVfZo=; b=bSLV/VQ2HR6K2ekMF7QjV/PvAWgoLu8FwVtsInnaYPKSwpjw3UR8iHksj8RHklnlTq iteB3pZtdO24Dw4b3F4Gm27DAgmmGcbY9Kap3eYqiGBWmlkWxH+myH4P87sa/mqeZIQM RScRbzNLwvYNC0TGeliS3lXfJes6C0SOx/S5444/mbv4V0A1DW3Jlp6dMjFgl0MsZcdC /9X8h8vXO3phvhJD+bRUNowTpK5bAGCdmgKL6cdEjrJGzK4yBeUBKLRdEyxX29skUKE7 p7rN9JCdk3TkmJ4L6l5Q051eDaF77ht8aLdcP9NtnuH1BSQMFFFOOVnu+enSX7nEwtmU 42kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477540; x=1708082340; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=6FCYANgF4lGfBb0oow1nW4bsB/Fdu+fIcf3p3BOVfZo=; b=G5IXPE+ccdbGvYayt1qWB1cT9t/fHfbBIgcx1MyM4dMJ0rwr85j3hvP+8rcbS2Uo+x HR4dd+oMl64Gd4+MPGiJ776SwyH1/bTPkH0RJa/yEvnU1sWjMqi0wvNkxNt1aMyhJ1o2 BJiQ9X1uRnwBJKhJJoiJvnOLJfLgxRtYJg/JeX64h1oWlLPcyK44QzDpCMmVEWjn2bwQ lQrhwu/36/mEKCw2dEGKsHg6EYaHRpnrnj0naZ65x63hqvPP7lFlHdwkSzRgWS2HHGQ5 crkiQY5G07wCrHti9svS7QUHeTf2WIM70XU8+lwhNo5GfcJUp5VsP1fNIvJKjcYNC9Xq camQ== X-Gm-Message-State: AOJu0YxIzWTkPKHD/ffGaTLM/yu9nRlt9ptWXbXNxrhcoUUwugRld6+F anj5WaqJGw6KAoOtn56YH8omE0uKCRRVx60hzd06Vtltg+ljDWckgnmFb9+o9DzlH2CywxfUGWz OOfJsd5qY9mnm5g== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:651c:b20:b0:2d0:dd94:4ca9 with SMTP id b32-20020a05651c0b2000b002d0dd944ca9mr1166ljr.0.1707477540357; Fri, 09 Feb 2024 03:19:00 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:17 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7117; i=aliceryhl@google.com; h=from:subject:message-id; bh=E3RpArjiH4nioml1kPKUKUnKZduDlkajGIRmbXxIUMA=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoR52G40En1ErRk4ewFgUO8fX4mp3h9lJumG l6RPs7WbD6JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEQAKCRAEWL7uWMY5 Rp5kEACcB92TIqUG+z0wBikO2hBIPI7gjDYF3SHW0x5qjB5WvxXic9+h71rZXkkrtlC/zD6x/Lu djaZpWwQUHHw1uJLA+7wmn0+GXGBjC97rhwZXktQIH5a+6rypSwJQ5e4QkFuvU623gZd7/mM7EQ N7uE56h/3UxdTFaEG1T8n6syqdmDWE1RqJkVU3CqU2CbrhjlZD1DVBomBv30NN2/FkO2/dMPCev C1O3Eeb7XXtD679sNvHggESeASeXsy+fSuaCtoL7dAoIBNsnS1htn8NvZ12obEzaxIWlav9Csll 6RZKO+x4psyQNuWqdaJnkPbfrWwmj1A3nPDN+myeVrN68orgcbIuYUbrACh37J4qel3WrWKHrla 9PPFaVhFPppwU+DnCvrZ7+nW/D+RqdVklU/DvK6+QE/dk42M5Kd0NhvgTBYfTUtITZG2yiK7F/n TiriCyvgW9hf73sZO8/kmkS1qa0Qg+HAjpqBa+ErKZiDigrABYAOso2bUPv3vhzVGMl1RyLH2xG aRSFY0rXlw1u3+s2mukvotlUWn727P1tSZMBHgIzAyiXZx7ImEXYeCgv2fUy1CQ68/+UQET3v1H 6xBPL+rrZLa9rPSu564U2gSmpBWhReIrdmCxnqSCpeK0UV1fhA3wpZsuFU558GuwbzrZ0t85Xxw B4dqH8Rwrzg329w== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-4-a37886783025@google.com> Subject: [PATCH v5 4/9] rust: cred: add Rust abstraction for `struct cred` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Trevor Gross , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420203940080525 X-GMAIL-MSGID: 1790420203940080525 From: Wedson Almeida Filho Add a wrapper around `struct cred` called `Credential`, and provide functionality to get the `Credential` associated with a `File`. Rust Binder must check the credentials of processes when they attempt to perform various operations, and these checks usually take a `&Credential` as parameter. The security_binder_set_context_mgr function would be one example. This patch is necessary to access these security_* methods from Rust. Signed-off-by: Wedson Almeida Filho Co-developed-by: Alice Ryhl Reviewed-by: Trevor Gross Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Alice Ryhl --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 13 ++++++++ rust/kernel/cred.rs | 74 +++++++++++++++++++++++++++++++++++++++++ rust/kernel/file.rs | 13 ++++++++ rust/kernel/lib.rs | 1 + 5 files changed, 102 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 41fcd2905ed4..84a56e8b6b67 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -7,6 +7,7 @@ */ #include +#include #include #include #include diff --git a/rust/helpers.c b/rust/helpers.c index 03141a3608a4..10ed69f76424 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -164,6 +165,18 @@ struct file *rust_helper_get_file(struct file *f) } EXPORT_SYMBOL_GPL(rust_helper_get_file); +const struct cred *rust_helper_get_cred(const struct cred *cred) +{ + return get_cred(cred); +} +EXPORT_SYMBOL_GPL(rust_helper_get_cred); + +void rust_helper_put_cred(const struct cred *cred) +{ + put_cred(cred); +} +EXPORT_SYMBOL_GPL(rust_helper_put_cred); + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indices. diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs new file mode 100644 index 000000000000..360d6fdbe5e7 --- /dev/null +++ b/rust/kernel/cred.rs @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Credentials management. +//! +//! C header: [`include/linux/cred.h`](srctree/include/linux/cred.h). +//! +//! Reference: + +use crate::{ + bindings, + types::{AlwaysRefCounted, Opaque}, +}; + +/// Wraps the kernel's `struct cred`. +/// +/// Credentials are used for various security checks in the kernel. +/// +/// Most fields of credentials are immutable. When things have their credentials changed, that +/// happens by replacing the credential instead of changing an existing credential. See the [kernel +/// documentation][ref] for more info on this. +/// +/// # Invariants +/// +/// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the +/// allocation remains valid at least until the matching call to `put_cred`. +/// +/// [ref]: https://www.kernel.org/doc/html/latest/security/credentials.html +#[repr(transparent)] +pub struct Credential(Opaque); + +// SAFETY: +// - `Credential::dec_ref` can be called from any thread. +// - It is okay to send ownership of `Credential` across thread boundaries. +unsafe impl Send for Credential {} + +// SAFETY: It's OK to access `Credential` through shared references from other threads because +// we're either accessing properties that don't change or that are properly synchronised by C code. +unsafe impl Sync for Credential {} + +impl Credential { + /// Creates a reference to a [`Credential`] from a valid pointer. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the + /// returned [`Credential`] reference. + pub unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Credential { + // SAFETY: The safety requirements guarantee the validity of the dereference, while the + // `Credential` type being transparent makes the cast ok. + unsafe { &*ptr.cast() } + } + + /// Returns the effective UID of the given credential. + pub fn euid(&self) -> bindings::kuid_t { + // SAFETY: By the type invariant, we know that `self.0` is valid. Furthermore, the `euid` + // field of a credential is never changed after initialization, so there is no potential + // for data races. + unsafe { (*self.0.get()).euid } + } +} + +// SAFETY: The type invariants guarantee that `Credential` is always ref-counted. +unsafe impl AlwaysRefCounted for Credential { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::get_cred(self.0.get()) }; + } + + unsafe fn dec_ref(obj: core::ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. The cast is okay + // because `Credential` has the same representation as `struct cred`. + unsafe { bindings::put_cred(obj.cast().as_ptr()) }; + } +} diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs index cf8ebf619379..3a64c5022941 100644 --- a/rust/kernel/file.rs +++ b/rust/kernel/file.rs @@ -7,6 +7,7 @@ use crate::{ bindings, + cred::Credential, error::{code::*, Error, Result}, types::{ARef, AlwaysRefCounted, Opaque}, }; @@ -207,6 +208,18 @@ pub fn as_ptr(&self) -> *mut bindings::file { self.0.get() } + /// Returns the credentials of the task that originally opened the file. + pub fn cred(&self) -> &Credential { + // SAFETY: It's okay to read the `f_cred` field without synchronization because `f_cred` is + // never changed after initialization of the file. + let ptr = unsafe { (*self.as_ptr()).f_cred }; + + // SAFETY: The signature of this function ensures that the caller will only access the + // returned credential while the file is still valid, and the C side ensures that the + // credential stays valid at least as long as the file. + unsafe { Credential::from_ptr(ptr) } + } + /// Returns the flags associated with the file. /// /// The flags are a combination of the constants in [`flags`]. diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 9353dd713a20..f65e5978f807 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -33,6 +33,7 @@ #[cfg(not(testlib))] mod allocator; mod build_assert; +pub mod cred; pub mod error; pub mod file; pub mod init; From patchwork Fri Feb 9 11:18:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198820 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780365dyd; Fri, 9 Feb 2024 03:21:49 -0800 (PST) X-Google-Smtp-Source: AGHT+IGEWwGVqBEGx7rbjI1o51dOseBPmWMg9LF4fdancbQgMKr3BjmVdYmNJk0ELv+E/5juXNLp X-Received: by 2002:a0c:e144:0:b0:68c:ae2d:a3c with SMTP id c4-20020a0ce144000000b0068cae2d0a3cmr1193583qvl.5.1707477709001; Fri, 09 Feb 2024 03:21:49 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477708; cv=pass; d=google.com; s=arc-20160816; b=K6Ea8GK59AfWpgKQnqRee2/pMsDZ73KgiyF2JIJQVof2vZ13GjAUC0fjyLMK4+21pm 6unA9HLKm2YHfAMKJbgAjZlRpErzbIKneSTdDCkKNTEKrfCe3gr5dy/ItK9wlL3Lf5PG b7SGwqCcxbokzzsZDT7AvDnfAFi2GKdPVJOOeyLJIfP6n2Bk5I1cxvr8nrOcW/Lajr33 flnlhq2tk+o425dP+Tmhr4eIv8nEKg3ZvMDBRQxdxqhNAuONL7+XheYJvXsIHzD3R5nh v4VVnjVUZVA/ajg4BXC9LuP6e37pclNUEwbIXYefDFj3gGqyRoJNjfKNfgYNk3rl9/IG Byww== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=N6zYzDocV9Qhlicntw8rLmKyg1TDcaEgd7JNHcXSwhg=; fh=xgCmI2WPkhK8nS+y8wc+2YdSyD9+69Fj5a1HuVqxPLQ=; b=lPf8VgON3cBnV2c0DPDMTykvsDi+pkI5nyCxdy2NQrEY9ZXd9TCrg0IJARf9qbeTra 93/G+NMuhVyT5kBO7yZKYRnyCy1gPFoTkUCxTMNpHK+PduWfWbm+U0+VRIJG/ejoyXtV MHPHZ1tRyZVDy8p+CYWIEWnvWQYJpoCKF7qFpqrj1TaGoQk6N/89CkyL3raokTCM2W3z LbuuV34u5YoV/K1dv2zF0tI0hX0aRidCySR4jfYM/SvpTy0nIhs3MYsVVZ+n396kRQtQ 6BNuxd2sArrRFtGJRtM15mPvhGP9NdwKE3zZkYjdv/zhk8XGZootbZ95OHythw1nPE2l GRWg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=g6OIXAg3; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59283-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59283-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWIIPw1dScn1hrEgnoggoH8d9kg0FkylavjKAgPUzcxwkR+U+H9CSVySqpseuW41YKo/3CMlpxInyeCWD3UYIKcvTZMdQ== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id t5-20020a0562140c6500b0068cc7eea8a4si1591563qvj.587.2024.02.09.03.21.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:21:48 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59283-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=g6OIXAg3; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59283-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59283-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id A67B81C245E2 for ; Fri, 9 Feb 2024 11:21:48 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9392A3C46A; Fri, 9 Feb 2024 11:19:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="g6OIXAg3" Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B20D2E401 for ; Fri, 9 Feb 2024 11:19:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477546; cv=none; b=YPnq5mPdZ/3XuKLdaP6Ra2dI32lZJRyQrAkhm2uUyrFmiKM5cFwwvWLM2l9bHp+BxmEeeyEq2E5pCdv+8MwikSS2rS3Llifc7MiZMq2wqDe1np8XfGdXe3xo+vuEse5f9/v3ivPpqQRFRNzqZlru1ankT7H4BpjxSq6YKLm3aQk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477546; c=relaxed/simple; bh=JMsIaHhJXFHUUWu3yyeKAXmjMagByT5pUYTSUjzRo54=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=kzClETc1W8Wn9R5F1R7CZWGU+RJu+L1bP3R0ccvanZTq/THPgPAfN7EkpsPSvkooVn5rVt7QE2TRszxKyomlPZH16EfNEL4vkE1XLRbJVmPMfikxL6BR5QdCk5x/vFmyl7Tq0enucAIjdo7EGK40Kd5iF1duSQ3s0mey0SeQlVg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=g6OIXAg3; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dc6b26783b4so1236883276.0 for ; Fri, 09 Feb 2024 03:19:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477543; x=1708082343; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=N6zYzDocV9Qhlicntw8rLmKyg1TDcaEgd7JNHcXSwhg=; b=g6OIXAg3wHu/7YUa1U/CGpqVfac34vYbBOtMiVPZDPG06iMKKesqy3W7vEMQdO753P OWzG1HqZ0ddUUIPyG7kSir6bHDzB2cwiCWqp75rodl45VDZFT4gOaXMnVaDXvte/CK9b ayRGlfnoAeZheW9vy/neNodNUektYmDP8NO/j+iWXlzIuwasSITn0+NptCO5Ys/52Bk2 JD7+ExngMcelYPETWAAmQEgNLzNoDjzLKvrl/sCkbrLmGssT1oQUBFdVkYUCfxkdVyTs KzmUw9gJmZgQQibUvaXmKCek6zNDzaqn5FHdHKK6I5mXaxmjeRLnQRd0bqQoa+cfVj42 Ya5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477543; x=1708082343; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=N6zYzDocV9Qhlicntw8rLmKyg1TDcaEgd7JNHcXSwhg=; b=oOiEKcPZQo6dfZsfjBn/dlEa0s38rTsKPekUlGqtX4zfYgVnR6r39CrcoqiMtCKo/s ZKa7/W/+In+HoohefqrsWRcPzXQuUJMJWpu4slzdZj0SojT58bv8jaKPDXiOx8lT5s+0 OnBe5P031SuSfsx5kOwbT1xXmc+T7kN97z51b9jrY9pC3FuxuqL9LSvmNq+JU2m7oMbn Gl+xEyG0S9XxTuW3+iN9hITljnzQw67CeiMu0fnYVg/j5sMFKNVTBX+bDFasomit9DZA rwxvQnCS0NcIdoXgbnFChTdb/j/1looLbzp+fHEMbv48MG1e/8+R11QrTnr67zYphVyr j32w== X-Gm-Message-State: AOJu0YyXitNmSgnSG0w4pbhhaKBspGwBfuO5DDrEdLFQic63DQWDFSW9 W2FtF5ieFcXShdfuWzz2isIy6RxfgdJ+N9cxacsc9y+UF9XOotRBTEZFpb/RvPpMx0cei5gCnTF 1bt5K1CXSpyIO5w== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:1004:b0:dc7:3189:4e75 with SMTP id w4-20020a056902100400b00dc731894e75mr18645ybt.3.1707477543307; Fri, 09 Feb 2024 03:19:03 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:18 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=6444; i=aliceryhl@google.com; h=from:subject:message-id; bh=JMsIaHhJXFHUUWu3yyeKAXmjMagByT5pUYTSUjzRo54=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoS6Bl6o/Gc13YOU7SZw4BO7f0q+SLSNyZw2 c03VNDoUq+JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEgAKCRAEWL7uWMY5 RtbXD/9SpVOukf20wD3Lw87sf+QOlVl4wKCvVksht02nEFck15Jq9lBGWB85P/VDxzNwvNYVFjm Y5DNk9Gjo38nqA2ISJBdUn5PRONTd6c/6D/sxwmSsWwwYMyW/1DfrEyniql9ATz7twTo5SDG0qv olUGwCmGJzenMA7rqUBkkI2cmsFnZmTV+HrcN3z89Qq2Ftwdu9Nd8wwkitOQizW0P5TDH7ZlHvt Jw1Tmc57E9Me7k2F2oPlnEzaXKBXHm6dm7RQX8tnDI4tr2ohz81lGXjZjWVJR40ZTfv9XtvK3N2 8o7YD3uFWrW0Facera6I6wmZQcCPBnBHfEpQpxLuNNrgjOkgm5HaRUKMjKk3r67B7n1VhD58LEU qMS8DHGngzMFLTpMVLt1O14hdR/6dJiZFKIIwC0VK6lttv6lSVIFMdpjgwMi19YeYIblP9Z5WDJ HBf2LdD4rFr7a3GH3Y6FRocdQ5/8cjVQa2C76C8XFQYBemIDAbRM0nS1Xg4aSYEbFpN1mvohDDs 062FJ7Ao7kbGM1rtND9HXnrhpo3quUnyP15jdL+a4hJpks6w0fxOaOpiKPles1qgVVU5pcIfh8l pQFm418ktkJhnNrd6KthgBv70AlbiEBQjGF4KUEfhhxBTJu/Mxrp67/ED6Bg1YtoHwSL6lUT28C mcih4vpjTnWaIOQ== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-5-a37886783025@google.com> Subject: [PATCH v5 5/9] rust: security: add abstraction for secctx From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo , Trevor Gross X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420146466741002 X-GMAIL-MSGID: 1790420146466741002 Add an abstraction for viewing the string representation of a security context. This is needed by Rust Binder because it has a feature where a process can view the string representation of the security context for incoming transactions. The process can use that to authenticate incoming transactions, and since the feature is provided by the kernel, the process can trust that the security context is legitimate. Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Trevor Gross Signed-off-by: Alice Ryhl --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 21 ++++++++++++ rust/kernel/cred.rs | 8 +++++ rust/kernel/lib.rs | 1 + rust/kernel/security.rs | 72 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 84a56e8b6b67..5ca497d786f0 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers.c b/rust/helpers.c index 10ed69f76424..fd633d9db79a 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -177,6 +178,26 @@ void rust_helper_put_cred(const struct cred *cred) } EXPORT_SYMBOL_GPL(rust_helper_put_cred); +#ifndef CONFIG_SECURITY +void rust_helper_security_cred_getsecid(const struct cred *c, u32 *secid) +{ + security_cred_getsecid(c, secid); +} +EXPORT_SYMBOL_GPL(rust_helper_security_cred_getsecid); + +int rust_helper_security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +{ + return security_secid_to_secctx(secid, secdata, seclen); +} +EXPORT_SYMBOL_GPL(rust_helper_security_secid_to_secctx); + +void rust_helper_security_release_secctx(char *secdata, u32 seclen) +{ + security_release_secctx(secdata, seclen); +} +EXPORT_SYMBOL_GPL(rust_helper_security_release_secctx); +#endif + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indices. diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs index 360d6fdbe5e7..fdd899040098 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -50,6 +50,14 @@ pub unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Credential { unsafe { &*ptr.cast() } } + /// Get the id for this security context. + pub fn get_secid(&self) -> u32 { + let mut secid = 0; + // SAFETY: The invariants of this type ensures that the pointer is valid. + unsafe { bindings::security_cred_getsecid(self.0.get(), &mut secid) }; + secid + } + /// Returns the effective UID of the given credential. pub fn euid(&self) -> bindings::kuid_t { // SAFETY: By the type invariant, we know that `self.0` is valid. Furthermore, the `euid` diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index f65e5978f807..d55d065642f0 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -44,6 +44,7 @@ pub mod net; pub mod prelude; pub mod print; +pub mod security; mod static_assert; #[doc(hidden)] pub mod std_vendor; diff --git a/rust/kernel/security.rs b/rust/kernel/security.rs new file mode 100644 index 000000000000..ee2ef0385bae --- /dev/null +++ b/rust/kernel/security.rs @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Linux Security Modules (LSM). +//! +//! C header: [`include/linux/security.h`](srctree/include/linux/security.h). + +use crate::{ + bindings, + error::{to_result, Result}, +}; + +/// A security context string. +/// +/// # Invariants +/// +/// The `secdata` and `seclen` fields correspond to a valid security context as returned by a +/// successful call to `security_secid_to_secctx`, that has not yet been destroyed by calling +/// `security_release_secctx`. +pub struct SecurityCtx { + secdata: *mut core::ffi::c_char, + seclen: usize, +} + +impl SecurityCtx { + /// Get the security context given its id. + pub fn from_secid(secid: u32) -> Result { + let mut secdata = core::ptr::null_mut(); + let mut seclen = 0u32; + // SAFETY: Just a C FFI call. The pointers are valid for writes. + to_result(unsafe { bindings::security_secid_to_secctx(secid, &mut secdata, &mut seclen) })?; + + // INVARIANT: If the above call did not fail, then we have a valid security context. + Ok(Self { + secdata, + seclen: seclen as usize, + }) + } + + /// Returns whether the security context is empty. + pub fn is_empty(&self) -> bool { + self.seclen == 0 + } + + /// Returns the length of this security context. + pub fn len(&self) -> usize { + self.seclen + } + + /// Returns the bytes for this security context. + pub fn as_bytes(&self) -> &[u8] { + let ptr = self.secdata; + if ptr.is_null() { + debug_assert_eq!(self.seclen, 0); + // We can't pass a null pointer to `slice::from_raw_parts` even if the length is zero. + return &[]; + } + + // SAFETY: The call to `security_secid_to_secctx` guarantees that the pointer is valid for + // `seclen` bytes. Furthermore, if the length is zero, then we have ensured that the + // pointer is not null. + unsafe { core::slice::from_raw_parts(ptr.cast(), self.seclen) } + } +} + +impl Drop for SecurityCtx { + fn drop(&mut self) { + // SAFETY: By the invariant of `Self`, this frees a pointer that came from a successful + // call to `security_secid_to_secctx` and has not yet been destroyed by + // `security_release_secctx`. + unsafe { bindings::security_release_secctx(self.secdata, self.seclen as u32) }; + } +} From patchwork Fri Feb 9 11:18:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198823 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780868dyd; Fri, 9 Feb 2024 03:22:57 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUSIlmtFII4rmFQ05q8KRT0aerl2rOYBCOlELliDRUJoe8WcKE6UxHroOScDHYG7FZqW77ElkYnViQmYyabGJ+hdf8pyQ== X-Google-Smtp-Source: AGHT+IFbTZuiBzfO6IgkHEWHDpx0+rHVZzDn6sQT3/glFJ2543VGJlNYqE1AbVAW5YS8+EFb4P41 X-Received: by 2002:aa7:c417:0:b0:55f:e35e:137c with SMTP id j23-20020aa7c417000000b0055fe35e137cmr985711edq.25.1707477776857; Fri, 09 Feb 2024 03:22:56 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477776; cv=pass; d=google.com; s=arc-20160816; b=QJwPAhUlvdeLt92FwkCs6nigvhelUS7RbTmTH2Yzx7rtB6ZOPzpAMXH61FYOsCXiE3 mBjpZoKjU2O7sEJR0VQxNIed/87yu0qA9H2jrOnWHL2uRRd/+rX3hV+ASy7vnhZa4XOg k7ScohFsLjXQDi2KCvpoOwJ+85vBikf8SDl3IGL2r+9PakBmh+kDGhQ7Wi8hO66wQxfI AK4rfzyRCm5xaskmeo6+GvzFuB8JzK8i6WJ76pvP82DR1XlfiavHgp0+3zEEBqNwLtp/ AOv+Z7GrZj7+sOtKsgEITvAJtqf3t5cswd8C895XuuXFnOmYf6V1SMGkpzL2Yu3KwJ3V +JdQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=dH78NmaaVu9DkNui20oQ6e4x0KTKrZZbiJBCrE6Owok=; fh=C1S12IdyxpN8cCr3fpJqzmzSXssQQIbel2mvace1t1A=; b=gapxHAraYuSPqm/V+5JJ8nS/7Gmvjucmqyw2AyFCmMaGQjPY1UzILvEQn+lT/oNQK7 Db0Ao62f9jPVxY6jA8HUHhxZ7F1IsmuDNUpJS199DB5Ox7F+oTJdoniPOntPFBrV1Gpv cqtXxf/XjtRALo+euq1PKvhLL06+sKIW+z43HpzFCH5osc+HwzwEIc1Iy991L/Hh1s3Z hR+bL27ozbDGOnRE6j/MeJjB/EWqGniCKrznU71V3fxktSJJ4QPNV7Nu8aP8nQJ7dPXP awjuddixunIoRvX58kAomwWaL13Gahw5OZvq4xY1d0cpW9FY+yO4yzdC4x04hWqui81g Mpiw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=fMwpJ181; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59284-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59284-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWdp6JEeVIUZJs1HVCNZv4iN9ECgId49/lpvtTb+MO3IuWjyAsI5Er46iEUmEXKAbuxaw+gg19QAnj/lxaEVErZOohzkQ== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id m15-20020a056402430f00b0055fefcc4bb9si802713edc.404.2024.02.09.03.22.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:22:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59284-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=fMwpJ181; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59284-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59284-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id EE6B41F29C11 for ; Fri, 9 Feb 2024 11:22:16 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E1ED43F9CC; Fri, 9 Feb 2024 11:19:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fMwpJ181" Received: from mail-lj1-f201.google.com (mail-lj1-f201.google.com [209.85.208.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECF2D37716 for ; Fri, 9 Feb 2024 11:19:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477549; cv=none; b=NTBcBpn6pVxFaduR+wnmdK7lnLSCdP4rPhM65c8/ghkU+iPWVLWWS3P9dQlvKHXHEMwW8UxVKXEDHDwitGOhzqBvwAaYDaxkJfc6ZyV4JZN58A9g1ZniO7WUByiOGUbPPtDyoHfES1i8lHSQ2kAjw5JyrIgRyYaxCJRjI5VJnx8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477549; c=relaxed/simple; bh=jpdPd0bnKJx0v5IohdnvKzMyKCUyMI+4XjIMSwBUtJM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=aI7W4NzzYEyvtRfCtPV4owRnZ5FL2L3youSyvA6nbuCZmheiU8DZ9UQTbCQXrlmR08gLZlTIYlug9L/gK4ZpLUoTCHUZAw4dNx2HxOWP1A20SHB67aHBfPEvFPc3zrQrc9TBBIV4eFRftb/HXzKUqfCFK0k0/Ub+FzIP+NWaaEU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fMwpJ181; arc=none smtp.client-ip=209.85.208.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-lj1-f201.google.com with SMTP id 38308e7fff4ca-2d0c1ef2966so6637041fa.1 for ; Fri, 09 Feb 2024 03:19:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477546; x=1708082346; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=dH78NmaaVu9DkNui20oQ6e4x0KTKrZZbiJBCrE6Owok=; b=fMwpJ181JsBSwEf+xWaG3/SYXBV5CQTgm1fer7YnRjhCUr5NquV/xRfFcboy8INDkb Wnx1ERJ9xVZhflkG7NnCDayOEv8HGbkC52S2tl/rqNP3VIQbVRoMIuGV9yFRKBa2lsyR 9Rj2kUB/1jwG/MMtrUpoHc4voNBRpwQuWhMybDKLG8FtpPnQz3Ic3DTBjc1WVsJKqd/u nnAaqg1jv9r1wV/VOkJFE83Q/Lm0GLUfodwwIoGzCj9/tqJEfTVrUmeps2YgaBQI3mYS YJ7nrUsXUUcT8Epn9pBekTXpz1vkD+hO0YxeHftcIMFgHQSsC6wSIhLCIeTx2aFQzvmT EwUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477546; x=1708082346; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=dH78NmaaVu9DkNui20oQ6e4x0KTKrZZbiJBCrE6Owok=; b=s5HVnFhOWYUFOiTnRk25+X/X7UemDyiTHR4LUpf7dkSz3fYSlwRaoXA6ivzSLzJqwn K8+YaRCGvA0g3AjGsmyIo1/TqExVfPN6Lwn5NCAh2fQjj9MnSXWuiShDb4F1Z6FZ85Hl liofEkaJ6PI7YvwzOseLHCf8+xVLMBj3UCBD92618MJpsqiaytWOg6q2aKUDXkvPMAgF 0IH2uSjXzcmL8LrI5ubOCwiJz8/CxLYLO4F3cTm5ae3d5FX89sWmj1l7GiRoMVKiiUTf IBY+AdQkaQvVE6xXFnm/oUtJNPA5INhfJKnmgeMOqoMpfdD0e3PZgy4DCyxwe5UaVaSW QY6w== X-Forwarded-Encrypted: i=1; AJvYcCVJ8D+lRq2+BGD81c78ZGLLV0VMoTGNc4E3DKKjBsbLvwcFt1tU5jSbB0wsBmxtcPHNcS9PWWW2MwqDG4XNQgh4NeutrhB42x72vj99 X-Gm-Message-State: AOJu0Yyci8MfWQEi9tErQfVvl5f2sFN57BBO/+4uD94B7x4ccfWVwuba /2jKIc7bbt/ng0IhNJTmSwzOQc53blIoJkXnvjtRwLPmBRtc/eDMw8VYZHnlIhxrxw84M4+wmaQ 5uMRcUtGldtYdyg== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:651c:3c5:b0:2d0:d4d5:ae1c with SMTP id f5-20020a05651c03c500b002d0d4d5ae1cmr1228ljp.3.1707477545846; Fri, 09 Feb 2024 03:19:05 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:19 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5091; i=aliceryhl@google.com; h=from:subject:message-id; bh=4MEaahIDL8tWEqa8QqxP69ykw7VMt4xM9gXmsdnnpis=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoTvYPgkAnbZVxHmgiO+gQPznHds8k46wwuJ MredE562XyJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEwAKCRAEWL7uWMY5 RtJQD/sEDIZSqHxDN3nJargoXJ16TZZD2XdbWOh/p5vtwMsyAeGLE9OeZDO+l4qmX/vzv1c2Shm JwyjAWkpt2FRHvpmP3XXi/3JIefGh98lCSC345lEzOWIMkk1gOa/PdxzPT+vU/f3VahQTmCaKHv oBPiBtlh6qYQiM+gUE0KzRgWPfNphRjYc5ZX7EFKL+3Z9Pkpxsc3a+BDxhhF5rsfaaFyQMQ56zS Nr887zw1Q5B/A9NOShHBQYe9TwazetkTKpQGBru+2TiYEqqKdohhWoTTqMF5Cb3YCUldHySQTNv FIEYF7Ix/wa1GnwChc9xfCiojLbJY1beQw5wRmDJ9Xj5pNZDDni6XlQ6evAxSaOMMraDEbNiHs5 VnAYKCgEA9BAMYAL7vW9yq5Zjxzn2pzE6NnS1Th+mbb8PTQ8L9v1sPknUdr60rU1M7B2zDZaIkA jw84LQ+PxUeZJk5ilgtzk6MO5Cb40lMYJ7S9efrYIXaZb6OBfvRtWWaYizRsCpphAX2Z3p3P/R6 9mhNHhSHJkVWE3Bo86kKyKz8lp1d48r2OepUJsyxAL0rz5AcOsQnp4T7+1otubS9PQ/PJCJdwrW MNAokD2n0VSroP021QoRGx6IJvRTAS10mN+pDIDaNX5N4+F76IotOXUe8V8Rat52C6n+94RpgRT pb5OJWjKzH4EhkA== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-6-a37886783025@google.com> Subject: [PATCH v5 6/9] rust: file: add `FileDescriptorReservation` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420217010459053 X-GMAIL-MSGID: 1790420217010459053 From: Wedson Almeida Filho Allow for the creation of a file descriptor in two steps: first, we reserve a slot for it, then we commit or drop the reservation. The first step may fail (e.g., the current process ran out of available slots), but commit and drop never fail (and are mutually exclusive). This is needed by Rust Binder when fds are sent from one process to another. It has to be a two-step process to properly handle the case where multiple fds are sent: The operation must fail or succeed atomically, which we achieve by first reserving the fds we need, and only installing the files once we have reserved enough fds to send the files. Fd reservations assume that the value of `current` does not change between the call to get_unused_fd_flags and the call to fd_install (or put_unused_fd). By not implementing the Send trait, this abstraction ensures that the `FileDescriptorReservation` cannot be moved into a different process. Signed-off-by: Wedson Almeida Filho Co-developed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross --- rust/kernel/file.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs index 3a64c5022941..fb903b7f23fe 100644 --- a/rust/kernel/file.rs +++ b/rust/kernel/file.rs @@ -9,7 +9,7 @@ bindings, cred::Credential, error::{code::*, Error, Result}, - types::{ARef, AlwaysRefCounted, Opaque}, + types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; use core::ptr; @@ -248,6 +248,76 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } +/// A file descriptor reservation. +/// +/// This allows the creation of a file descriptor in two steps: first, we reserve a slot for it, +/// then we commit or drop the reservation. The first step may fail (e.g., the current process ran +/// out of available slots), but commit and drop never fail (and are mutually exclusive). +/// +/// Dropping the reservation happens in the destructor of this type. +/// +/// # Invariants +/// +/// The fd stored in this struct must correspond to a reserved file descriptor of the current task. +pub struct FileDescriptorReservation { + fd: u32, + /// Prevent values of this type from being moved to a different task. + /// + /// The `fd_install` and `put_unused_fd` functions assume that the value of `current` is + /// unchanged since the call to `get_unused_fd_flags`. By adding this marker to this type, we + /// prevent it from being moved across task boundaries, which ensures that `current` does not + /// change while this value exists. + _not_send: NotThreadSafe, +} + +impl FileDescriptorReservation { + /// Creates a new file descriptor reservation. + pub fn get_unused_fd_flags(flags: u32) -> Result { + // SAFETY: FFI call, there are no safety requirements on `flags`. + let fd: i32 = unsafe { bindings::get_unused_fd_flags(flags) }; + if fd < 0 { + return Err(Error::from_errno(fd)); + } + Ok(Self { + fd: fd as u32, + _not_send: NotThreadSafe, + }) + } + + /// Returns the file descriptor number that was reserved. + pub fn reserved_fd(&self) -> u32 { + self.fd + } + + /// Commits the reservation. + /// + /// The previously reserved file descriptor is bound to `file`. This method consumes the + /// [`FileDescriptorReservation`], so it will not be usable after this call. + pub fn fd_install(self, file: ARef) { + // SAFETY: `self.fd` was previously returned by `get_unused_fd_flags`. We have not yet used + // the fd, so it is still valid, and `current` still refers to the same task, as this type + // cannot be moved across task boundaries. + // + // Furthermore, the file pointer is guaranteed to own a refcount by its type invariants, + // and we take ownership of that refcount by not running the destructor below. + unsafe { bindings::fd_install(self.fd, file.as_ptr()) }; + + // `fd_install` consumes both the file descriptor and the file reference, so we cannot run + // the destructors. + core::mem::forget(self); + core::mem::forget(file); + } +} + +impl Drop for FileDescriptorReservation { + fn drop(&mut self) { + // SAFETY: By the type invariants of this type, `self.fd` was previously returned by + // `get_unused_fd_flags`. We have not yet used the fd, so it is still valid, and `current` + // still refers to the same task, as this type cannot be moved across task boundaries. + unsafe { bindings::put_unused_fd(self.fd) }; + } +} + /// Represents the `EBADF` error code. /// /// Used for methods that can only fail with `EBADF`. From patchwork Fri Feb 9 11:18:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198821 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780758dyd; Fri, 9 Feb 2024 03:22:42 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUAgYode9lS50E/+EWHTlMr51r2Q//YeRnSg3MBctIrbrueA+M2E+c5vQNTbQ1e5VBYzEESShgLHCBy9GFONImIXG0ePA== X-Google-Smtp-Source: AGHT+IGROmpBnSIdHsoL4zfi0Mpxxycj4C7Bisk3YkVAWG7niea+pxlVaVpgsNdcgcJWUWhHuxj9 X-Received: by 2002:a05:6a21:151a:b0:19e:5fc7:b3e8 with SMTP id nq26-20020a056a21151a00b0019e5fc7b3e8mr1618812pzb.61.1707477762567; Fri, 09 Feb 2024 03:22:42 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477762; cv=pass; d=google.com; s=arc-20160816; b=AFW2NeLNOZbmNvc0OnfUsJUn8VOomRhXBZ83iY2uzurG0409a9XzhgnqYYLrc7m8Zh PjsmL2A9E3TUDcUy4O7YXJqaODaieyWBNLFawFV2IPF3frgGouNc4ynfPhYL3psxpB1+ ap3N5xfWTXOm1Ys2kLxnTOm10W/XVr3WWUZFNM2WuN3WlOkOJHROMiNEOYJ9IQ0U6cUc AOCT8q1CnLsZIrKUSB9TLNwAcIdJbgQflAhcqz79ggFKc4mqomGF7yi7VH4EvmBqhG7E +PtRLKXfUx0XTcGpF/v/U4o+ClYXqeTjzAnfC2zC2wgZHZtNRGypzbV3jmlYwUJN4Gj8 bL3w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=VdMtlvXSdpyuBlQLT4isky8KfbOQu099bwECdJmsAI8=; fh=8rZ52hjDANaol5zq3bRi17SzDufNby62uPG9AfCItUM=; b=RPY0QrstKPbTjRLcmHo+ms1cfjywazH9Jzx3V5Ni32dIxjnWRjk3C4ZlVSl2izFg/4 lnHplN8Kp2RU+JBK9PKu3ZUWN2Xz9EzqwWkTDdofXP7O+3cqY1aWk4UMOXk0agnaoPLN BqhIjTNHI7F4BegsZROp59WUJg9dR++4Ua0jMfFDH0bXajCjjKcqSpG7JovxrHltKezr Af3g2E5nTEdEqPDHKfORjVXwvpEAqvtUvOBPpxxPeYuGJWRFle+5MCP4gakJglbNGbTB tLCAVG1lHovTFM1z7obmV8PFvlNFANX+3RuaiZB8qeUIR7sxXVndAPuaELyE27P9u80+ tCGQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="U1/hEMt+"; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59285-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59285-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCUsaY+TUuCej8gYGMclMEXT2uJK1rcrotsEw9B4vlWELPUwtZ6or1SWLW7EIL1XjWmzD9ddJj6ZumyPY5AoTid3kf2/7w== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id y15-20020aa7854f000000b006de169e5800si142589pfn.373.2024.02.09.03.22.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:22:42 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59285-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="U1/hEMt+"; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59285-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59285-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 533B32812A3 for ; Fri, 9 Feb 2024 11:22:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8F0DE3C689; Fri, 9 Feb 2024 11:19:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="U1/hEMt+" Received: from mail-lf1-f73.google.com (mail-lf1-f73.google.com [209.85.167.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E35A83C47A for ; Fri, 9 Feb 2024 11:19:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477552; cv=none; b=kolS5y+lwVTb8uAD3imvKwqOVDQ8nAf8QW5UAJJwrXO8SWVzhz7sxjyS9uQNpSGjJZSE2zo5CkF56uqJ2Nf0A7wf2cMeas0fW9KDDsnTKjBp0SoBHybNqwiX/TIn3NCPR6S1IfjzagLWkCATqPjqlrMbPL7TM33SUGEWA9OyCWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477552; c=relaxed/simple; bh=E1buk0zzZWt+ClaaZ+b63yUoP42+YT0Qbdk1d5cyqEs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=T//yZYfavh+ICl0xRXYHqWz3K+h+pSFVcF5qUvAK1G2gd/yMsQOpIjLBHdOcsElLEMiTueLallDOGfBAmEmUcPxfk9NbVmJnvk9TOOl+HRnJDPrPe8v3NiqVcIHd//Zp3wKD99Od4UZTA3lVlCAsXB77fz71Dn5TVTGHXK11VhM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=U1/hEMt+; arc=none smtp.client-ip=209.85.167.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-lf1-f73.google.com with SMTP id 2adb3069b0e04-5113b77ff80so643117e87.2 for ; Fri, 09 Feb 2024 03:19:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477549; x=1708082349; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=VdMtlvXSdpyuBlQLT4isky8KfbOQu099bwECdJmsAI8=; b=U1/hEMt+fyH24R0QU6b92lYfSv5xUPhKdUi+t65OwFvAY6xkoeHQ5n2+MpqmqEC45/ ieDXnSqjH4x4iscsAQuabLs9seVQWmebMUw8NCiuoYe2sqJSZphd3qUSM1JXoytbuOBV ecsP+zbi6Qce8vL8YVkZmC+mnEuqwchmE7zW8g5bWFhW3HPRs0UYys1hzRFUsGPXAmr8 YlwIMcImeSyD7UcXxwo6MHrfeNa2rA03V3WUwwJHsG8WMZwBV5g8/GdB85xzqmWKgSme 7aniK5cmsa8vMNfdAUQe6HlRa80bM4HKUlXCLDRaJGuNBCcVKOUrXwfwNnh7vw0MhjPr zRBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477549; x=1708082349; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VdMtlvXSdpyuBlQLT4isky8KfbOQu099bwECdJmsAI8=; b=aU3g8v+hzUem1fIVvNPqN8NbvuZFA1HTKHco8DAIekVsKBs3nL32SM7TovHernaNjH J012EuSYk7OoevSNS/rEtniHbZEnmsbyjxucbOKAdLt59C1KlFny/as/YFn0jDJqciuX 41gOobdxbMN4QMEvmTWl/ildnghMz3ghz6z8Wn7/LiltDLlxFIBxAeISk3hTEda/UZO+ Uy4pN9sEarJbUTKXHB2iEzNDOp35tw7oprItXGZnZAtPFQeUtEDFoTU6bHgLCa9F4wLb XJwuXQYsRRardA+GRdHXiLfOyT/grdTzHgp7bWI87rPe+JLmimPZZpW5llPVCPVYbCIA FfgQ== X-Forwarded-Encrypted: i=1; AJvYcCXKKT7P16djg32EPuh5kY/Ew7SNu4n1niOENUxzsgr50dMarg+Jt5IuaBiCIjopJE7eee65N+zc+SCK08MIK0z0Zi9IR1u51RYsdpP7 X-Gm-Message-State: AOJu0YxyDOLwebZrIi3bn4JqPt3zaUYG74ZXiAs8gWj84S7bVIqsI4BF 1WYjRNe7cDokjlVQO64jj+dKt/gHeIrFl9K+bk9GFxnmI2j21gmMnMaYQx8m4cKhqUgO5ptdpAk MBrYboeupO+vzaQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6512:36c1:b0:511:7c00:fb36 with SMTP id e1-20020a05651236c100b005117c00fb36mr111lfs.10.1707477548849; Fri, 09 Feb 2024 03:19:08 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:20 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7824; i=aliceryhl@google.com; h=from:subject:message-id; bh=E1buk0zzZWt+ClaaZ+b63yUoP42+YT0Qbdk1d5cyqEs=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoTxQ7fOeQVqeJHhvMo3R4TWUWv4Zre9VHmv 1n6+dozzJiJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEwAKCRAEWL7uWMY5 RoTID/9DrBtrSeP6a7LrW8zdrFLqeLQwwj3lFqnnNrTM5QW+TdfhVwnLMnRTGE0+zgC05ke+Gja CZmAOET4+/vTYR24qksd1KZsRj8jCgg5xlc+Mq1/t2A/x/CUP4+oArC9rX4YZK3777fVV1m1Ac0 bLuMffDV9reg3o85hMLAjyxk3PBDGqN+OWHnjwdNYy0gsWHUMN170+74qr5xgJUfIcIJVTItP0M QG1JsSs6EbrwR+OBo/TchCNF6VLu5O0ZjC0yKqDQZdJfbs0aeqHGGi4tiyhxJX3FR2QYcH+MUGq vbGN4vPIy6dgVwHaClly3eBpi4vuCZiYXKEDbT9baigwQbZC/ZA1dwVMTVM5i2mikL1wg9HuSf6 xo+/zXyqysdcRlK7WmTGOQQm9xL6VLcUMtw7cql35bKXsA/UoTOFVoHUum2oYiLy0KnXwcn+Vhh q9Xc99KnXgEqroKeTSbFbO0f27sGvLDgIVVKrputudqRtzI4RwOeY3z9BhcpPP+G0ubccGV8FO6 nAcUENW/W3vAANq8eWdUGyMY7axO8w3ayfurOy2qNbMDmXUzIfjiq5G8xZ/K8IkzMkWbGjrlrWA xwzn1rpRENlTrg+ej6ywS506rraGmNyYseWQhal7cvOX72nz2GHsEu68IQqnlM5Lm6gl7lVeyFT D5PnyAJZebOT5YA== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-7-a37886783025@google.com> Subject: [PATCH v5 7/9] rust: file: add `Kuid` wrapper From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420201955369093 X-GMAIL-MSGID: 1790420201955369093 Adds a wrapper around `kuid_t` called `Kuid`. This allows us to define various operations on kuids such as equality and current_euid. It also lets us provide conversions from kuid into userspace values. Rust Binder needs these operations because it needs to compare kuids for equality, and it needs to tell userspace about the pid and uid of incoming transactions. To read kuids from a `struct task_struct`, you must currently use various #defines that perform the appropriate field access under an RCU read lock. Currently, we do not have a Rust wrapper for rcu_read_lock, which means that for this patch, there are two ways forward: 1. Inline the methods into Rust code, and use __rcu_read_lock directly rather than the rcu_read_lock wrapper. This gives up lockdep for these usages of RCU. 2. Wrap the various #defines in helpers and call the helpers from Rust. This patch uses the second option. One possible disadvantage of the second option is the possible introduction of speculation gadgets, but as discussed in [1], the risk appears to be acceptable. Of course, once a wrapper for rcu_read_lock is available, it is preferable to use that over either of the two above approaches. Link: https://lore.kernel.org/all/202312080947.674CD2DC7@keescook/ [1] Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 45 ++++++++++++++++++++++++++++ rust/kernel/cred.rs | 5 ++-- rust/kernel/task.rs | 66 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 2 deletions(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 5ca497d786f0..4194b057ef6b 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers.c b/rust/helpers.c index fd633d9db79a..58e3a9dff349 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -142,6 +142,51 @@ void rust_helper_put_task_struct(struct task_struct *t) } EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); +kuid_t rust_helper_task_uid(struct task_struct *task) +{ + return task_uid(task); +} +EXPORT_SYMBOL_GPL(rust_helper_task_uid); + +kuid_t rust_helper_task_euid(struct task_struct *task) +{ + return task_euid(task); +} +EXPORT_SYMBOL_GPL(rust_helper_task_euid); + +#ifndef CONFIG_USER_NS +uid_t rust_helper_from_kuid(struct user_namespace *to, kuid_t uid) +{ + return from_kuid(to, uid); +} +EXPORT_SYMBOL_GPL(rust_helper_from_kuid); +#endif /* CONFIG_USER_NS */ + +bool rust_helper_uid_eq(kuid_t left, kuid_t right) +{ + return uid_eq(left, right); +} +EXPORT_SYMBOL_GPL(rust_helper_uid_eq); + +kuid_t rust_helper_current_euid(void) +{ + return current_euid(); +} +EXPORT_SYMBOL_GPL(rust_helper_current_euid); + +struct user_namespace *rust_helper_current_user_ns(void) +{ + return current_user_ns(); +} +EXPORT_SYMBOL_GPL(rust_helper_current_user_ns); + +pid_t rust_helper_task_tgid_nr_ns(struct task_struct *tsk, + struct pid_namespace *ns) +{ + return task_tgid_nr_ns(tsk, ns); +} +EXPORT_SYMBOL_GPL(rust_helper_task_tgid_nr_ns); + struct kunit *rust_helper_kunit_get_current_test(void) { return kunit_get_current_test(); diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs index fdd899040098..961e94b6a657 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -8,6 +8,7 @@ use crate::{ bindings, + task::Kuid, types::{AlwaysRefCounted, Opaque}, }; @@ -59,11 +60,11 @@ pub fn get_secid(&self) -> u32 { } /// Returns the effective UID of the given credential. - pub fn euid(&self) -> bindings::kuid_t { + pub fn euid(&self) -> Kuid { // SAFETY: By the type invariant, we know that `self.0` is valid. Furthermore, the `euid` // field of a credential is never changed after initialization, so there is no potential // for data races. - unsafe { (*self.0.get()).euid } + Kuid::from_raw(unsafe { (*self.0.get()).euid }) } } diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index b579367fb923..f46ea3ba9e8e 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -9,6 +9,7 @@ types::{NotThreadSafe, Opaque}, }; use core::{ + cmp::{Eq, PartialEq}, ffi::{c_int, c_long, c_uint}, ops::Deref, ptr, @@ -96,6 +97,12 @@ unsafe impl Sync for Task {} /// The type of process identifiers (PIDs). type Pid = bindings::pid_t; +/// The type of user identifiers (UIDs). +#[derive(Copy, Clone)] +pub struct Kuid { + kuid: bindings::kuid_t, +} + impl Task { /// Returns a raw pointer to the current task. /// @@ -157,12 +164,31 @@ pub fn pid(&self) -> Pid { unsafe { *ptr::addr_of!((*self.0.get()).pid) } } + /// Returns the UID of the given task. + pub fn uid(&self) -> Kuid { + // SAFETY: By the type invariant, we know that `self.0` is valid. + Kuid::from_raw(unsafe { bindings::task_uid(self.0.get()) }) + } + + /// Returns the effective UID of the given task. + pub fn euid(&self) -> Kuid { + // SAFETY: By the type invariant, we know that `self.0` is valid. + Kuid::from_raw(unsafe { bindings::task_euid(self.0.get()) }) + } + /// Determines whether the given task has pending signals. pub fn signal_pending(&self) -> bool { // SAFETY: By the type invariant, we know that `self.0` is valid. unsafe { bindings::signal_pending(self.0.get()) != 0 } } + /// Returns the given task's pid in the current pid namespace. + pub fn pid_in_current_ns(&self) -> Pid { + // SAFETY: We know that `self.0.get()` is valid by the type invariant, and passing a null + // pointer as the namespace is correct for using the current namespace. + unsafe { bindings::task_tgid_nr_ns(self.0.get(), ptr::null_mut()) } + } + /// Wakes up the task. pub fn wake_up(&self) { // SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid. @@ -172,6 +198,46 @@ pub fn wake_up(&self) { } } +impl Kuid { + /// Get the current euid. + #[inline] + pub fn current_euid() -> Kuid { + // SAFETY: Just an FFI call. + Self::from_raw(unsafe { bindings::current_euid() }) + } + + /// Create a `Kuid` given the raw C type. + #[inline] + pub fn from_raw(kuid: bindings::kuid_t) -> Self { + Self { kuid } + } + + /// Turn this kuid into the raw C type. + #[inline] + pub fn into_raw(self) -> bindings::kuid_t { + self.kuid + } + + /// Converts this kernel UID into a userspace UID. + /// + /// Uses the namespace of the current task. + #[inline] + pub fn into_uid_in_current_ns(self) -> bindings::uid_t { + // SAFETY: Just an FFI call. + unsafe { bindings::from_kuid(bindings::current_user_ns(), self.kuid) } + } +} + +impl PartialEq for Kuid { + #[inline] + fn eq(&self, other: &Kuid) -> bool { + // SAFETY: Just an FFI call. + unsafe { bindings::uid_eq(self.kuid, other.kuid) } + } +} + +impl Eq for Kuid {} + // SAFETY: The type invariants guarantee that `Task` is always ref-counted. unsafe impl crate::types::AlwaysRefCounted for Task { fn inc_ref(&self) { From patchwork Fri Feb 9 11:18:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198824 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780934dyd; Fri, 9 Feb 2024 03:23:05 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCVWJxu+6CxY9ip7iK0GRXQFKrxfw1u093kBeNAp2ZMwKTU2+yg7+MZFVhxImUpbSPDSZcaxKuFLG6o1U7fTY8/H/AbjmQ== X-Google-Smtp-Source: AGHT+IGUrkk+Djauwo+GoIwAMDHb4Tbbi+thJlvbyGH6cQT4mg4ivYyN6eRAxRtVlDVrNPiDWA/s X-Received: by 2002:a92:db06:0:b0:363:c1f9:16f4 with SMTP id b6-20020a92db06000000b00363c1f916f4mr1485484iln.28.1707477785490; Fri, 09 Feb 2024 03:23:05 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477785; cv=pass; d=google.com; s=arc-20160816; b=yMYKXS7ic1pA9EeGs9kJm9Aib1R2ezh3QLG7K+AHiwQP6qkths9sD7Ip/gYYAtg+7T iCiLSimXI++EkEzQdsZF1JSp5IchH8sZ1a7jzgFpRGyHKldiXqth27Ir6Drbgby6V40E SH11nXEjUlwFEYub9wRQe++u+GhH+5J/kmvpMK/jBPwU+emJdfmHb9lD2G+uS7Mm8JpF yEHuL1I8w/2OPeouLj+JLYq2H2Ip8YYGDylZIpm3d8smyTnJ6WRm/BHugTwWj8ykJNg+ bbw7rImd2XZatdWOnsYfv1i57r+8oKSXYCeazsyNiG3hrngprvLmP8c7mQiFl8D1R75n Jf0g== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=5J2ATY8bukI5yS7lbmM4YWFCKuUjtHfxnPFLlFPpxZs=; fh=LFQofahG6/FVk1f646K432N6+U8YW97fhI2VUOqf1s8=; b=SAPZ5gcnhxhRuiOgduW1T2DtbXZGfGC/Lpa+3aNrch8d8dkRTTPcSo7i6KbrYSKkdV G37ej2NiWqM9nF5u4JhnihqoIuV5akL7y52t7WtCgaQx++2lq0HFGzMf8b8kJaxu3cSB eLsr6w0bJLh21Y4t7Mq2nm63ZLp6KNbtQ2YNpbK28B4/UZCffy1H7MUeKeeHzSz1DKRx q5MD+LItLFgxPoIiKfnwdYGFHGQ+22LqLpXbSmAkarNYZvQebh3QofK+HnvCjBrUllzn SzANf1/7LD3mrmJmgA9yU7hVwucUqQBdw7eZ7LO85fB4mPSTfZ4XrO5xSUW9I6GO8+Xh VOpw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="zLu/xjEv"; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59286-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59286-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWNDPHkkUpvxjoJmn4TeGujIJVRNEFKNAPJb345ZQZ/nzMQEh8+w2WEEVdpm7WTjAiKTaiuF37/4YOj4JdfS745JFwf9Q== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id k7-20020a633d07000000b005dc496a3597si1578934pga.417.2024.02.09.03.23.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:23:05 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59286-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="zLu/xjEv"; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59286-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59286-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 3C0F32808EC for ; Fri, 9 Feb 2024 11:23:05 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C7B0A3F9F5; Fri, 9 Feb 2024 11:19:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="zLu/xjEv" Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C3283D552 for ; Fri, 9 Feb 2024 11:19:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477555; cv=none; b=k7pOCxIfp614qOB4sR6xXw6xjZ//7cr/qdLnxY94Fm8wM8PTqdkBjf7qmvo0/wvtTVO0jmsJ2mfbK7d8LuShS8Znyw6JanYOEsejU0VR04iDgt42uoOFd06bGEmIU+OfLbpJM6N4jkNUPCphbamCctg0QtBqxJoBrC8ORRdALRY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477555; c=relaxed/simple; bh=QXbqLmgDd7EsSTUpIcWNfbiRX0vIgR+IoYx0H4gKGSw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Q3cKqYoJHPboRmsbxRc6jj6k5Z9LNeIWEK/6qPUAjd6gL/qvw/I01I7EXA2qKCw7A0CT1Vc/CbPZmmfOciFoXrkrIM8BeiJS9rk5ixw/58WVWg19DEK+j+qu66kKiN6/TYe/TevWv8oKRd0BHLSe/ZioUWLt5sOL6/KyqT+QreA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=zLu/xjEv; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dc743cc50a6so1141395276.2 for ; Fri, 09 Feb 2024 03:19:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477552; x=1708082352; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5J2ATY8bukI5yS7lbmM4YWFCKuUjtHfxnPFLlFPpxZs=; b=zLu/xjEvSaS58k37KZj0wf9TKNo/Qw3aXXO7IrxVSfQ/Ef5InVS5bZapJMj2SWSgL/ Pqb0pNZtg0Yz0f5K/jIQgLaMZxyhEBtgdlWV/qiYligekfbZRx9S1rmKr/t28ip89CIw SH6W64SfW8mTcCdPVsY58UwMPiXQ+dFbqAfiiw2KDoB4estadgOdLqfXybMaPCl287/A 3d5OlIKLYcw4qyUvMbybwJkIkrcB+ep0VsvMwLeU+gwmsqggq3pl+4B8k6RbwfDamRRz dc4va2D0Uo7BEeDcdwaUoxp5A38gMHjhyzZCi2ZoDo7XOVT0giDpea8XbTRhn9vZkg7T B3Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477552; x=1708082352; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5J2ATY8bukI5yS7lbmM4YWFCKuUjtHfxnPFLlFPpxZs=; b=Z7jBco3brjM9NJnz32clgINlwggKhIXMDCo2tQ8F8TIAdHE4TNFhZZqivmVGcYfESg FQpLLpbUcbGdm586tldxGuZWcMfcxRXHJWYtmKls0aVS6MUpgY8Kz6+2qSIzkxHIhfV+ ocTgUSByfOL5/JKc0moWcbi6NrBu5tusuL10NAe3BHEHruGh+Ekna7hCMnWk8J/tYpih vCYrCzIISurauMCobaPTmUKazdqYpPRlJ+aOoXO3rLbltqYbw1N29z3uKGEugJwzyb68 qFKtMsxOQJUdd+2aSzJSERdVC+UZDvEIGbUWhCw0xqacr/BgY/EId/mu+tq3Pp4vUbuo ms1A== X-Forwarded-Encrypted: i=1; AJvYcCUOoCCKZ+KFAxJ7h6XLV+lupJ7h8HUlIE2T+VxUr9Qn0GeCqOZjC1WwIowWvjwrgYg3xsEkbdbDlwApxrN8HUfuTItNwuHGNmXEJTzj X-Gm-Message-State: AOJu0YyJYs40AB7xcUH2D5aFR+OJ8nJ+E+Ed4iDwOFcJnK79Nm4W6UFw /aLnd0RhF10din1oy1LIijMkYiIXQWPWw2jRcXLW0LthV+UOKPAs/s7j400edA6S4vgMqloEqPp 5CQVPnyzepEYtmg== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:70c:b0:dc2:5273:53f9 with SMTP id k12-20020a056902070c00b00dc2527353f9mr26727ybt.1.1707477552214; Fri, 09 Feb 2024 03:19:12 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:21 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=14200; i=aliceryhl@google.com; h=from:subject:message-id; bh=QXbqLmgDd7EsSTUpIcWNfbiRX0vIgR+IoYx0H4gKGSw=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoUJDoDGV2XYijN3ZAjluEEyVP3dFd7yKN8i RJH1bhEabmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKFAAKCRAEWL7uWMY5 RtgtEACOlFkxgEuF95gttJJXUVkL+y3AqSMiNe9XgvJTy2d8sYLEqQWbvnsyojucCOUkYtUp3e1 pSZiym3YT582eDSEndRo9m6W/FaLCsP6Quqgz3kQ48AnFT7QNNgvBaTX60nP9y5TbW7VuwJutwX vd4BSQAUVp1120h40XUWBZwr7MnT9jtkJ10dDlQwdYA1z2F87I8W5AZsH5ici95CuJe8zZSVWIL La/r9cAb0UbiFKHaeGkLaVcy4zzRx+GR6MpOpvESWRdEnOvl5f7wERoaeM+L0AEfp2Z3gdxi5PT 5vORnezMcXPeQGWqJzh25fOOb9vktQBepBTojH77YyLY1ciLxPPd7u4Hpga40UHQo/HwzoWoSti 3xtxgAftQ6iWFbW5F+UlqaL+NoDXXRAeDNMcAsaO/n/dYUjPqVR1u5Qf+/C34oDc7B6ifSOKDF6 LC81v/mXbwENI7IpGoMf8nOLXSFsmT1dSdQFjB8w5MuTDpDsIvsIgpBnZ53pn+MrncrOmriRN4n /5zHe34CyN0hWniSfY/0oah5dPZxNK8x1DOsCsJwUDFMZVozXclM4t+B9qMoH6U/+kIkIi7qlHu ibsJDQhxbSJdL10myE/kE8Jw5y+/2EBtTWpmuklECZILfj0mN040EvLjGi7l06PahGRl8CoZMUw E00EPBQK0lO8J0A== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-8-a37886783025@google.com> Subject: [PATCH v5 8/9] rust: file: add `DeferredFdCloser` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420226268807288 X-GMAIL-MSGID: 1790420226268807288 To close an fd from kernel space, we could call `ksys_close`. However, if we do this to an fd that is held using `fdget`, then we may trigger a use-after-free. Introduce a helper that can be used to close an fd even if the fd is currently held with `fdget`. This is done by grabbing an extra refcount to the file and dropping it in a task work once we return to userspace. This is necessary for Rust Binder because otherwise the user might try to have Binder close its fd for /dev/binder, which would cause problems as this happens inside an ioctl on /dev/binder, and ioctls hold the fd using `fdget`. Additional motivation can be found in commit 80cd795630d6 ("binder: fix use-after-free due to ksys_close() during fdget()") and in the comments on `binder_do_fd_close`. If there is some way to detect whether an fd is currently held with `fdget`, then this could be optimized to skip the allocation and task work when this is not the case. Another possible optimization would be to combine several fds into a single task work, since this is used with fd arrays that might hold several fds. That said, it might not be necessary to optimize it, because Rust Binder has two ways to send fds: BINDER_TYPE_FD and BINDER_TYPE_FDA. With BINDER_TYPE_FD, it is userspace's responsibility to close the fd, so this mechanism is used only by BINDER_TYPE_FDA, but fd arrays are used rarely these days. Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross --- rust/bindings/bindings_helper.h | 2 + rust/helpers.c | 8 ++ rust/kernel/file.rs | 184 +++++++++++++++++++++++++++++++++++++++- rust/kernel/task.rs | 14 +++ 4 files changed, 207 insertions(+), 1 deletion(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 4194b057ef6b..f4d9d04333c0 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include /* `bindgen` gets confused at certain things. */ diff --git a/rust/helpers.c b/rust/helpers.c index 58e3a9dff349..d146bbf25aec 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,13 @@ void rust_helper_security_release_secctx(char *secdata, u32 seclen) EXPORT_SYMBOL_GPL(rust_helper_security_release_secctx); #endif +void rust_helper_init_task_work(struct callback_head *twork, + task_work_func_t func) +{ + init_task_work(twork, func); +} +EXPORT_SYMBOL_GPL(rust_helper_init_task_work); + /* * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can * use it in contexts where Rust expects a `usize` like slice (array) indices. diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs index fb903b7f23fe..8902f490ccc8 100644 --- a/rust/kernel/file.rs +++ b/rust/kernel/file.rs @@ -11,7 +11,8 @@ error::{code::*, Error, Result}, types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; -use core::ptr; +use alloc::boxed::Box; +use core::{alloc::AllocError, mem, ptr}; /// Flags associated with a [`File`]. pub mod flags { @@ -318,6 +319,187 @@ fn drop(&mut self) { } } +/// Helper used for closing file descriptors in a way that is safe even if the file is currently +/// held using `fdget`. +/// +/// Additional motivation can be found in commit 80cd795630d6 ("binder: fix use-after-free due to +/// ksys_close() during fdget()") and in the comments on `binder_do_fd_close`. +pub struct DeferredFdCloser { + inner: Box, +} + +/// SAFETY: This just holds an allocation with no real content, so there's no safety issue with +/// moving it across threads. +unsafe impl Send for DeferredFdCloser {} +unsafe impl Sync for DeferredFdCloser {} + +/// # Invariants +/// +/// If the `file` pointer is non-null, then it points at a `struct file` and owns a refcount to +/// that file. +#[repr(C)] +struct DeferredFdCloserInner { + twork: mem::MaybeUninit, + file: *mut bindings::file, +} + +impl DeferredFdCloser { + /// Create a new [`DeferredFdCloser`]. + pub fn new() -> Result { + Ok(Self { + // INVARIANT: The `file` pointer is null, so the type invariant does not apply. + inner: Box::try_new(DeferredFdCloserInner { + twork: mem::MaybeUninit::uninit(), + file: core::ptr::null_mut(), + })?, + }) + } + + /// Schedule a task work that closes the file descriptor when this task returns to userspace. + /// + /// Fails if this is called from a context where we cannot run work when returning to + /// userspace. (E.g., from a kthread.) + pub fn close_fd(self, fd: u32) -> Result<(), DeferredFdCloseError> { + use bindings::task_work_notify_mode_TWA_RESUME as TWA_RESUME; + + // In this method, we schedule the task work before closing the file. This is because + // scheduling a task work is fallible, and we need to know whether it will fail before we + // attempt to close the file. + + // Task works are not available on kthreads. + let current = crate::current!(); + if current.is_kthread() { + return Err(DeferredFdCloseError::TaskWorkUnavailable); + } + + // Transfer ownership of the box's allocation to a raw pointer. This disables the + // destructor, so we must manually convert it back to a Box to drop it. + // + // Until we convert it back to a `Box`, there are no aliasing requirements on this + // pointer. + let inner = Box::into_raw(self.inner); + + // The `callback_head` field is first in the struct, so this cast correctly gives us a + // pointer to the field. + let callback_head = inner.cast::(); + // SAFETY: This pointer offset operation does not go out-of-bounds. + let file_field = unsafe { core::ptr::addr_of_mut!((*inner).file) }; + + let current = current.as_raw(); + + // SAFETY: This function currently has exclusive access to the `DeferredFdCloserInner`, so + // it is okay for us to perform unsynchronized writes to its `callback_head` field. + unsafe { bindings::init_task_work(callback_head, Some(Self::do_close_fd)) }; + + // SAFETY: This inserts the `DeferredFdCloserInner` into the task workqueue for the current + // task. If this operation is successful, then this transfers exclusive ownership of the + // `callback_head` field to the C side until it calls `do_close_fd`, and we don't touch or + // invalidate the field during that time. + // + // When the C side calls `do_close_fd`, the safety requirements of that method are + // satisfied because when a task work is executed, the callback is given ownership of the + // pointer. + // + // The file pointer is currently null. If it is changed to be non-null before `do_close_fd` + // is called, then that change happens due to the write at the end of this function, and + // that write has a safety comment that explains why the refcount can be dropped when + // `do_close_fd` runs. + let res = unsafe { bindings::task_work_add(current, callback_head, TWA_RESUME) }; + + if res != 0 { + // SAFETY: Scheduling the task work failed, so we still have ownership of the box, so + // we may destroy it. + unsafe { drop(Box::from_raw(inner)) }; + + return Err(DeferredFdCloseError::TaskWorkUnavailable); + } + + // This removes the fd from the fd table in `current`. The file is not fully closed until + // `filp_close` is called. We are given ownership of one refcount to the file. + // + // SAFETY: This is safe no matter what `fd` is. If the `fd` is valid (that is, if the + // pointer is non-null), then we call `filp_close` on the returned pointer as required by + // `file_close_fd`. + let file = unsafe { bindings::file_close_fd(fd) }; + if file.is_null() { + // We don't clean up the task work since that might be expensive if the task work queue + // is long. Just let it execute and let it clean up for itself. + return Err(DeferredFdCloseError::BadFd); + } + + // Acquire a second refcount to the file. + // + // SAFETY: The `file` pointer points at a file with a non-zero refcount. + unsafe { bindings::get_file(file) }; + + // This method closes the fd, consuming one of our two refcounts. There could be active + // light refcounts created from that fd, so we must ensure that the file has a positive + // refcount for the duration of those active light refcounts. We do that by holding on to + // the second refcount until the current task returns to userspace. + // + // SAFETY: The `file` pointer is valid. Passing `current->files` as the file table to close + // it in is correct, since we just got the `fd` from `file_close_fd` which also uses + // `current->files`. + // + // Note: fl_owner_t is currently a void pointer. + unsafe { bindings::filp_close(file, (*current).files as bindings::fl_owner_t) }; + + // We update the file pointer that the task work is supposed to fput. This transfers + // ownership of our last refcount. + // + // INVARIANT: This changes the `file` field of a `DeferredFdCloserInner` from null to + // non-null. This doesn't break the type invariant for `DeferredFdCloserInner` because we + // still own a refcount to the file, so we can pass ownership of that refcount to the + // `DeferredFdCloserInner`. + // + // When `do_close_fd` runs, it must be safe for it to `fput` the refcount. However, this is + // the case because all light refcounts that are associated with the fd we closed + // previously must be dropped when `do_close_fd`, since light refcounts must be dropped + // before returning to userspace. + // + // SAFETY: Task works are executed on the current thread right before we return to + // userspace, so this write is guaranteed to happen before `do_close_fd` is called, which + // means that a race is not possible here. + unsafe { *file_field = file }; + + Ok(()) + } + + /// # Safety + /// + /// The provided pointer must point at the `twork` field of a `DeferredFdCloserInner` stored in + /// a `Box`, and the caller must pass exclusive ownership of that `Box`. Furthermore, if the + /// file pointer is non-null, then it must be okay to release the refcount by calling `fput`. + unsafe extern "C" fn do_close_fd(inner: *mut bindings::callback_head) { + // SAFETY: The caller just passed us ownership of this box. + let inner = unsafe { Box::from_raw(inner.cast::()) }; + if !inner.file.is_null() { + // SAFETY: By the type invariants, we own a refcount to this file, and the caller + // guarantees that dropping the refcount now is okay. + unsafe { bindings::fput(inner.file) }; + } + // The allocation is freed when `inner` goes out of scope. + } +} + +/// Represents a failure to close an fd in a deferred manner. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum DeferredFdCloseError { + /// Closing the fd failed because we were unable to schedule a task work. + TaskWorkUnavailable, + /// Closing the fd failed because the fd does not exist. + BadFd, +} + +impl From for Error { + fn from(err: DeferredFdCloseError) -> Error { + match err { + DeferredFdCloseError::TaskWorkUnavailable => ESRCH, + DeferredFdCloseError::BadFd => EBADF, + } + } +} + /// Represents the `EBADF` error code. /// /// Used for methods that can only fail with `EBADF`. diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index f46ea3ba9e8e..6adcd8ffcfde 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -145,6 +145,12 @@ fn deref(&self) -> &Self::Target { } } + /// Returns a raw pointer to the task. + #[inline] + pub fn as_raw(&self) -> *mut bindings::task_struct { + self.0.get() + } + /// Returns the group leader of the given task. pub fn group_leader(&self) -> &Task { // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always @@ -189,6 +195,14 @@ pub fn pid_in_current_ns(&self) -> Pid { unsafe { bindings::task_tgid_nr_ns(self.0.get(), ptr::null_mut()) } } + /// Returns whether this task corresponds to a kernel thread. + pub fn is_kthread(&self) -> bool { + // SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid. There + // are no further requirements to read the task's flags. + let flags = unsafe { (*self.0.get()).flags }; + (flags & bindings::PF_KTHREAD) != 0 + } + /// Wakes up the task. pub fn wake_up(&self) { // SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid. From patchwork Fri Feb 9 11:18:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198825 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp781019dyd; Fri, 9 Feb 2024 03:23:17 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXZDftbLaBq2bwyLVtmPylFi/ZjggHdkZPSPMXgHeEYerVINh3nvlMI5hRNFKTb62bjwFBIi6/ANQwnL7bRqobHty9veA== X-Google-Smtp-Source: AGHT+IGuHjuwV2qnF+dFrvPDKoPZbP7KSjbiuP7SMvkn6glRC0T1/KLDDooQ/MuJnDdQQ1Sxcdh/ X-Received: by 2002:a17:90a:8a91:b0:296:69a:34c4 with SMTP id x17-20020a17090a8a9100b00296069a34c4mr1252553pjn.21.1707477797235; Fri, 09 Feb 2024 03:23:17 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477797; cv=pass; d=google.com; s=arc-20160816; b=VuivfIKuDpJwGtkeFEe966rCKIx17QS/QPFh6OXc7HDA0FiJBM2jzjsZFW4AK3b+au KRj3BXIuN8n+q199IhIdVEV5WxYN/sE6fH5xf9BhCQKvPHTiMgXw+kVBXqOfq4iBOf7J mhQc2PRzvnSGZf/8QpEXGFrGINWsHyLQLoxvIfJFNM3kMzjN/qeGY8PcjLbjWbC1GNan NOm6mEqOuMQGs7jluE7PzenZQkPVmXj7+IZZXtdMlgxCMevhjqSWGsrAfTcaS6BFHl7/ LMqr1EmOft+ZkaRC9PTmITwX1rVNZOvSRMb5yZzeL+oP5iDAxRF2L7JDDADrXFbfd6fq e9Kw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=i/eEjy8EjBs/e5Jj34VUfUT2QjrL+J3wcm7XuKGrkuc=; fh=2DaSviYS3SDlo+Rfixt8rdqaABxS+ZErCpDLuqVwnNU=; b=eHf+mAlxmIc9IqyjTr8vgjO8IS5uUn40Mifc90u4XCFZkOkgksPswsPuocLj/KMBeC bX4QSAKguHNDx2HJZeh6nILsyRyxFYFoXCaqgSrRW0EdACMwPARyK3JTlfbYsIZ7B73W pLOl++ArzowjL/eE8pTyQsy/wUjj/8My60YDhFscka2D8Axonp7WuEVvRSDJgwsjhZtq DcLgXpkJkj99AcXTLVrzOj2kXUAOrfQUPX/sn0Drl3pArlvjR2RSYCx29OJHoGN9MgZ6 Dmgpgd2H6XOHkiz6LsiMe4ZyTJKillOrPrzCjHMDAmRTdodD+uYhuXOl4f9HqGIkDLkO g/LA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=vP8IHFo3; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59287-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59287-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWypy+4qdIKtBfM5XJXPUqRCPBtlAY9iE7aiQP621pTcxAJgiX5jqvgjnrV/gvWLJn7bgJ7AsE8PNMmp+tJR5WtRMDqpg== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id pi7-20020a17090b1e4700b002908e864e5asi1470917pjb.98.2024.02.09.03.23.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:23:17 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59287-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=vP8IHFo3; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-59287-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59287-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 98D0A280E0F for ; Fri, 9 Feb 2024 11:23:16 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7E6E244C9E; Fri, 9 Feb 2024 11:19:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="vP8IHFo3" Received: from mail-lf1-f74.google.com (mail-lf1-f74.google.com [209.85.167.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0FF23C087 for ; Fri, 9 Feb 2024 11:19:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477559; cv=none; b=bWGmgmwbY45ftO/OWTuhWcBix0SUiWPhAfRu9zqIeaN+uPjSRfX7fU0+7v2ph25iiynqTABxJ4uqhgkKXapmz70cuL+vxaRebrD8TUt0l9rmt536RlIUKJL4VsK7uPAvTALPByRJHPIpKRqD7DMYZwdvxZ0IuS/yZqvfi2Fuhro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477559; c=relaxed/simple; bh=1xxnjqk+SAwAyAAQTy8XinjcAaTXBrnKqLlMXwl2Prs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Mr+3trN6Pm1qofxFs+m2D+6E9DlalB3NXO5zQ/QKLh5BoS/OWB+arTQJKZXBEsV2FByED31ra5zKvIUF81E7FUNuL1We/2h2baXxDQ8WZqIjUKljW6zGG0gywORwzKAfuzG8tPwPWI05TaegmKGxjnsJlZMl5Omeqhd8z3zD/3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=vP8IHFo3; arc=none smtp.client-ip=209.85.167.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-lf1-f74.google.com with SMTP id 2adb3069b0e04-50e55470b49so936213e87.0 for ; Fri, 09 Feb 2024 03:19:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477555; x=1708082355; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=i/eEjy8EjBs/e5Jj34VUfUT2QjrL+J3wcm7XuKGrkuc=; b=vP8IHFo3fQea4cDR67Le8r9eqGLeLALz9ujrZDTivKBkx/22xGFdCPYBSZfv1NZA9b zUSeyTavWND1VX1W2mh1xCxVBWibp5No908fbEzQ4Lekg4lvcjl9jhwIIbEMHV1ey6CN LnnUxqLb1Aj2puBe0OYWxyUMpEIFtP7KK1Z6CP5cdz+pV6d9CRG2LKf/0s5hJRCdErnp 8lTtBOAcvaxvtY1KaWEgHQq0Sjc6bK8+fl2lNR+mL6XcHoaN8E7r+wJPKcicfVAjgLim d8H7K0StyLoUfBkqRDB1+heL6CYuXlq++c8KtkTzNxAC/N4sspELuN4TpiYdsZIXd6E2 fZpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477555; x=1708082355; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=i/eEjy8EjBs/e5Jj34VUfUT2QjrL+J3wcm7XuKGrkuc=; b=YPZOiOBavfSigcd3ikoh77K8EXFZbZMW2FyyqbqlYaRwOagZCIa9zqlgZx3uTuUlT+ KaB27vqwTKE69cDGDC1wOfIVEzYDsZz/cmsV7p+aoUyu99SDDvyjXMD7xwJuKNuoZ1Dw 2GiR0Rfa0uuseWYM//aOkXOWKdRaeQehym98R3e1hgMl6rBtBHFc9yL1dUdYA169J9w5 kXAJcgzvCKDindyyLfS5t0RsEaKyVOK+vfuFeHz4O15wOjiNZ07MQidxfqKrnX9wy0GW Oz2eUr75VBVE0efszGjYCNzrjEsKLr5VCg9hjd2tbbgTCkqg1EEIekSFyoyoDUAsdqFW HJWQ== X-Forwarded-Encrypted: i=1; AJvYcCWla/IHxa+z178My99s+hdfdIVC6J3CmD2YZFQoS8TBLBWj4KxInFyoPMz+qAJ8WKn89FiNI+YBMX3qCZPxxv1epmSFe1SXMJLjvoAT X-Gm-Message-State: AOJu0YxFnbrgHqTKcHYYMKFMBiwMagN6SYcQMJouI+t9/5P1XCWJ8la4 rodslD476x1smPLUPxQZFH8avP3mYEzvp5uWag6gYJLqqv4Zl5b0Ank8CQsFtYwsqADlLaDYKxw j+bcgHQFuny/TGg== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:ac2:58e9:0:b0:511:6aed:81b0 with SMTP id v9-20020ac258e9000000b005116aed81b0mr1053lfo.1.1707477554973; Fri, 09 Feb 2024 03:19:14 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:22 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7156; i=aliceryhl@google.com; h=from:subject:message-id; bh=1xxnjqk+SAwAyAAQTy8XinjcAaTXBrnKqLlMXwl2Prs=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoVLbAi+A07gA4PEN5j4TTZreWWkynfVzDED d+aosnS5liJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKFQAKCRAEWL7uWMY5 Rlt1EACSq7MgWC8Sbje5LSLlyb7hz89g6mUiwRJSmz5SRDBQYWSN8Tcr9Mf3f16t2orPZ9zXYk/ ORVplPxsXG5fsDrzGXyze3TFzvYpgEbVnGIA8LSv1YU6vYZ5PVp7JsNLi4tgzgeMi2oP4yUcikn 3xl7gbwD0P55oMysz0e01XanDYmbQYqcsDEskMdNkOeecytfOm9pvtfy9fU6yHfvcC/ncrJuzxM H58q3ymrF5dgJ1s8kPdk4gmsgIiPiLDBa322oab9d0vaxOu1MMxH/aA0pcGv4z9FgBhGYyTqUnT UayLsGa0B9ewQxGECeBmNnJ0CrRfkrG8DLSJbwlSLOd6yaepCz1frLpWtgcDngnzjQUe8KAv0lZ m7lOnjHtUM5EQTjDUT0IhDytoQMQvYpIfmryunDDs0Vdem2WC3WQ/cEYP6tv3VcvNGLzHlClLsf 1mR4QYwWuVDVqr2V4bPZV13oaq5gn4rToNontwgVv0tCUfOUdTnQpcTXVvBX0+/MMoRu8r7Z6s1 SwKALcMr3yk+jbTY5mynOhRqPpiT/RapVX7vZfF2xoUYwnxY8RGTAwdbAyio5sTpcGPRq2fvqLP DvDwq9+JR3C0P4+2JoDI9PPDE2BZy2jXcCMV6+u7rnPIVwZx/TZEbHAHVUGssn/7L0CRWCuvI5P pO9K71qEwt8invQ== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-9-a37886783025@google.com> Subject: [PATCH v5 9/9] rust: file: add abstraction for `poll_table` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420238375277338 X-GMAIL-MSGID: 1790420238375277338 The existing `CondVar` abstraction is a wrapper around `wait_queue_head`, but it does not support all use-cases of the C `wait_queue_head` type. To be specific, a `CondVar` cannot be registered with a `struct poll_table`. This limitation has the advantage that you do not need to call `synchronize_rcu` when destroying a `CondVar`. However, we need the ability to register a `poll_table` with a `wait_queue_head` in Rust Binder. To enable this, introduce a type called `PollCondVar`, which is like `CondVar` except that you can register a `poll_table`. We also introduce `PollTable`, which is a safe wrapper around `poll_table` that is intended to be used with `PollCondVar`. The destructor of `PollCondVar` unconditionally calls `synchronize_rcu` to ensure that the removal of epoll waiters has fully completed before the `wait_queue_head` is destroyed. That said, `synchronize_rcu` is rather expensive and is not needed in all cases: If we have never registered a `poll_table` with the `wait_queue_head`, then we don't need to call `synchronize_rcu`. (And this is a common case in Binder - not all processes use Binder with epoll.) The current implementation does not account for this, but if we find that it is necessary to improve this, a future patch could store a boolean next to the `wait_queue_head` to keep track of whether a `poll_table` has ever been registered. Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross --- rust/bindings/bindings_helper.h | 1 + rust/kernel/sync.rs | 1 + rust/kernel/sync/poll.rs | 117 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index f4d9d04333c0..c651d38e5dd6 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index c1fb10fc64f4..84b69e337a55 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -11,6 +11,7 @@ mod condvar; pub mod lock; mod locked_by; +pub mod poll; pub use arc::{Arc, ArcBorrow, UniqueArc}; pub use condvar::{CondVar, CondVarTimeoutResult}; diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs new file mode 100644 index 000000000000..a0e4f3de109a --- /dev/null +++ b/rust/kernel/sync/poll.rs @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Utilities for working with `struct poll_table`. + +use crate::{ + bindings, + file::File, + prelude::*, + sync::{CondVar, LockClassKey}, + types::Opaque, +}; +use core::ops::Deref; + +/// Creates a [`PollCondVar`] initialiser with the given name and a newly-created lock class. +#[macro_export] +macro_rules! new_poll_condvar { + ($($name:literal)?) => { + $crate::sync::poll::PollCondVar::new($crate::optional_name!($($name)?), $crate::static_lock_class!()) + }; +} + +/// Wraps the kernel's `struct poll_table`. +/// +/// # Invariants +/// +/// This struct contains a valid `struct poll_table`. +/// +/// For a `struct poll_table` to be valid, its `_qproc` function must follow the safety +/// requirements of `_qproc` functions: +/// +/// * The `_qproc` function is given permission to enqueue a waiter to the provided `poll_table` +/// during the call. Once the waiter is removed and an rcu grace period has passed, it must no +/// longer access the `wait_queue_head`. +#[repr(transparent)] +pub struct PollTable(Opaque); + +impl PollTable { + /// Creates a reference to a [`PollTable`] from a valid pointer. + /// + /// # Safety + /// + /// The caller must ensure that for the duration of 'a, the pointer will point at a valid poll + /// table (as defined in the type invariants). + /// + /// The caller must also ensure that the `poll_table` is only accessed via the returned + /// reference for the duration of 'a. + pub unsafe fn from_ptr<'a>(ptr: *mut bindings::poll_table) -> &'a mut PollTable { + // SAFETY: The safety requirements guarantee the validity of the dereference, while the + // `PollTable` type being transparent makes the cast ok. + unsafe { &mut *ptr.cast() } + } + + fn get_qproc(&self) -> bindings::poll_queue_proc { + let ptr = self.0.get(); + // SAFETY: The `ptr` is valid because it originates from a reference, and the `_qproc` + // field is not modified concurrently with this call since we have an immutable reference. + unsafe { (*ptr)._qproc } + } + + /// Register this [`PollTable`] with the provided [`PollCondVar`], so that it can be notified + /// using the condition variable. + pub fn register_wait(&mut self, file: &File, cv: &PollCondVar) { + if let Some(qproc) = self.get_qproc() { + // SAFETY: The pointers to `file` and `self` need to be valid for the duration of this + // call to `qproc`, which they are because they are references. + // + // The `cv.wait_queue_head` pointer must be valid until an rcu grace period after the + // waiter is removed. The `PollCondVar` is pinned, so before `cv.wait_queue_head` can + // be destroyed, the destructor must run. That destructor first removes all waiters, + // and then waits for an rcu grace period. Therefore, `cv.wait_queue_head` is valid for + // long enough. + unsafe { qproc(file.as_ptr() as _, cv.wait_queue_head.get(), self.0.get()) }; + } + } +} + +/// A wrapper around [`CondVar`] that makes it usable with [`PollTable`]. +/// +/// [`CondVar`]: crate::sync::CondVar +#[pin_data(PinnedDrop)] +pub struct PollCondVar { + #[pin] + inner: CondVar, +} + +impl PollCondVar { + /// Constructs a new condvar initialiser. + pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pin_init!(Self { + inner <- CondVar::new(name, key), + }) + } +} + +// Make the `CondVar` methods callable on `PollCondVar`. +impl Deref for PollCondVar { + type Target = CondVar; + + fn deref(&self) -> &CondVar { + &self.inner + } +} + +#[pinned_drop] +impl PinnedDrop for PollCondVar { + fn drop(self: Pin<&mut Self>) { + // Clear anything registered using `register_wait`. + // + // SAFETY: The pointer points at a valid `wait_queue_head`. + unsafe { bindings::__wake_up_pollfree(self.inner.wait_queue_head.get()) }; + + // Wait for epoll items to be properly removed. + // + // SAFETY: Just an FFI call. + unsafe { bindings::synchronize_rcu() }; + } +}