From patchwork Fri Feb 2 10:55:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195795 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344097dyc; Fri, 2 Feb 2024 02:56:35 -0800 (PST) X-Google-Smtp-Source: AGHT+IGrwffEJWVFRm7mMJEuUBTAfzlTeb+w5Ho9ZGVEcq0agTNUhX9vYRg3DAXBjPLxAueIfLV4 X-Received: by 2002:a05:6402:78e:b0:55f:b005:4c1f with SMTP id d14-20020a056402078e00b0055fb0054c1fmr3056475edy.30.1706871394823; Fri, 02 Feb 2024 02:56:34 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871394; cv=pass; d=google.com; s=arc-20160816; b=uj2AEtMz/D135PoBlK3aDbar5JjCOa3uhR814wD01Iifr9SmBgW5d+Hj/JXQUig6Ip uXDj1crHiaBPlM27hn7phXsBgibppvJfkL9q261jiBlC8YSLz+sj/JNVEXJJScixv8de gK/LTraCs4rQ03hi7o06Y4LekBaGu+gVFSFLexGZxAKfHUUDpASmD3klTrHrCUNjkU/g 07HdvsuxYNKboH30/6kpBl1Zr9PO+YyDk3XQN/dK+9ZYh5r2TyPYF5JEkTempFmDbdJX 7rQ37PpgGaHYS+3a+MJy9W9lcE9PvxBj0vCbwFSZomPBKj3mutrvJnOdcSxgRSEi50Nv WySQ== 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=+0ZULy5/y5vgNdfWgR+xGryignYZX4VlToe5mV4Cwck=; fh=qNAsQEs63Rpl7+7UonzYOPPaZev40aurB+9r3utOE3w=; b=sK098Dc+f2E4uCjTuhh0zoDmsYMzSWMJBPIU1RWXac/iIoe9RFxIim027YTe7s7Tws KSZ8rDlFchbEmZB0MUm2LkSfx+/rUzzxUQqh5ZuoqhFcHkdAxhb2pKXU8sPIg6kdFxqL +P/MUxihfZ+70YpRnJyTK1ex0rfz9hJX16ykIZQWCCfLnvcioAcR4y5PwJOL+wndjrSF exH1ZPRTxTpc0S7pVwzIU8MXCznANra7uTGsT+TOWu+2witVyukxhrMZWZO355UTWCDs REHHRZR0WQwbdXSD/4Rjvqz5rWNsrQ/KwmANiaxBafGJIhNNf7inxnRcVkKyR+vYBAgF 6Q+A==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=ELhKLNuU; 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-49706-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49706-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCXiqtRRJ5YN7Xcqmyk1bPkmuGsLSOl9H3+x80IBKh5rsPJ32goQmNDmHzMp+5f6NAOwymJJokzTAYUaxtT3jDmeKaSPpg== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id b99-20020a509f6c000000b0055d3711d427si702247edf.484.2024.02.02.02.56.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:56:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49706-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=ELhKLNuU; 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-49706-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49706-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 3BD271F262E1 for ; Fri, 2 Feb 2024 10:56:31 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8ACD313E20A; Fri, 2 Feb 2024 10:55:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ELhKLNuU" 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 19B5B13D4ED for ; Fri, 2 Feb 2024 10:55:49 +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=1706871351; cv=none; b=aLSXAT2YrRCD5udXuoHiz3S31wmH6x8caDqLGjXLxO6DR0Ai0ZDA2Or116JYQwuRko5sb2ab5jYfBnPQukXECdlRkrz9/P739TbjEa225n5NU9e19v/aNI2JYfxhwYza6QGYzPAr7c7bfNLGjqBBSdJIeO3x+nX90KuvbSfct+s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871351; c=relaxed/simple; bh=7gwoE0vtO/2/iYZib8O58rbMHk3Wy9KYeSDPJyHPimY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=HW1OUDQHolrc/Kd4Djm85vZ42qi8ptWPe3QiNZ08IgCw6V1ch3+HlDu/corIJK4klPnybAZ0DfaNlBSVZcCZHhpX0yU28jxW/tSDl9Eo+3o8LtHqyN8a/FeT5mazZItHCLcCP4Mx/mjbamUryM+XVZj3AfLfWcai349LEMeb8V8= 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=ELhKLNuU; 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-dbf216080f5so3090406276.1 for ; Fri, 02 Feb 2024 02:55:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871349; x=1707476149; 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=+0ZULy5/y5vgNdfWgR+xGryignYZX4VlToe5mV4Cwck=; b=ELhKLNuUmyCXTskm7QpxezpTciGgsXbMl8drYauIMY+c2t4CSWfgrA1h8s97tIOHTe 0dDHu77WSE/1OeQgB9GNpiuXXhlcb/iNPXFUTmJ6mVTX16cac4Kp+Pca16xQqFfXzG1+ u7AQXr6WCUcS2XahAe1FnVM0YOwSRnHa6JnqSjrQ/pz2VrOunSRGXJ2Q+OFUIcLP+ggE vZbdRpgqpD2P/p1DbDKUV6R+HI0ijO+z0WHhJsr/hORpYPfHBPiyyZzcnjd4ECMx9OGD yBMHfHTuZgNSfyevOPrG9k5m5lhDXkkRBk+165JEJ8eYPNbV/gl0MqC6zaVG56yrkEHm QNlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871349; x=1707476149; 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=+0ZULy5/y5vgNdfWgR+xGryignYZX4VlToe5mV4Cwck=; b=AAdk5x2lpVkCmR/mYrjQ+/IDtCHEXlJPGv39J2u61jqPDAkCI7kpX2DR6j2Cto1mnS N8PhY4fseq4xRHiB8lpi8zhNEnEXcaarROagmAteu7IXGmp8ORC8OxGdqRpfG5lmSNut sgBfwitf+SimIVDQENPtmoxgcJWs8uyWdyq3n1y8CBXiU8rm1/cAD3od00jjFd6OJGzq 4WANecNoee3wHHhG5RYOczuuckPr8TK/ZjUqijyesnROgL76zFgX2w8XS8BKKY4maBFE BusR/ZKebLqiyd0lPFIqA8BdsnBaZCBxab4jZL0eR7o4eJm+3TFURre3LJtVGn+HZblB 8isw== X-Gm-Message-State: AOJu0YzrjdEzkUG4+0801jx2rHTQzH/a9WhmvXc9JqyphgubAqI9e575 X/mD/0uvQ5PxjU4/+fpw0Zw/GMiGA4tidzmcVwGKgGvZMOxUpVgR5yZOp3Co218cVhSPYujLiDz lMGKjmJgAlZq4Lw== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:2509:b0:dc2:4fff:75e9 with SMTP id dt9-20020a056902250900b00dc24fff75e9mr513170ybb.8.1706871349089; Fri, 02 Feb 2024 02:55:49 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:35 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5180; i=aliceryhl@google.com; h=from:subject:message-id; bh=7gwoE0vtO/2/iYZib8O58rbMHk3Wy9KYeSDPJyHPimY=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJVrh8psmguMzY4qssJLn8fU7x6TwLXZl0A b26AWdaCAmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RsolD/90eoXCySNpVOb7NYRwSd+K9mdkE0Zgp+frXI3IfySfd1n78V+DlKjLpoHuW9yKpDOFThM FVZmlkIbki2JVo9lQRrVkXk2SB/jYE1wiIu7wbMN2T4ptQArp7/tLdI158J+m/Y475QCmy6yb1o pgxmY0UWqcmFmMv7bjHCtHqGC3zlfR6PND0fuZISbwIXKxEzgrWsw8OgIzoPFhUj1CaYQnTFV3P oAKBBFrQ+0o8IooTJ1B34MkVcx706eNu76S4KxBlPTzD9SxdLrKyz4opCYHL/p80T2SPpIjP188 08Ha/Cxy8O2pYBiHRQG0Qdg7bnjma8ZaCcclvUg4e1WqVgcYEoaz4xaDDmchAfYao92E/4lGQVl SB969da/RLsuz3NjQTa4xkHwHi52i4AqGYxjn53r/kaiOCuQZaCWohdVTmSUYvbxh1LGwp2C7fv 5lTGSpE6ej8oALanvEfgMz45GsYtTcASuQIogQFmAv1ai6bbOCSYo4zYtfnshTvAn39bLB7FY9i iSIfPamxyb94sXgTK14n6r1M0t+j5wQoSuvlmeeECJ/7aiDoZc11FhYISfw7ZQfHs29Am9qknLV RdfX+lzQLuncgDEMDEEnHrCDSbQteIDfXKU2jW5nk5Vs7KOfc7HwlnKDsnrJvXfreFCM1Fbq3VW Y//l4Ceyv/iuXNg== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-1-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784379509403670 X-GMAIL-MSGID: 1789784379509403670 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 introducion 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 Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo --- rust/kernel/sync/lock.rs | 15 +++++++++++---- rust/kernel/task.rs | 10 ++++++---- rust/kernel/types.rs | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index 149a5259d431..d08d9d32915a 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -6,8 +6,15 @@ //! 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::ScopeGuard, + types::{NotThreadSafe, Opaque}, +}; +use core::{cell::UnsafeCell, marker::PhantomPinned}; use macros::pin_data; pub mod mutex; @@ -132,7 +139,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 +191,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..5841f7512971 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -387,3 +387,20 @@ 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 when a type stores task-local information for example file descriptors. +pub type NotThreadSafe = PhantomData<*mut ()>; + +/// Used to construct instances of type [`NotThreadSafe`] similar to how we construct +/// `PhantomData`. +/// +/// [`NotThreadSafe`]: type@NotThreadSafe +#[allow(non_upper_case_globals)] +pub const NotThreadSafe: NotThreadSafe = PhantomData; From patchwork Fri Feb 2 10:55:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195800 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344781dyc; Fri, 2 Feb 2024 02:58:15 -0800 (PST) X-Google-Smtp-Source: AGHT+IG6ymEm3HgIrwNGYUL4GlUhPXKA4pxnyZhG7R8mxJNc+saxvLi3wYzXPD3gAVdjNkkOJiuo X-Received: by 2002:a17:902:b595:b0:1d7:8382:322e with SMTP id a21-20020a170902b59500b001d78382322emr6756419pls.56.1706871495529; Fri, 02 Feb 2024 02:58:15 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871495; cv=pass; d=google.com; s=arc-20160816; b=nbo4IshIlAiJjJFXl6LxvcHVloSr3x+jHUIFe39b17eA2OkOAg1iCJhdGTII46rDBz BkdX7UatEoTWvd8PAtAVOVm0xmSyUdN4ViS/6KoyD40yOEW9wGNzSF9J3pkaUh3cU61O f82CWKZZsD0rURZJ08qEe70iF/ojsK6YChSAk74GcPPBmWSLR7WufILiITiEYP/wbX5Z izkxqczEDgJWmJ7TSD/GjRbDDePNWrw2/QJGcVi7ljl3kPeVrOW5wzcAKRlHC9k+8YUM zSgS64zsljo3c+zuDwaX8VCwUdJFtadi1J1cgXTrtq8/c5JT3/ns6B0bBZ/W1VK0aClr 990Q== 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=/ApmdViD79PTF2wWIJgz6LFiyNcf37NPzHjT72tU4L0=; fh=h1qoEl76TXb9/bgDWqYTfUqNUU+Rj+lzp2HcB+DUaSs=; b=p22gKQic+Y2ekVCU3U9Q6LMspoV497GKzSAgp8xzSFeNi46yCHvEm7TzWdWGMeh9Qf aIdoZ0WKhInJiJQlRSMiW4hY/acxXT8PkcVCIHdwMiv4936ojYKILFYl4hesua5DE/fz Vy7F4ctjlnAqbBNsxfcPoYSND2Z8rXhgV0wSPnhiVBJcTeeOPi351r08ywQSy1j34MM9 5LuViNfw6tuis6WjKKH9/mcqJfpOg3QLJC9ewk63TVOQtK8vIa/XbpGijxWi+kiDSR/H sPGfMX2s8xx1LwIqHebPySeOvU0N5rPqKKx9NIcaMNAb//kawDWwaWhW3f97hKZ2jcld P1SQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=xFIj4sol; 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-49707-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49707-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCVLSMMLqYuBL9Yh/5wynYbov2zWp/VkYHDJcLHluwY1QqVG0YEeZZpUWlprbf+XR6joPI44exM+A2zCCxzTkRy8L314YA== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id l10-20020a170902e2ca00b001d95ef2a557si1514486plc.170.2024.02.02.02.58.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:58:15 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49707-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=xFIj4sol; 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-49707-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49707-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 2ED9528FF3B for ; Fri, 2 Feb 2024 10:56:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7077413E22C; Fri, 2 Feb 2024 10:55:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="xFIj4sol" 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 905C413DBA0 for ; Fri, 2 Feb 2024 10:55:53 +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=1706871355; cv=none; b=gz7bLKGMuYYbOq4TMLF89XRXFYYbKz5bbiGwD1PGxQJ78ZkkTPZOF7VZz3+FDmzwkgXmLDHW0AUscP4+SQK1xuJRJQpFojBC2sHdWabT4Dx8T4wekprVOhe+jaE55RwXMCsile24WpEfRjBU/0AMoiMHt61YtyTNxKfv48rUB3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871355; c=relaxed/simple; bh=Bjk/OB+Iji4BInn1vTv4uXEE+/4bkjfr3M+GCsCoH3I=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=JBN9ijmDp2RgKhoYUuomm1+L5YzUHxc9BGgst0B++HtqLKx4xZ98lr2th4xdZI0Niw7hFV+w2/9n1EKljx+hzfRIuXgW+QEykO72aGFgOJ8e3ro2joslozn/P/j+LyoszSd5lOr5MVV6GL87vX/RKrDcF2UOOpI++8ToANTtOwk= 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=xFIj4sol; 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-51032b2fb9fso1486012e87.1 for ; Fri, 02 Feb 2024 02:55:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871352; x=1707476152; 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=/ApmdViD79PTF2wWIJgz6LFiyNcf37NPzHjT72tU4L0=; b=xFIj4solmwkyqz0Hx99esWgEI6m0K4Gdnth+taPK7Jv+Z9ioN22ctrf00Wdm0JrTOX Nbg97B2yhsyRVC7d1QeJtE2ACK+h7xbZg8JownLqJM1UE2ZvLVSIy9bHgFqoWHuu32ms xx13uoxQK887TSE3WX1ytdIVChlE4/c7kNWx1U8I59/3tUJpVhFMwgx9AeHqR545l1qJ A+5FAO4h8ckU/KXSODxryyUjjVc/p8rwV4WxzRGfXjKLCURiDFUhxtOG6wm1yCdbyB8N uRvGN1VLnpY0APvuQGfRFoLznYc6w3mekCVrkTUKTuK3T/fjWP/wJK2UNaFuMGpNT64a Z84Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871352; x=1707476152; 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=/ApmdViD79PTF2wWIJgz6LFiyNcf37NPzHjT72tU4L0=; b=ekqNLOW8u1TSkKpdpmpjaeej/yl1ZP1mbdN3ytrA7TCFhlEDdlJvM+IMWw3Liu75+5 Z434/vsLYyda/iVefzKZ8MaJROC0RCYo4qMy+BImhGmfTajTPzipeMETlMK1yXIUG4OF aSIeOUgwOzHM+NV+KPOmDkyQsJozE4WLCoW4Ni9XnhkBFmscalodE3bfgeeHLCzzPc9c ZyG7Q6tYoqelMahf6EYASF4RajCW9PYTGIWdW34uPTvCkV2VHi/C3jyg3EioOzgALUAP NhLZ6GoO2DnRhn8ySUay+Sh1zayqsWrIjwEObMYvoAqagoa88nCMgNYv1KJiO8D62M/a O6Fw== X-Gm-Message-State: AOJu0Yzz3rNcJcwAFjWy7kklbMKcHEFZ2tKhLWs0JKutrebCR6t5GeTH RqwWPHE/3Fcl8CmKZZkZmgsIqMch0u4n2NYOri3nu0eKbYQmIGXNaaMSbtQCpibbe3uKhKBUzvw 9W4+ko1JzYA+BBA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a2e:a449:0:b0:2d0:6086:57f7 with SMTP id v9-20020a2ea449000000b002d0608657f7mr8753ljn.2.1706871351660; Fri, 02 Feb 2024 02:55:51 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:36 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=2292; i=aliceryhl@google.com; h=from:subject:message-id; bh=Bjk/OB+Iji4BInn1vTv4uXEE+/4bkjfr3M+GCsCoH3I=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJckMPHmLhUIiPgXUpw7gM92pGwvmvNEzb9 4LAYK2UX5iJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RrAsD/4jSpaOcEIG9sCDcWDdJX+UN94jVByiIBv6iGusfSlTy/zrfh2/niLbdxLt5ihG79Kvim1 Vy/8VkquGO1Rm1Ff4oAQx9W2waylkLTFnV8IHA18le/kK9Y0P1sUSny3CO4anLD564bXrtBaxZr Fk8CTX9DbPsZCXw5aacUEFUKRk3LI5ZXFRLnKXiACAYr17InVZKyoe+UoiRvalbbzEJKqXbWlzw 352wpnmE2fcf5lWm8JxIj350VJ5YO5jmq9blleXBucfcm5Jhj5yPnfmkj4bx4FR4TEbh/Onh/HK cs0WE02UazElXGcb1W0zjVRW84gxA64KGuZe2cijY0HwL9fEH4w7Wwe/xCxDUjvq2sFkoOalGgp Zzrb/uMoO0is2D3bHXwFGx4gZ5TB+6ungdBIEUWLqb5ZZbqR2MadBJQ6+S4uKHhXVsDLCpXrLVs vium6PbmOAAGWv3R0YD9art/w9pP1JdtTXI3pGPNXt9wcbiq8bdIQ+znCFJG9BKNjuxgvDZcYu9 KTXOk4/+36IgaJm2BI8QJfdwriLQ7Y9Ol/0EzcDbBiVvokUrzJoUSpD/R1Qy7ldBOzuInua0TjX ECpBuyuQYXhjFIBTTLFWmkzM5HHK+yvWlvjaY7F+TKgyUDFyZx/uEE2D05lqho6PPLBtt2SdEHx kvILMP8qnvciJBA== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-2-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784484950722529 X-GMAIL-MSGID: 1789784484950722529 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 Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo --- 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 @@ pub unsafe fn current() -> impl Deref { } } - // 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 2 10:55:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195797 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344510dyc; Fri, 2 Feb 2024 02:57:37 -0800 (PST) X-Google-Smtp-Source: AGHT+IFLjtiuX6gfhlgr3pYFXfCst42LVjlUWrX3Z6AA9rgNw3mSrjKGJOUHias2nAwwP/+fyYIp X-Received: by 2002:ae9:f808:0:b0:783:fa44:b578 with SMTP id x8-20020ae9f808000000b00783fa44b578mr5472168qkh.34.1706871456904; Fri, 02 Feb 2024 02:57:36 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871456; cv=pass; d=google.com; s=arc-20160816; b=zKCmunhP6KgnVHHM9mJlFHeefdxYUO9ev/vFt9+wfPXlz1uwErPgLCRTjMfZVTBeHz wC8/0ZfHszy9g1drX93Rfu0qsbQYqiUZ/x0QAbzGWajRzBFx9faCkFJEKNIlfvB4bKSO 30Pxm5WkG9TyC42ZP9kSV/U6fv7pS1yqH94EWqvu15TmWeKrk1313vZAjCdIHPpC6j3m tt3B2sd+hmbGvBuPeRAt2nfMruvqldU08ATEZXm4loX8oBAeZIgbttQK+5Lohj/+rUn3 fiK8Y0LK4rh5CfNq1bVOH5ctK9xETDzFwEugyd8XjiPXjgjFgEt+5U4iilgVp8K4KDtZ x0fg== 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=/Wv9nx/hg++Pfxe9omwezAG39k+nXIE0TtJhZJnwGio=; fh=3n7rXQouOxFY4KYzC11xendjuoN+EjqJDLuZns4Vykg=; b=X/22wTYhcgcxrv6xbjC/gt1n4lCGtFYBVVu3yOnzxgK0VfZyBpGM+PRd1OjmI7ba4d IkLBjDeaMbR8pjRL5Q+jviVQoSN8RED5K/NzdvLSWPdRE5lSfZmz7S24czc36li9qYis x1hTuoSpMpZp1EhxNpbGrYwjbT7rmHYYU8ZoGXo2wt8VPkDCthiIT8uri01ngHeCo+Fk LIhu9aR7h2zlaqm/NtkgF0qe9Hw7pXL0MuU1p9YUQQIL8ku6P7kiRy/dzcdrfA9uaFJF FOfG5cjZLxCiOfisNyHW7QvfycOmTwoera8Hl/CktulmRev9xM1qn1Y5MFHFmT1kgdYA FsWA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=Wk18TbdO; 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-49708-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49708-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCUDshEv4b4HqfVJuWcyw+awaRqzHgZjbobf0EOkpk6PQV9hp/FzHm2+msnWl75+V2cC4rxfrn8hzQV6km4T5OJ8hViE/g== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id s9-20020a05620a030900b007855e48f56fsi47971qkm.444.2024.02.02.02.57.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:57:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49708-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=Wk18TbdO; 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-49708-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49708-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 9FB171C241D2 for ; Fri, 2 Feb 2024 10:57:36 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 05E51140777; Fri, 2 Feb 2024 10:56:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Wk18TbdO" 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 A85BF13E20F for ; Fri, 2 Feb 2024 10:55:56 +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=1706871359; cv=none; b=jMRZd4jtjyoY71UlF5HwUU/v0X0W2VOW/9Rak4qv0eBPy3HuY4Udx3IkSq0btdK0juJLoUBUacsvgUYKUPJPYaclAq8vvnDYnJMaWUN/NQ3U4JoTPpI7Phl45AY6tdnroZMCWqYhaqO+Jc8bLCYH0VXVa+VLv+owb6SUb+W09BU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871359; c=relaxed/simple; bh=OK6nCgH+RyE9t7EW8698kuFkSaxikkJxGDMbdUM44M8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QwOhWjtFI4z9QT+JGii2HpkLvp6+4EnC1pQ8fy2kLFBfYOE4a9cmcd2SML5WQbeNCwzJbggTTIZwPyYqvyZNuiUCMlGLmb+Igf7aFCLJ0YeE5UDSh7lhgL1j2gMJHfNlFJ1xVj+lKY2Ew59CTJysCeHSfKv4xS83PFZcL/aUbUU= 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=Wk18TbdO; 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-5101569ed09so1923706e87.0 for ; Fri, 02 Feb 2024 02:55:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871355; x=1707476155; 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=/Wv9nx/hg++Pfxe9omwezAG39k+nXIE0TtJhZJnwGio=; b=Wk18TbdOyW0VJM07TyBd3yHnF1rczWomLAFsvVUTjoPdJ7zq3ej9b/h7zoMMdb1q0i vbYkEdZ1F4Eh5dVlgWUX1wtR9A9iLocUtXWLZ8PDy4iVc9iadCOX5WOjLwpN4KlAJ+Vi h5vC0tZnJRU4wPlRGRaVkLCTc+WMJOKrjdPG3F4wV/PQJWjZ6AoXDJQ1CfH7G7kHd2Dm eZ1JwipRv0XQrCTXI3zib4ds5K/nV7rE/5DJ1qorlbdy6e+M4kBcmmGsFV5MUrE5F/XN excGYtX3tcDgQxwjUx96ISN3P1tyT2jCYD725TbuX0bLVucf3i3fAyWdRBGpseQwCdz8 zyMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871355; x=1707476155; 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=/Wv9nx/hg++Pfxe9omwezAG39k+nXIE0TtJhZJnwGio=; b=rc/JP6+Fk2qZIanTNtxoGGjKSGLXw3IHI4VkDu75xPPS6bp6jMXhNWf7tFWFuLTTLo Z69kvE+ZCw4ldgoOW4InIlNX/zhGCoVnCfw6seFZrGYzo+iNq/moYyl5jA1U0N6sD6is /WEutoVo2jlwGg2ltDR08TFyW6Brdwkh8HadCVu0q+01v0kxVibnW3swkJQG5FDYw7d+ GmSR8f/ZAGLV/+TVD+u9nVd5kQ0tsNcqvaAOLnAkjr3rErpMwEL2ll0AeUlqGhAa5oD+ mUbaTF8s4+mwGa53HxTIc4cJh/+fKEkrqB7yGEa597BmsffhipaO6aXKDXIY6iX5M7nh MVUg== X-Gm-Message-State: AOJu0YwnsurboK95NLsDzZ/3gipD3OHWz4KxzJygs4FgvEMeG5fGxE8L dNIWqvUbFOkejloKikDFHY2euyWLAp9dlrTjDvDKNd8XQn1GMwTYX9kmx8fjX4VOu99uNjr0cFH /apCdFNDcB+kSeA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:ac2:5e28:0:b0:511:1afb:db4e with SMTP id o8-20020ac25e28000000b005111afbdb4emr6094lfg.1.1706871354618; Fri, 02 Feb 2024 02:55:54 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:37 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=15836; i=aliceryhl@google.com; h=from:subject:message-id; bh=Y5frGCIgjDFoW7XzeCBNv5ty3pcNGFQjMN/M3VqKY78=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJm1MjNjNhozhIhF5gOkylEenZy+uL0IMf4 3IyMk0DpU2JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RnWMD/9Bi7eGuJMxqK4PLS2zJPtmSpFQoWK1kDx5RE17sw377z8k58z70xadV1VOF8/sNUnJvkG c3yiIFhIwlSgfw4jnl4kK+tw25xRNDDwewgdPfbsIeJfTydwrB4Q2X/fQOw9NNvc0qhWHUyFENd 8/li+N0srpxJge0c7v+1oiczvDZ+psG7Xy3N6mrXhKYvXPZ2mlPti+xk1JUCs+nkDF1EKFzOzLv LolcWEd7B+gQrjTziZlPUFgRKmus1Ffhv/v2bCePQIF04/4ENxO1bLBLltMpz9G+VfI8Kh45RGC wPNraGZB8uQ3EH9Q/cfgYEUMjjm8Fn6XzLYrED4vrL7ST78j+ERIpv3AwJTm2LlF7y4DNlAJNbS i9neKiss7Nek7wG6KR2qN5YLH53CY1Sp98tthCsB2bcRtK+QZ9Lc6cDtiYqdO880bh4OT/qizYQ pSdBwtc7Wsn3hxOz4+teMTW7ggR4nhslXRd4wvhnyYVAK0lscGu2za9Em3Xeh7BHZrGuGr6DtG/ lnpD97R7SnsaSyyc3chT0gVc05QjKV5vTDAdnrZxBcMfQ2yaQq8UBpxgb7R1fsk4ov8Z88DEnIS g/LFlc83Qkl0pQsJZybbtIjYtxiU8o4ve8uMdr4QV2ehS9Oo50cyKmByPMEwv5blyJB3y4mvVNt 7maRZHSqOKeg7Wg== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-3-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784445148933086 X-GMAIL-MSGID: 1789784445148933086 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 Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo --- fs/file.c | 7 + rust/bindings/bindings_helper.h | 2 + rust/helpers.c | 7 + rust/kernel/file.rs | 249 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 5 files changed, 266 insertions(+) create mode 100644 rust/kernel/file.rs diff --git a/fs/file.c b/fs/file.c index 3b683b9101d8..f2eab5fcb87f 100644 --- a/fs/file.c +++ b/fs/file.c @@ -1115,18 +1115,25 @@ EXPORT_SYMBOL(task_lookup_next_fdget_rcu); /* * Lightweight file lookup - no refcnt increment if fd table isn't shared. * * You can use this instead of fget if you satisfy all of the following * conditions: * 1) You must call fput_light before exiting the syscall and returning control * to userspace (i.e. you cannot remember the returned struct file * after * returning to userspace). * 2) You must not call filp_close on the returned struct file * in between * calls to fget_light and fput_light. * 3) You must not clone the current task in between the calls to fget_light * and fput_light. * * 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..0d6ef32009c6 --- /dev/null +++ b/rust/kernel/file.rs @@ -0,0 +1,249 @@ +// 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; + + /// Also known as `O_NDELAY`. + /// + /// 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`. +/// +/// # 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 `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. + // + // TODO: 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 2 10:55:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195796 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344467dyc; Fri, 2 Feb 2024 02:57:30 -0800 (PST) X-Google-Smtp-Source: AGHT+IHmb/5izfuRhMWDStZMEsb8oBAQkmSJ3DeTubEjTEM5+oocxuwnjqjaLV48+FJIRALEYYny X-Received: by 2002:a17:907:7782:b0:a35:3c1f:b29f with SMTP id ky2-20020a170907778200b00a353c1fb29fmr1215706ejc.5.1706871450305; Fri, 02 Feb 2024 02:57:30 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871450; cv=pass; d=google.com; s=arc-20160816; b=w+SntET34WXmAKiD2JwY92VQ0XvQYrvhNlY/KSyHlsQllmp3vYXJwL9prA+ODIVcFt P+HsR4/6kelgRsvxftGxseeXIemRAI0Q9+OPzKb0AypVUBkVbIL9YO39tTm3rAOj/+Ux 5LPPJdIPqH6vms9WcR6kYtvzu9gIsjjV1s5Kwy/uvxWUlyyPsARvLKqDEGP3dfpxDeIs KQPVDet3tKpVJWTXolYxn1iFfUeV2drmIlwoRzFe8/FJ5qScRCvsMZn8yIlPUf5D5JhQ lCuo5Qj6w6+hScvsw7vG/kpYt1QjZWKgZOkR5lLOr2p1dvHhRp8ysOsjHHXiLNvIz9qF Np6Q== 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=6GYoowl1Ig0jePPuB7MkxgkBlU6gWq9TSj9WyS6KkJA=; fh=w8yS2t7vhYW88WXSTyXTmAxcLWjRfHqadt4ezDplCJ8=; b=kASSA8T9DLpp00GqN9mqO1fprLyxgO7nlDjQ6GDtnuDtQ2omgm22YAycrfw907lNU6 3FTqtc5OUvY12JHyLRq69orbDOg+gfD3QUzRD/mHMraWUomSLv8tClnS8SwuVNYc8QeO NpIJOtpxoi7PXf/1r8TiMoRHhVmeDxPDhN0Sc2tibw9LVdcEelAUOQtE/QTfRWICffPO AEw+m4QtsMS66z1ZLY8XvEeLXXgLI4h2EAjRhvhTSGrLJh2MKm00hGOOpMEstNF7uxWI 77Hm3POvG8uuGrPgWNrGzDr5UUQonmOEfv3VazNAMjDPEPLkzDFRrs+TlXJyDUCoHQpl 0NRQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=g2KIhTdi; 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-49709-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49709-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCW2f0UC/OBASU7yHsbL0jG9ilUhW+RdIesZYiI5osdbLUQ19rhKncUdxP1u9qOwO6bVbaUTC2LawD+UAFA8YcOS5+phCA== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id rp13-20020a170906d96d00b00a367c3b84a1si714916ejb.431.2024.02.02.02.57.30 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:57:30 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49709-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=g2KIhTdi; 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-49709-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49709-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 95A521F216C8 for ; Fri, 2 Feb 2024 10:57:29 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A698762A16; Fri, 2 Feb 2024 10:56:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="g2KIhTdi" 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 A221613D4EA for ; Fri, 2 Feb 2024 10:55:58 +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=1706871360; cv=none; b=pkXI9Xd9uuMpq921xRMOHY0YVIMm7U1KA6D1GBZ88we7l36yLzAQfS/tycdQgIc7z9WncwnNawGZsSeVUIMF6G2R5b++p9jBiLvn9r+0O71rq3mMOLmNOsefvJHhccglmlIQ/UGAOPqyP+GY9dX35QVnQuTYXiD82SAPgtSrMvo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871360; c=relaxed/simple; bh=VjG8KeHVT0bRonA+wMBCaRlMOvyLx3lxFBnR9ZrLsnA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=JI2yjtQDqC5U1VTOhyF9sqwAOhokD6JEbn2YBbxSpM4JVJzmMB2UNRcyacga+Zodp3NSPPpvz+LbhJHQzFZP2r6teQdfVYMgeLG9IAK5IhbIjuF/Ta4qerr3DMwl6uBpLp0EQnFtD+ft2/vOHq9SDQs8CgWMS+Hdzjb1XLW3kLc= 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=g2KIhTdi; 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-6041e5b4367so27584747b3.3 for ; Fri, 02 Feb 2024 02:55:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871357; x=1707476157; 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=6GYoowl1Ig0jePPuB7MkxgkBlU6gWq9TSj9WyS6KkJA=; b=g2KIhTdif34wZGV0noroII1cIVxMd4IKatTE7wjP28HjqtQPtj2s/9u1ptBYxCDFWI BDk4ePZPqLfvNzpXhTI3CGW2ZnO2sff9q0vXXVnNlDcxMce5ZhpUkLu6GMQmFYfBbPwi Hd78bMnK0Fhh97QXlqXRJhyXY6s0N1KRpNaflIiiuGx8fikNn1MI8PzgsoTi75VPc/CF uKakRRXnIqZNwLGJagXeihQa72v4Bdhw8Lxehp8s/C0TN+Quf0wKHTDIuTKFxZ0lNpcS nA1FcCvZgnncsqnJURetKAM+YMnTlFUklYQLSQ5XU6Ztue+Rfn3hO+SODG1+75yIAx+e J5HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871357; x=1707476157; 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=6GYoowl1Ig0jePPuB7MkxgkBlU6gWq9TSj9WyS6KkJA=; b=ZelgijcPe7WuBf/naE4IFbGMI5yrfsU1Yxgw3GPeMU6Ha4+7ZGQtOgYsuPs2S7VX36 nfSqvleAWt9aJGG1mCW4OBr1NAJFcxxkrv6fH4pv5PsIO8tdOLoIPOwPhQAIUCx25tRQ AOh7SbHbCm6495sKzaBAWqX5bH11EryRvzNVh73gl9FJLIJMliEPiF/+Pm9H4JsUZmnN FlDKYJfjKV0H9ucfklo8cWVvnqj5JmLZ9O7UwT7wqPfXZXjZxQgQdSTxt0kpyMiS+F0M zSYiDxYxGLCLKN9e00brp3bb/co7HoauACTZZnvh/xawDH2A4FuDdn+JvFdOoGx72BLM jNBw== X-Gm-Message-State: AOJu0YxMezJflMKbuv+uukNVmqDaYGxUK4NAU80FgUc1WzhnB3ilt5k0 62ai4NdW948ujgfI1GHd73LKB8Vm7m73q+X2tu2UttEkHqrSjCMoXYyLqZ3S5Pgd1ZiD1fReIAt i7XBjwSNahWJ6PA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a81:984f:0:b0:5f8:e803:4b0d with SMTP id p76-20020a81984f000000b005f8e8034b0dmr1243493ywg.2.1706871357746; Fri, 02 Feb 2024 02:55:57 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:38 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=6907; i=aliceryhl@google.com; h=from:subject:message-id; bh=2vVeNVuu/5fFy4n9rU91a6ylN+gEl4mdw/ZMMDxAU7M=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJdh5WgrbgvuCcDMOcJWBvJ31HrlBrqBMtS /dzR3QR8VqJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RhthD/0bD1c2e2WGe2h61KiU83ljczWqb3+bILZhB64qEg9UlTt63TNfGwR9QGT+RIDVrZPzLV9 1ZM7UsVbYuzKvfJYloFIwFO4pJxR8EJjXV+Dto5AnDpOVOs9fJDQtQEIbBC4KLK/FsnrGQxgljM 2CDtyixe35XiYQ3MRMXE3/OV2m4+ST6kdJMOic6v7WVjy0Ry2uxTZte8FsQCLA+jElL1KAAsGSX AVuscLUH5cgMv+gARKHD64flxCjtTPIuCyA7GF1DoxeBGx9xmap6ueEjm1o037WOTQLsNaNwNO+ mLFJl/qUTfaFrRTf7vK/r4l/xYl4oLItqBzZUGJM94T5NTc3vnrjKD13UtP6d7gRaDTNZ2+2QBq zWI/shFSPuPqJG+t5ukjZqpJU4opkpwFM/FNtfzpQI3jWecOh7fhiK3MhOlGvtPm2FM7MfvMP2a ty5TKPi4IAG2GFfF8mZ7mG/aljSHkc7uKOCNTRUIXF8bx/cczvr32jFCxugdlNygaN2WhKQvykn ezvsqLuVCH347pWbgDNsjOQCH/ZtttJweKtkljqN0//5j+g7zqUhK6mPiZGwz8e3TBJEaXC2MCq bV1V+mOeUgKvDUjJ/rk8tuLyu3RpNaBVHPFOpPvTzY1Q/+6cUnzScaAbOs9IosJEuP54fTRKdk8 dn2xJV158IEQIeA== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-4-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784438202588557 X-GMAIL-MSGID: 1789784438202588557 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 Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 13 ++++++ rust/kernel/cred.rs | 72 +++++++++++++++++++++++++++++++++ rust/kernel/file.rs | 13 ++++++ rust/kernel/lib.rs | 1 + 5 files changed, 100 insertions(+) create mode 100644 rust/kernel/cred.rs 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..fabc50e48c9e --- /dev/null +++ b/rust/kernel/cred.rs @@ -0,0 +1,72 @@ +// 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`. +/// +/// Most fields of credentials are immutable. When things have their credentials changed, that +/// happens by replacing the credential instad 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 0d6ef32009c6..095775411979 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}, }; @@ -202,6 +203,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 2 10:55:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195798 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344603dyc; Fri, 2 Feb 2024 02:57:50 -0800 (PST) X-Google-Smtp-Source: AGHT+IF8vMBvA3Ka7FHVibr/e38JG3rZsE2BTxj6sKeNbkOJbdQjikpLhCSPO1mG8y+DDEqOAmdm X-Received: by 2002:aa7:df0f:0:b0:55e:ed35:ffce with SMTP id c15-20020aa7df0f000000b0055eed35ffcemr980978edy.37.1706871470170; Fri, 02 Feb 2024 02:57:50 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871470; cv=pass; d=google.com; s=arc-20160816; b=Atg+UuhIxJfsPxls2LCO3zet7EDSoohZrSD2EG2pkxkyWPIzFZtsdKp3afxBA8q779 nUOMq8jIT5ljxiwr2AtEhUl6oskCfiz3DiitSaqAKBATGKPJQZ/4rkKaXQkhjNSo6IaP qfeb0SQQ7XF9QY0OriMPkrL7G2D1UcgRJarCgonh3ou9BOzHWzxYBRo8PM6Qb1IaslsY jjA0G29SCacT/HDCblyt9zk8jZ+bYvPsLO3+XLw+ApOZjT7CDK8ZVW3N6VDOURWauQ5N PFz2Jx75SF8F209Nhy41unIYDmP1J2Q2OKNVQhuuq4bgOXXzqG925xw+E5ULCQ7id1T2 tApA== 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=N/cEy1eL/l/XNVoA+dLHaLRQMYmmdCYyUSwII431DqQ=; fh=j/7kyGGpKcEwHQdz9v5HdILBox+yyfhBXM6E90EM950=; b=Nom1XR20rY5HT5IBLLZUlNTCJpMYYglqaVy2DoHFDajr7cTlM1TZ/zvpfkN9yMikSC 2WWmeGVtKKLM0eSCemW1zTZ32wB78v71G3/brl2ujTE1uNtfvJRcei09fup08UtYDut4 DGa9I6lVKif+ygu9szoEYLl+gIrIHJKuTX5FF1j1qJcpAl2CcEvHty3epJUw5wDgLxjD CKIhkLAK/LG0rO2slK2lJP7AzoayG+/N1zNqHw7X5NBqOYB+jBSiKpHTCDmCdRD9pjLk v2XPAysQJtt7rN1DQUWj1EofXqvL/FJHv4WJeMjoXUD/4pEAIA01QHrMI0OLtV85RvaL zTxQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=qLqtGd5q; 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-49710-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49710-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCU3l5u93/Hcj8V1gDCSGMAaKr+EgoldC4H0E1T3F4KoyGLAHA8m7UXcFjVFP5KOQNlZMtHxJkKkPxL3Cj7pXPKYa19YXA== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id cf13-20020a0564020b8d00b0055d0a061ef7si709112edb.523.2024.02.02.02.57.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:57:50 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49710-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=qLqtGd5q; 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-49710-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49710-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 9ADF71F21934 for ; Fri, 2 Feb 2024 10:57:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 868CD14078F; Fri, 2 Feb 2024 10:56:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qLqtGd5q" 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 7B1E613EFED for ; Fri, 2 Feb 2024 10:56:01 +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=1706871363; cv=none; b=l+noix3jPX+RRicvE+lGM2orXqyCnPKRTRZcF7Lq/LG00sG4mQxGr0rUO1dzRKdRD5XRkXOutmItryxOY/vZwZ+mksUIHZQdaXaa9dEyrZod5xuwvNaHPfQzmHCTA9VrcHoj6OV1qoqFF7qPREMUPDF44VHKWomkOQtLMejr/wA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871363; c=relaxed/simple; bh=LAKcJY6R7fk8wuf3FdVFNOskSEsABniFk3E+zDxpTYA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=i8lc1lC3K3EeoodVuGSkebopMHXkHFlu9LW7zot1rW1yA42YGS5EZ31TqShVWu+UwGpBPajLO5ce9oar9i6jLB5a4Ra11p8cGL35waGiDkT8eniQvsN6JmeTJQVH68LHXSxhbqiwYOXa4aIa9L8xvKPtsMv6OutH9WmVAnJYN/A= 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=qLqtGd5q; 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-60405c0c9b0so45297237b3.1 for ; Fri, 02 Feb 2024 02:56:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871360; x=1707476160; 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=N/cEy1eL/l/XNVoA+dLHaLRQMYmmdCYyUSwII431DqQ=; b=qLqtGd5q+9Vt67M12OaNuLmEbjzVIx+CmdnnCfv/v6R9DdAv9OQPP7wLdPIWCCLAvX qk9HGMWDCasO1x9rNXwCCoTsXbdjN3azltQzbEJnI0d/4Fae+bOggIOGRt5NAnS+ifE2 5IJZ+lK4jRMTXFTUexjTSGyoC5FNYbMClpMl50gmy/jP0an1ZD9u01l3e4bowT6nJ2H6 nRhRc6gLJLHMiedm8j1VnDwF8k3XDWkYfoOOIHyAI6T5WtsexACJmA031LAwF1/cUpEa 4UUdgjoGchaODyr692Cdvcd6vwRdr6bCnZ2as5+NFicpiMzYdFS7iaO1shIrR1Jc/EPA naHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871360; x=1707476160; 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=N/cEy1eL/l/XNVoA+dLHaLRQMYmmdCYyUSwII431DqQ=; b=iPK13OXlcOSUTk7SF6Y0W6xiPA0cS6NW5luMxQjjjJVuhLccEAkIn+OaU+dIfNR7Eo xpROdiAne1uIhIT6YSEWRE6ugLr1t0NOc7/P8o06fN9Z/8w2hDz6C8XdDujvWqWncoba GueDb9uicN/TBGsCJmFj0i0eWni55EAPLhxhnPY9YrEeumLG5zGDqeI4IGIv9vdmTL1I 5EoVhXMsWecrXFGEL9B1SjfOH/kytmKkAhe66j4qi3NTaLqMXvKJq8NyTypw+a7Me+LK wbB05oimKq5l+zPnfh/3j/JVWA7Vr+wgvExpsOytvvXIqkRlEThsbzbX2TqvvnqnGX9d AY6Q== X-Gm-Message-State: AOJu0YwqZupxyH/pn54U5RUE8DYh2GO/HNIgXOO5AWhFOE87OGDsLYP6 65pQMdB2+BYtCJaeZ6GmNyct3XJfl5io0D4vQF2m/chf/qc8oiqmfnITuJsDXUvxi0IuWpdjKfV NJds6zT86ykPyhw== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:108e:b0:dbd:b165:441 with SMTP id v14-20020a056902108e00b00dbdb1650441mr505685ybu.0.1706871360496; Fri, 02 Feb 2024 02:56:00 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:39 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=6367; i=aliceryhl@google.com; h=from:subject:message-id; bh=LAKcJY6R7fk8wuf3FdVFNOskSEsABniFk3E+zDxpTYA=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJDLWaBObEUkm/vJdm8vQJA/wX9vGKDjqW9 /at096sPU+JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 Rou1EACWIY6SndO4eyAbK86sp6UNQjtZ8uyPav+PwM/ipkr9RAskcCYz2fIsoyiYlBEC3g39+BY cXPs5MvP4YA+vze3qBBnSfX6FBp3VB6p2FJpwEltRdhQ4/ryThht6Ji7UA0FyD2OtcvvD4+KJ8d GNjK4haBwvbTUS3ia8HSGmwaX85QiyR/YpUt683Y1vCd0eU/PlOrRYXgtPvKqdWibdUrRpfOt+c ciTN9lOgbgBvUCJWTKO4v64p1eAnoemMsU6jrAMp6AyCCjcdzs066y7gmAYqQE1Qh1iBl5Mt9OU 7Mt03V49vTV+4vPeKkq9wVefoXHrEZOvf/rADw89dqqd31VS30ldHS4BnWGWXVnM5XJXU7eycyW fydQ++WqeaOF2bMSvs92VxM3LSqyFf6AfnrVNooHAfASfsUIT3Jp8ajGXJXvfXmgUBaU5WXz7Il NmUTpwOJSGccHILnkzJI+dh/mXf/M8X1xb7/E7N8LHZndnJ0QOxgtKebuEWPKpm/0iDWok7tXGG 5dh7txZAq7ZRYgaVjRsg+BmElA/b5s865Ptz7EX10xPaVYpslbrfOE+3M3sQmO2zJ+ubLiE8WPD vQLys3PlDJxRvYWfFntquWD+FsnO3aBe32FszwqFGGRD4F0ZuNaWYu1yDXzsZd16RV1akKwSc2F o7onX77ur4pqzaQ== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-5-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784458939992779 X-GMAIL-MSGID: 1789784458939992779 Adds an abstraction for viewing the string representation of a security context. This is needed by Rust Binder because it has 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 Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross Reviewed-by: Martin Rodriguez Reboredo --- 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(+) create mode 100644 rust/kernel/security.rs 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 fabc50e48c9e..0640356a8c29 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -48,6 +48,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 2 10:55:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195799 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344758dyc; Fri, 2 Feb 2024 02:58:11 -0800 (PST) X-Google-Smtp-Source: AGHT+IE5CiHFhHsZ7S6tyFBrq37/fwF3qwmWSe9OF3w3Gkx8iqQMYVoCtMbCP2eStxAFi5AN1mE0 X-Received: by 2002:ac8:7dc9:0:b0:42b:fda6:dbe8 with SMTP id c9-20020ac87dc9000000b0042bfda6dbe8mr3290701qte.17.1706871491619; Fri, 02 Feb 2024 02:58:11 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871491; cv=pass; d=google.com; s=arc-20160816; b=WWvzPZSBdHYilJlTAPNjnntWH8fy+Ut4bMUTR7WkVSrswraJwpQthuXLChU0MUcUgX SgLiEawxuTKsy9Z6f+0hOli3Rl3o7oUKv+rbHDTHg1Axy13T0fTsp4Ka1I/Rn9cE99ie /4qqT9sIVB0YIP7tikh2JTqv8ectaiLBaYGtXH97JomU94KgsBdrlzf4uZczD2MpB17C Rl/Gg9g0D9bqMtDilItgsUxcaR1Fv/uac8BOfAnOg3ktJI9sbbloyaiUv72X7ybGuftC mN4cjIcOQMywYmBm+6WUu/ULhjtyWHv93pyvAHJ+YwYyFtyGJPbRrDw57mgZqt+GERe0 MIzw== 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=j0kQAYir3oZEIRDEnXelicKinA6h+DIjN/X4cL6IApI=; fh=3BCXC/vw3JLndguyf54b/GE+QxCR4zwwQsnks5vPmfE=; b=RrP7hLu1D0K31/OnIvN+PBaPQb+jYF//CeVJYboj+fKSjr1AbIMBDLwPswtRq1fh3L HKPEW5TWE/B5dDBSMEtl9V19gpcag8ZAhF+cPNM5y3wCrREjxAujZYm2MKIYkSYzb4b0 ZLljy0Hz88gGvOtO953egr4aiQoaHVewi9UzW5UNfOr5BtguY7mZSHV/uTF+9LjuA3T9 Bx1PcFBS1rAMdpCrtPIF7igQ+9nWnU9acy5NaS3UDuZGeFWhyPc8hh90WTBdUTmzH4TO nAS8FKhEoHX/0cRCxLi7OvPe/WAV7WMx7iX9Qa3yApskL0EG1XXIhL9hpi55XiWYnnDW DrTw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=KaDpZSN4; 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-49711-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49711-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCWW+JG8X8mremFuoLfthBMmeU4ozxI5Xz7yLWKiD+gTkd/Fiv5o8ibRoQBEsXf9ceZkR4Z7GhVEp5PDeRAOJAKUvEQ7lQ== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id 11-20020ac84e8b000000b0042bed047689si1762039qtp.315.2024.02.02.02.58.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:58:11 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49711-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=KaDpZSN4; 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-49711-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49711-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 5D43C1C2676E for ; Fri, 2 Feb 2024 10:58:11 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 00F10141996; Fri, 2 Feb 2024 10:56:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KaDpZSN4" 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 3CEAF140771 for ; Fri, 2 Feb 2024 10:56:05 +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=1706871367; cv=none; b=qp0QxQooPrFUJJJMCRHYlmOn3RkQoggIBIojNDrprrAsvpgee7D0ZbvGj/nJ4qVpu0Yn4edXosMvlwPsCwwPbkDwqRZbc/LAxblWdEvxuqkmhLDOCbEOtNb87cYAf16KzWHnd9yB9nC2mx5/MtRRRMHvTExxSWf7qdGIgUM4O2A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871367; c=relaxed/simple; bh=rtE/oxepQqksMoR2qP3TYN4awGZUE7hR5gf+H0B+bNQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=LrH8OTv1GmS7HidXlqHOrmosOWGgrdupE5XvHg6we82Xbx6YPaK9JsxpReab8P60GctPosETFclU0xI4I0jnxhZZFfT+Dd0JPHAE6u7vhD4g7Z+ZgR824jsKaF3IRg0d5JIhKQx20iKKfhZgAkTFrwvkQ3uvTapkRPSUzMAy+Bg= 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=KaDpZSN4; 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-2d07ef53265so13238701fa.1 for ; Fri, 02 Feb 2024 02:56:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871363; x=1707476163; 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=j0kQAYir3oZEIRDEnXelicKinA6h+DIjN/X4cL6IApI=; b=KaDpZSN4pKxnXUYxuj5/iF+QNSfN3yj5BUM5H9r7TXd2anKAOCvvNU79Y4Q6pNdI2c LFOmXYnut1BSr/M46c2xaB+cEMamMaEWh1XoGo8rN/sXZCuy69LxpkvU+HezDem+wgk5 L/VyPf+bwRIsjocpuHucBmtGAJm6mf6MqFqTEQ1JmzM8WgvqtdGo8LSLNIgQaW7WQ/5n BQ+PlZ/tq1tMe5utYIzc3tjVnBgu+4CQoeeXJP8vNbOtINx81icRqA1ZU6HEgLAXdUZP cfGZqsksaVGOoJ9ASytsqaTLl8V4FMFUZHiNIcH1aDAqMYwBmyKrBhnF8Bv+ybZxYmSg Spgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871363; x=1707476163; 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=j0kQAYir3oZEIRDEnXelicKinA6h+DIjN/X4cL6IApI=; b=Yd9JI8P6lNe2TF1cfhPmV6FImGaBRZeaEGay9I+UFgMBoZWL0CHRo0DnaErin9A7Ak /jYOSvqLl0OOt5Jyus57qE3XFz6OGE+ugv0Qxsf4Tts8AaO8Se1FYHx+B2eZDBcNgS1x 2JNVS4wnDqseVXnhiRbo9pGm8f3cNdRkNTT+IN76/j2/zFHFcajcQHp3VZKzPxttEPAb qWCGd0AUNfKzhytP9yzm00qBUTYZW2l7qvoiaAkSiCtP2Nx2K3Q3CHZgvYs1Z6hshLPL g9uLbQVcKYkgcfpOnBYxUZlBc1RJgFONGMXe957imHGAhomWytChq0Lnmgb4t/8zKH6l 6hZw== X-Gm-Message-State: AOJu0YwPGSoRoXJpSD9Q7yha8GB76MxbuN4Y0SCDCpVsatvK1BtdPEa2 dr4AkSym27MxlZ5LbDn0PgOBdS2XUvwxqPMir0yWJe3DFUlyTQkhB0njgG66mWGE4ncegRoLHyz UV+qhPD+szIuqLA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a2e:b74c:0:b0:2d0:8445:ed0 with SMTP id k12-20020a2eb74c000000b002d084450ed0mr1642ljo.1.1706871363112; Fri, 02 Feb 2024 02:56:03 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:40 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5020; i=aliceryhl@google.com; h=from:subject:message-id; bh=YCd8Lz4NQ7loX+ZbPkzyOHKKxufRjuF+zON1dgx0uqI=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJbqrZjLJl6uR5Bkp5+R171uPaIU6vFld2j bMoKBaFa+KJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RrkLD/9+HcI/n4ZPrDD3BILD8zoSicDxCF9ACdPWFuJApsidYxMhtaI/iA9uM1hzg1MoAiotNr/ un7kzqyv0CyRf/+GkI9BVhxDjfsmc3vdKX9KwMHs/8UJ2/LYQX644ERm//D/Nc9av81/PEMIyj2 yUygfbPmRF13ridgReF6P+Bjj7F/aQJyP5GRewBhymFkRt4NFw51lS+PDqtTXQ99lHrp2xQLVOz MpUdSJKRlxnHJDVEX+tcgSJs3ffDLknbvXegWJ296c0gJZz1w2xpN5yslfrhfeYWXBuYbF53O7c ktdmltlm0EZfGyKvi+cvcOyh6TZHEoePWuAIw5NHJIYXC+4UzR0oXuXb3Gx9yyMz/zNjU0YA+lF BZTgxlbBCSExKmQJgEgJ56HQblQYqUnQnSQ9ZieDRGoOWPcS5hINxO16yYPxWMhJWK/6KzhNQXp tqDBH2pxmLHHhndhlXDq7BCtkB0hCIrdc8WGBbk/rzOCuLBkP0Vz5/Op/Z2xFzYWTFgNjlB+6Pj UbLlXkG9iJew2C9h4KnwsCLKTcz8uhppbqztkMuSxfqY9uRR42re2iwTi2Nc1sXrji4/+p/E8r4 uqeMOUneKKvT6whbLAFHT8GaqazYU6NvxjLfmL4aBKnxeVHaxIsbzeI4jfCFSKFXs5cb3kUhBbe TJ0DQpOlv8/5MjQ== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-6-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784481491058763 X-GMAIL-MSGID: 1789784481491058763 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 Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo --- 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 095775411979..2004270a661c 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; @@ -243,6 +243,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 2 10:55:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195801 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp347530dyc; Fri, 2 Feb 2024 03:02:39 -0800 (PST) X-Google-Smtp-Source: AGHT+IEF+PE3lwFA4WeB76BRJ0UkP6++PNNInbX15zipdCQ/S1Cc2EOAHdR5BYh41CP6aG6LZXap X-Received: by 2002:a17:902:e5d1:b0:1d9:2e9d:8cb6 with SMTP id u17-20020a170902e5d100b001d92e9d8cb6mr2911656plf.15.1706871759001; Fri, 02 Feb 2024 03:02:39 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871758; cv=pass; d=google.com; s=arc-20160816; b=z5EFVzwA/ej8A6LgZio2V5NJ35zGtDbbeot4NqBg/awfPPRY/BxVkNye6mNyKHG9Rb 0kOKhZKzOs4HmtXhwSIXlq3IC3YjPKwmQYH92fr5VVfKh7gzMDDyfz20wG7nIjYGz0dq rAqGB7u1Dgrm5gOquJWzsklZ2KRxoo45lob6E8ZM1r+E3rQSlM0nvy4JzA4jsiVx/Zje S0gL3Boz0/V9WFN8VT7E/rJuPU0rG6RVIxj/mNFHTRgr4ldfTW+iUqqDevQYQaTAjnYR 28hR6Ge8IqpoUZ3+MA2uP43musnaoSEea0HuiMPYhxOb9j8sUb4V02x54qQ/4Dobrb51 ouSQ== 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=hwQz9+kg606GttZk5ufJHJgW1rtd9e3JGMr5cW0AGC8=; fh=irtNFfZPV2VvIw76GN3Df2b2IiTM6v8vAP+H4s2LJBw=; b=SNVvriOeQWSBp/CRH9UTukPsYLt6k118UEAoS7TdBj6SXOyQdc1t1u/OQjbG3zlaM5 l0OHO7qhUUEec89sDPhJEXCTENCb8lTYc3DoPCvRExuBMQLCQuplCIlg0Bnm6Z1akau7 Jv3PC/5YlCxLkdOfgo3KLUL1SVkYCMlwlMz6OB0imwihobAu5WyEBiCJ2Tw4+CT1XK2j gMgtG5ZQKXJIcLYlSjzEk4I3eWwBxOvH9ry/VWQoKt8pQUWv+2mgKn1Csf/C0RXukwxE xyVhJTW7ypntR/1wHo1RqoXygVuFhbX0f7ygJcWGq/MaJ/cogCl5QFedqbwxUKdzpNqd msbA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=C0uB5cDT; 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-49712-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49712-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCXKiZzgDOo8GjPHaaQazKyak6Lcho5rYXLCiBPaGpxSplPeZcAG/NJajxaH3rKzd5j+mIfViPGmEO/Nq37gTKhFtETe+A== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id i15-20020a63584f000000b005dbd4cf4466si1433081pgm.122.2024.02.02.03.02.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 03:02:38 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49712-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=C0uB5cDT; 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-49712-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49712-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 59465292288 for ; Fri, 2 Feb 2024 10:58:23 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BAC2A1419A2; Fri, 2 Feb 2024 10:56:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="C0uB5cDT" 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 86319140785 for ; Fri, 2 Feb 2024 10:56:07 +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=1706871369; cv=none; b=BoxyjcgDJL1AXJnNWatKw8wLnG9WjmCl6qYt+oZCpytCH1ecYtgx4uSKWIX0qt5GlPXeQlrGgAktcu3LUneI4CAF2I+izKtiSIXlux73kjcumjk3kJgbgXHyllZf8AE1aseP3anCDfxEQm9G/kc/ZWvGDIulj1HyFW37n7DFcIw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871369; c=relaxed/simple; bh=ckP4VcTWLY1vkut07zfIb8pSktRGGroqoRVYR3TM6VM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YacqpNhu7wkBz+hNbl7+yyt/+LDcxb22YfDru4dk/cMBURG7fRE5nr4dtZwtX9K/mH6lEG9W/gbVdJogKU9nYq7arx19Gxx4uLJNIuNfps0Vm3uOGSZAhgwt51d5yUW6Rxpkb6Gx0KaSzxueKGDLSP36bXC0ewOFwzaqfxMTXnQ= 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=C0uB5cDT; 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-603cbb4f06dso37070747b3.3 for ; Fri, 02 Feb 2024 02:56:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871366; x=1707476166; 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=hwQz9+kg606GttZk5ufJHJgW1rtd9e3JGMr5cW0AGC8=; b=C0uB5cDTWm2ZgIHOu4JMmynHSnhaEVOt5LxODNEH6BW3WB9MuIiP31Zc+L/0oJk/VU mIVkNKuUR5RQzAvmzwHK9cm7TSzz4dGE8oR2zUw5RLW3ntNmAbp9S4VP+La4xfv7ieMC A8gt1yvPqMKqUgeqlwbCZXPoWzEMD4GJ3qJDveeKBQJ4fxLfDAXWrnxUPovMlpNO08uM Cb5GHOeYaowG5NypPTFaKv203WuAA7FVtHe2kLHcEgFviHRYR9aMx2coTBxZXVBQFYG8 ZB9nehQICigWDdu9suxwEyLiuqQovH7Z/zCYovTybmPjIZizYNr5uhfmYNMf+PeZ+z1n b8/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871366; x=1707476166; 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=hwQz9+kg606GttZk5ufJHJgW1rtd9e3JGMr5cW0AGC8=; b=WqE5mrfM7RFcGBHHNpLw/t9Dg3QWtLnZm0/PmE0k6CsVl9zvZ8jhWNTVfcQuQmzHV1 3K0zQF/ha1ESxaSjv9yukdzP9O6mT9QHevtxuB70JQeNkH3JTmgranoSM+L6TyEoHETY kiAPcW43CA4ITuLtKm16GjMCe7HUstOYk5sIOuiUtSyoDszE/iswKb22ibQt9NJ3tWVI F65AgPRIUUiomRyBoxOQu9HYDrRFI3i7Bydxm9EZIyDtda2qHLXCfeuDgjcXXXByovOH qLMOby6ZEcCuh8pJ3Q1KpcOS1oWMRl/W53lA5cDwF1Xksbp9bkwjrZP750oBfPnOBwSC AbrQ== X-Gm-Message-State: AOJu0YyenCMYI7FrIsytMVGJCU51w24XAosTyK3lpkan8gTYsJOVxtL0 2ybno4DN6Z4nrYCkraQRk95lNrwyC93l6ij9tkXccgbz1qbD44za+spnmjCBGx4BiA47+UGsozp 0n5K0HPA7+FHaSg== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a81:7905:0:b0:604:1dc3:122c with SMTP id u5-20020a817905000000b006041dc3122cmr980062ywc.5.1706871366353; Fri, 02 Feb 2024 02:56:06 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:41 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7944; i=aliceryhl@google.com; h=from:subject:message-id; bh=ckP4VcTWLY1vkut07zfIb8pSktRGGroqoRVYR3TM6VM=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJZ/XE8S05EXGfpUiuaCzlMjesUC2ggCLEA w2FnJkMZ+eJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RqqcEAChQ+pN8RIm1l+be6QscJCR4mIR93Y84zjg8C+iyPSRL6wgKOHbeXRXEiIw8Ddgb+XZ6W2 JUicZJiBYWWqYzT/7waYhBHR++87ZB7Fwk19ksty2D0BOJ6hIxYfqZLafKU6se7tVtfFw2kmMR0 KYPgEGmoWewD/d5rnvASKPZeOL5kuSidBqzTbB+xgUPp0skdf2nyOTzU93K8ck0vTDLzp47v+uV fTQvYlGwBEdS0ugFwdBP2Dsx0qdNY0UG5+oFOIPqw7x0Krr5Ph2Wk2hOVyzzK0K5LdNSMBRM3a2 D7tNU0t8VbjUmyPUXmUsEGL2RIh3L8AApYQiCy1qhqwLvFZRWnDQlVe+Rvvlob+RbvZE0wqzAjE PIuEJDYVUFYTCcEkmy2wE18gbEC0Ws2B7nVbf2C73Y3RDHQ7r4HOlir6XWGAWkaqxRGIFlQI+hk kmlIs8aWyq/R+h1E+6S3psBp9phnDiV5ALPNqw3cgC3zvOlpUGTsWhfAkTxd3X8wFtr2qRIb4P9 xi0fNEBgRxTZoewcV64AZOrvXNu0BmgGTdbnrv50ragr3nmIe9VKq/9X1Tr9HWv+8E+XsUXYp7u TT8+Eq8z2wf0hRcC12ZTNRbBpp10my+vtCLDZvZto59DB0cyFTtX+VYMb9dwYaWpGoBZGxr9UED O7wMh+D7A2+0Dvg== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-7-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784761826033391 X-GMAIL-MSGID: 1789784761826033391 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 Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 45 +++++++++++++++++++++ rust/kernel/cred.rs | 5 ++- rust/kernel/task.rs | 69 +++++++++++++++++++++++++++++++++ 4 files changed, 118 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 0640356a8c29..b80276d68247 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -8,6 +8,7 @@ use crate::{ bindings, + task::Kuid, types::{AlwaysRefCounted, Opaque}, }; @@ -57,11 +58,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..7d59cf69ea8a 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,34 @@ 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 { + let current = Task::current_raw(); + // SAFETY: Calling `task_active_pid_ns` with the current task is always safe. + let namespace = unsafe { bindings::task_active_pid_ns(current) }; + // SAFETY: We know that `self.0.get()` is valid by the type invariant, and the namespace + // pointer is not dangling since it points at this task's namespace. + unsafe { bindings::task_tgid_nr_ns(self.0.get(), namespace) } + } + /// 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 +201,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 2 10:55:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195820 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp364137dyc; Fri, 2 Feb 2024 03:36:51 -0800 (PST) X-Google-Smtp-Source: AGHT+IHXpI46twAR91grBMjD4R0scbLDRM/UYU4LDVCIi5cUlX3E/EBbRaeSsykVU6XsKIBgWpEe X-Received: by 2002:a05:6e02:103:b0:363:9343:cc18 with SMTP id t3-20020a056e02010300b003639343cc18mr5031920ilm.31.1706873811121; Fri, 02 Feb 2024 03:36:51 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706873811; cv=pass; d=google.com; s=arc-20160816; b=f6VJLvuM1LqGYIIObHHklxRFR8xJqz8q6nAegk7qbZmskNlbAFLyS0FR6/SCOiXO4n 9z3JaNiItDqp4kyoC69Qo5bncGkwCf7idiixCx8ZtGiVlAtQI+cRvP0YOg30asU0EAdh UoEEK7xvR3JPlz7N7lZULLteWSREj7CTGChXAW8qfy9X62qYDXTCBLqGT6ZijlQh0nzO cuMPSuSalHVQLtf3wNd+An23yiJRO++mtO4o8RU789hKXIyfoNvNsLdLy07xHZJgQvpZ opbdSpGYELkejKwI2g+cUNqoGHGjA364zkPd5uuTvzY2MCEHFTBjNzw4PoMMXK4uN2Bo Ue+w== 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=V7OJTEzfCPkXm3kKAnpxteFoSUxuxzJgtxMaImG0Qms=; fh=tOXrLDNf49NTBWVb4pQFguIHJq9iwSP/0B3Y8/YUx70=; b=f6OWn5AbloPpgkcCslxTyuYVqSqnI5+NY4updk4SMYcZ9zf7pI+edndE5WCjRW08Ck /ymIC+5gxOEz3o/Dra/RDHxc+d3m+R11sSq8aJqU8z2bBBIwWc0gYZBUcF/V3+M6EDp3 S0IvCk9WjwIbf9ONr6BPtd3Y4vrtbU3JhHMwPxW4rHLF+GHeBq3BplbUTKd3tM6clNbl eR94aoEu9XSC/y8Ad19wihi2tIQY+EMlYj4mwVBt7DWTntop8kUak7M32DWlUMWt6I0u jS2B/4G+F/xYNq38FmqmK6cW1xzygTd/CKJicXPw2E+93Q92D6gGQX80eabVPzou1oCq rnzQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=yq5LugfC; 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-49713-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49713-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCWjRdICT+CTey16ZPe4Lq5ac7YH7Jg/ir4fEB0y+iaFwhxzGG0ipZPr6xkB9EHKyZk4j8cTbcMTGVQacwp9lfICGeDdew== Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id o3-20020a634103000000b005d70736760asi1430832pga.870.2024.02.02.03.36.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 03:36:51 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49713-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=yq5LugfC; 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-49713-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49713-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 60FFFB2A038 for ; Fri, 2 Feb 2024 10:59:09 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CF6CB1420C5; Fri, 2 Feb 2024 10:56:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="yq5LugfC" 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 E0AC1140787 for ; Fri, 2 Feb 2024 10:56: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=1706871373; cv=none; b=bZZlnO8Mgk0bD9F5S9aiz3fk/LWB/4y3QeBddMH5qnWh86PODUYe9y30u522XhI2oSFGNGLy+AJWAYxIu2wd061ZvD04Xr6SwWaqRFQc7VatIM7q76TMcTC/vK79UJI4uHMVnpiCUigLilFOw8xHdh54vVpenXxA0oAQTWfeVZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871373; c=relaxed/simple; bh=LqQ8OwVxbPzdUo+kW5koCQz+OcHsDol7M6Fn5Cd5nIc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=X+WjofrVw8e8vjG5YqzldoSUVxeaB3lZs7L/g9A+1vWqFEINh6bIbfTav4hN/vidUrMD9QReIvIdK8O43GKalrURPrPyOtDCyBzT9w64x3M0EsF3VsciRmq8IliEj9DmnZSwcCpX5FW8CHP//6k3Gat2vWvo1J/rOlUyrP/YaAw= 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=yq5LugfC; 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-51117158dd8so1718899e87.3 for ; Fri, 02 Feb 2024 02:56:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871369; x=1707476169; 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=V7OJTEzfCPkXm3kKAnpxteFoSUxuxzJgtxMaImG0Qms=; b=yq5LugfCIHQoAQC5LRupsMt8csMYLmTSoj78FqqPMnY7l2lhNqTU849fJPR4LSdc9g dfQhSKRY8yjjEgJu2ot+YFS2TIeLkvGJ1Dj0MPvIRCI30h8AJbC2ygPbj/O//9dK77aL a5NdndxgQpa+i7k67ed0CmDTb8bsUmmbdxhBE8k5udTw9C5IN9ZrIZ6NKovT6PtpsMdP j4VEcexQaPx8taK6COS0D+ZT9iwQk9FUXnxjlcaX6nFR/npIJ964k9Rkk09PIru8tvya ErrZXnibXVzT1gtkGUMVoy1q/NP4JIY4RMBHgNZ51u95ZbOmoOTKnpIMFWPc4YmvwjSS e4wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871369; x=1707476169; 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=V7OJTEzfCPkXm3kKAnpxteFoSUxuxzJgtxMaImG0Qms=; b=RM16K4401ErvqSJHz2pXx/zmPbhidTrWNsr1jzN8OBrkSBOjlc2INZUX+LiQku+oec 1xQtJF6mDTHNxTuVqRd9p7U+IcTZPeF9NAc+ROyWX7X7IvuJ/nR6wTuyzFkBfWVmVqwv qYCjJQkg0TZxhDi05S0smnHVDayGghID4v6Sb4uKSjtaiemztbtrEjpxNYcxV9+e0vkd PpAFYmQ4OpFgeQu3BIOC4HzVrU2iLDpwbcdULoyqW57XoxLkC3f9Jd8d2yXMjN1DiHdg sPv7LoxHNdz+NR+vrRH9xXIw0uE2mMlGl6yCuVgzOe7cyFJeh7LobuoEEH1m9eZRVDVy ASrQ== X-Gm-Message-State: AOJu0YyrfTFi+sXC+Op96/ksXoMi5ML8E59PZaNIdzuq2uneM8vpwI/h oQ+KpRxc0iqlKP51ZJQl59BKLbf1WXCDP9L8RuQa2zgaxLpiojpgdGz/dogKAa1dH+4gxKz9V0K dQmZklI7EJwwhMw== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6512:368d:b0:511:1c91:268 with SMTP id d13-20020a056512368d00b005111c910268mr6391lfs.0.1706871369140; Fri, 02 Feb 2024 02:56:09 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:42 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=14091; i=aliceryhl@google.com; h=from:subject:message-id; bh=LqQ8OwVxbPzdUo+kW5koCQz+OcHsDol7M6Fn5Cd5nIc=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJO6KBh5YtYnqNShkLgwJE3tMy6AH4i0YjI lWYfgu+5YuJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RuoNEAChUCKS58KFezVriwOkb55q37x1VRoxUOixTV7Bik5/BUQTGEhzyMGqZ5TFq0NwLDh8aW+ I4X0vFzqV3dOD66lrSs7oXghQX2cEu9FZvaJHC0lfOgeWxQcTw9npoXorq6Mv2xWBkqFqCidmxa HeH/XhxR7F9vcJtOxXWlKl5XW1EFtTiAdOiVa3NvMsSX4pwzUui3H2BAeumrcS5H37aKvVwsnf+ fH2yyv+Tl8IRW6W8+s7PX2U0ZLNlT6pt7abrMiVtPPj4XeuhNFnVSEir9vELjSICDuFRFJNqwZ1 DXBW5N1o/tcVC7bSKVSpYYmUqkQUgW6hPn7sz6Per759+832a+GdfhGLxqF20hZ2RbkbzIu10qQ sn6I85HxxvUHeDpcBwrxv/GdSZYL/gPgSAj/FQnbvkqf9DyTpEBHNLKGNMNaw9QZYZQiS4AM2pL eG/Fta9DYPiNonOqrsP98lFApmR7XpkIfzNsuNxiUtwmlcftZjJCIBwzSj8A16c2XH1FIWFeCES 9DqdUQIMgQK0o8ozhtcWrrRl+SsbaIJGExwYQa0Hzdxt+ZgV1y/T3vQ8r3MC5yJkkW4S5si4i7c Vgl8NjyrOv2WksDWQkm8sEw8k4bJPwxV1RoIcjWHxu5BbfREa0AsB6ge/8ZhdBYLlvu9lKU2XKp dN5GkK+WXgZymPg== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-8-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789786913447565560 X-GMAIL-MSGID: 1789786913447565560 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. Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo --- 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 2004270a661c..e7628c574b57 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 { @@ -313,6 +314,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 7d59cf69ea8a..438e467fb145 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -145,6 +145,12 @@ pub unsafe fn current() -> impl Deref { } } + /// 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 @@ -192,6 +198,14 @@ pub fn pid_in_current_ns(&self) -> Pid { unsafe { bindings::task_tgid_nr_ns(self.0.get(), namespace) } } + /// 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 2 10:55:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195804 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp347918dyc; Fri, 2 Feb 2024 03:03:11 -0800 (PST) X-Google-Smtp-Source: AGHT+IEVytlalukAgoyjNWnKfdY07O/F27JopTqItXIqaNXfcYnyAQJUaynD4L2iThn8Vsz3GxIk X-Received: by 2002:a05:6870:7095:b0:206:daf8:4ac7 with SMTP id v21-20020a056870709500b00206daf84ac7mr8945241oae.6.1706871790789; Fri, 02 Feb 2024 03:03:10 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871790; cv=pass; d=google.com; s=arc-20160816; b=xZnmvTxJVD3TELtvO9RNRS0F21YD4qMma2LMNPnTeCPCM/zn5VfOnhYUrbuvXUeiQk 4o5RbZ1AFUzXcxOuGR2hPVFSl7wfLd1mQ1cRcgCGyf+Bm4i1qiw4Dt2aFi1vZO2funDh /XZePCrtIaqSjn8eG1KJQME4fmdFb1Aq5Jje4Ni6xOSVxI24kfriuLafluwqEg36oeRP SD5xKXZwMij+D9QPLUFSo7xU5jgaptoqfiXnqFfdRGS6xqcywfgz1plQpqowA5cJPuI9 kAZGDTK4VEVqc0BWR3uCmLzagNytMlg50n0fhEVmk9BDdpCZ1d/YWeRT7RTDsiqm7+Co UI4Q== 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=/T3POnWw3qzAjUziQFt05EJyPrMhtND82GObaMSRXeI=; fh=LvKWspDqAy7MwQpjfdzaWY07GJckSilPUdqKffBvXBQ=; b=sow9UWyKnDviqTAnDuaKAKOKduRdogM77UiI7YDDBiSXUjCpDKkazBSMxDCE3iHch/ EWuSpRJvee+8KwVhbaCTKw+qqY4pA9b95n3b2ipVyiwvl4ncPhXhhtC3foZ9RtsLaZbB AcsBjI4uMdq5Zvj7HQ29ZmwHizOJV/ZYM+Mh7oD1Id68LwvoGBgKkFWaM4CvHjcdW+16 jj/l8zSXXoa7AGpjhJ3aU9lyzk/+DEb6f2IxUjUDRH0g17T5x3M2aNlnMfovLdvyq3p3 64/scwZLWBZ1UHzSfbTlRi7DVQ5zyFFknA+joJrOB/2jPD7UcZnzIfQQwe9R+W+9hk1g 6qTg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=oDgxrgn2; 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-49714-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49714-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCUnLytlRM4tANs9w8QvniUeYiEr6ZuzCB7KHp1tBnfKP7b0Fz/HDyNdwiPyswS+C/z5LRbBv0Eg8PAJmXHEOkN30BRdJw== Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id t25-20020a656099000000b005d8b6e93993si1424242pgu.22.2024.02.02.03.03.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 03:03:10 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49714-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=oDgxrgn2; 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-49714-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49714-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 A25362956C4 for ; Fri, 2 Feb 2024 10:59:14 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 57DFE1420D0; Fri, 2 Feb 2024 10:56:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="oDgxrgn2" 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 4C4BC1419A8 for ; Fri, 2 Feb 2024 10:56:14 +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=1706871376; cv=none; b=JBFuIZFIcg3IrmNS7VoGEJ/CVpUp6QcfMoMKQ6BPjAtJFonmptlGw45wxHrsxe+N6a/qiu5tToaAbZ1ta1aqk4xSEMpEqfOvNDlsRQhBaMqixEhGqMPdSZpeAOE6GpPcTTq62b63VU2xRbmr7QuHAbVxfZrqhrMDofM8+cTGJm0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871376; c=relaxed/simple; bh=/9E8jl2L0BIX668zHWJR7ToHHbaSj1Hq8IfbP9A+fIg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=pV77fANkS+PzBwFw/+ekK2sKKBd5I4XopT9DvlAI2RA4iRK8GMC+/tSsK7VLObyi0zzAeXdHx4F5+o82wQyA4CglNtq4XyPuYcrJ0ME4Bvchy1CV2fS+Y28QMKwbDp37WO60gRuBTGAl2ilij6Kc0w+pfgPMXqvqunnocn1yaQc= 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=oDgxrgn2; 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-50e91f9d422so2207029e87.2 for ; Fri, 02 Feb 2024 02:56:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871372; x=1707476172; 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=/T3POnWw3qzAjUziQFt05EJyPrMhtND82GObaMSRXeI=; b=oDgxrgn2Oiu7po0wHn4a+p4ke9dei6b/0am+R/LY3cUQlngRKQYnjcDC8Hp7R/3nIM yLSwHIZx7BunaHUGQ66lOmxafX2OUj4nGTHiz3DO9T/EeQYC2rdbYEEHc91NdJ20TfTr UBcNRQ5LSpjAn8tEBe9PeCivkoZ3YP4q8l9vzJkvrEIZi8eT0hxyNuX03fGRQ5mJYK8W VraW3qqS1o6bgDwUZbMlYzQ/Xhf3a60knR8trVk2dyPafXWJ575yzbRPVlfCP6FH0I3h sVxIcZqkv9I9xz4PirmXIF7kgdDzE4nqFvW42D/SIsvQJrjIMKH9ayaQqwixUhQTIZt+ E+fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871372; x=1707476172; 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=/T3POnWw3qzAjUziQFt05EJyPrMhtND82GObaMSRXeI=; b=edIC42PcFoa3J0TnMq5IxJrQiNE2KTsFDBU6EtKPmmCP5BtG2EjdQJP2P0B/EVyjNV NoFtSUimOV3Ph+UOohoPLdvm99ttMZ3wHv1TO23Jxu7iIcb+vgp+tpyszoXm4RFyN/B4 UEdQDjHs1EkVv5psVUZfQCHhXhk4nAMosck0OHOTtoP7WK3zinWE8w+3OVxsbybYRngJ qSSBzrTXynfnQRtlPyf2BveykhYTgTUC4fmewBnZP74o6bEgHBBfaNgVFV8DfJ+90+Va RwOPV8+8Sqv7THuomgLn4n5D0zaIQnhnJLlcpl4cuQbjdI1Dmgr5cCK8Qd65U1NKRiI2 OOBw== X-Gm-Message-State: AOJu0YzXMa5f68BSA9N2fuLAWIprYpT5/GVoiJhPvNt5iSJi/Qk4zMWq Ju01Ry+VOiIviNCgf0RLBgA3hTLADAJQp//byoArKu//BaguqrNVo4+A80W5GlUQjQEvF/8IZOG C6J8rT5bRlQrQSA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6512:3451:b0:511:b40:8202 with SMTP id j17-20020a056512345100b005110b408202mr1955lfr.13.1706871371849; Fri, 02 Feb 2024 02:56:11 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:43 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7079; i=aliceryhl@google.com; h=from:subject:message-id; bh=/9E8jl2L0BIX668zHWJR7ToHHbaSj1Hq8IfbP9A+fIg=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJeoAg3CjA+Q8HoANiJqIfHhAzETLQqjC3A qx9NpkZ3AmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RlXoD/sGN5Q4XsAlugRqT0Wr/qujcbxi+PwWXhHAB2Om5c2Jh4e00/uxSkhy1Hf4OIVlqG8aigU Ajb+uW7ABF4dCChXejn/wWF5tJ5mn5DrVL/buuyXdsfSPaolQukZEjFN9FU+Bs7dOgCMvJXIK+V 1gVwbxEg1jpJTso8gfhl9XV2/BSSdmINBdNmTafSuvCAtD/TIPAq4+JBXzK4xsfqNx7SXLArmCX WTnUy5BVZNSzk6bPNK5vyWNSmEC83ZBCkF0u/8gCtS8nJtMONJIozFMqO/XEMmbL8RQDwottXFp N+Cv7Lwv3yFWXLSB4CYWITqntU119Ck/Z9R3hT5r7cSQO6Fjh9c0lnLDNMGUVmHlOjuynpDsba/ F9rO9YQQMyBqnSeVbPa0tD3kOVVPfdsfb9ni5R+nIEeL7ru0XOmA2KbWg5JMSK2Q1Rfz3WdAzWw yQXKkEwJWkLKrk89xLiP3pFhrjXB4II1Odk44sFxoeVgjQIJU+DCH75GGeCDQ7LX083MII7D78r gXjUJeWbCbxbwDWqnrTMTKQReUwzpLts51b7vV/cZVG6XE25kyHSlso0Oi2LSXjJlQTZy4aWkNS A6RJ+zsustodt8E4lBs9Q0cpXutnd1EZgNjgy5uRYpDkLcTpCzoSwdNWphWBVdIDV4LqTkehaXn SXwLTwkCDJmFXCQ== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-9-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784794752665760 X-GMAIL-MSGID: 1789784794752665760 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. Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo --- rust/bindings/bindings_helper.h | 1 + rust/kernel/sync.rs | 1 + rust/kernel/sync/poll.rs | 117 ++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 rust/kernel/sync/poll.rs 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() }; + } +}