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) {