From patchwork Thu Jan 18 14:36: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: 189226 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp383712dyb; Thu, 18 Jan 2024 06:38:14 -0800 (PST) X-Google-Smtp-Source: AGHT+IHWE4ANhN3uXBREJprNCmQHVk/sLh8wgqJYs+DefzyhgGlsxNmUbCJYNt16Pe0C+6ADqe2P X-Received: by 2002:a17:906:2dc6:b0:a2e:acd2:4434 with SMTP id h6-20020a1709062dc600b00a2eacd24434mr551589eji.70.1705588694724; Thu, 18 Jan 2024 06:38:14 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588694; cv=pass; d=google.com; s=arc-20160816; b=fCCAbj/cMtdurBwAHmmpHRY1Ih9oqyM7BnDks03XE+n3kPL/ajirh/BtM92eskqKT0 fBw7u5KJAdqIAr1R01u3CipJAeULNsMi2DE+SG/LQr+rxreTMwZMrpSmPJsfsmuLCCLY ZS5YGpWC9r4rW+l8HtIEvmY6h2eXWVMxM8QpcBj0MsHafE5x9mNNEmGTKIfX/FODazjy RHxfy1BYB/LLPKBxwd55gERjRqoxrRDiwGiE0vLD+OEa7w01hcoL/LtLfO7b1g2/1Ehr e97N+B6QULJf9avWlMtWUWG0z5W2aHCf2C7F1Er/sIRmRUdMdOZaPo3asHbegFlttW3d VBMg== 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=+NXIaUJ6bzXLcyHJp4GAelDzBqPJ0TPlQ78FrxfcfpQ=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=n3jzDCohLhKI1S3x80tUmyPqAEa/P5TmG+KDxaiWHymyyO209U0qW0PCdhTzH4wJUG 3B99qUVae06lr9AIWrqUzCOePWW5jT14YQ2j5xJKqN9uyY2TpqW5sNVVrRNB2aYYDRg5 tXOfKCjG/jF2RRHFSVNA9+7t62NpG3i6r28csR/ZXGZZ/isBuvSP1fVGw9heY0aEISQA m9sqw8Zg4xR4NVNg0P6HSJrm3BgV167u/s40ZO8Wg4nAw7NyUPZdq8Dp5Ibd3PQwjNi7 YhS0AslTlx4FzzzgyzYSF1eShDdB5hgml/4xGu4kieP0jrRyukbc1GuZPHn3UH2UEBOT UgJg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=4Lv7VDUJ; 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-30202-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30202-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id i14-20020a1709061cce00b00a26db9496d5si6546280ejh.545.2024.01.18.06.38.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:38:14 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30202-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=4Lv7VDUJ; 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-30202-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30202-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 316A31F21F1A for ; Thu, 18 Jan 2024 14:38:14 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F2E002C195; Thu, 18 Jan 2024 14:37:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="4Lv7VDUJ" Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3FDA61DFCE for ; Thu, 18 Jan 2024 14:36:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588619; cv=none; b=rMCMRfNaf+zW5iq/2fVhC+HL77J1bPHgoDEdHUT8wmEpqntrdT1KIp2zz3B0XFLqifEyeZJLUOi45S8QOEb6KOJeLKdvF8zywuUPNpQIyrouH5UTG56slA7QhjXWjPgDtYWvwqC5tN/F1MKQ6kX9irTQkSD94ybrfSf0vgIYHZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588619; c=relaxed/simple; bh=pFxh9FlVYPnH4EfOhnbf41ot3VvVE0gACf9YM10uw9M=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=GvaFxzlml+kXymKrEN2jAxWYuqOWu+EoXhidbi5GC0/0IE3I04R+O6jIDm/PJ6LmiO35zR557P/9kOL+FXnIsvS0ZHGNGsosDpLN0I+uO2zdq7Gn92Aqx2tJOHBDcxYrTEvQroU5zKlX9PTKDZyJc232kC7ktexYI1JAPXxHDKY= 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=4Lv7VDUJ; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dc2284779caso4037983276.0 for ; Thu, 18 Jan 2024 06:36:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588615; x=1706193415; 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=+NXIaUJ6bzXLcyHJp4GAelDzBqPJ0TPlQ78FrxfcfpQ=; b=4Lv7VDUJdnBdHPU5nKPXrMqvD8cJcwhClVGXG/wRfalnMSkFWnC++O+xGPCao/2GdT swPCPT7dX/yFvjJuoO9hYHjAwvflULS7sDR7Q3NQUG7Osyy49wXk4+cuRHARqts6NPiz /Fpn6Ckz/Olngf3kI3+G7L0wpjJIcr/YtyFMQ0uWN5SccqDnJ3PPzAdNtYwtSYu0k/Mu mLEN+Is00vQbuCOimrdNQ+1X++SfBqQ6Gmvxh4/Ljzq6M0K8u1bv1OS9T9pgQga9Lobf Tc/ZFykTA90Tx3q943LjwjjusAp6HebNBT5Hnn6Jx8OJuye6YNC2Yb3pNAou5eyFk93X m9vQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588615; x=1706193415; 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=+NXIaUJ6bzXLcyHJp4GAelDzBqPJ0TPlQ78FrxfcfpQ=; b=dzVmWcX+xbI+moaGJpWSPIXPF7FlLDE/ZyeGX84vBK0gxTXzdpjDfrNtJBFEE6vpp7 mU2vi0MneofmFIWpz15YMKZUh3oHfHBjzxFE5RwxRvmpCrL7vjV2tSgOoOi21rhHbk46 fEXa9AKB2OcVBeKVSC+zw/U1GhL9Jjg/bJpSC+t1gIBopv+Iqkszg9kWhih3UFHTnYWK V/c1cYFbKXijxTG9GN+cLW5GL4j6DfQC5BFgaF9qELggnjuEY/a3z6IRQYfTg5w7mAlV NahwVwQJCk9XriDF7ZoRwno1ztVyXiRB6RFJZUm58hW8MHmzAIavS/LVq18sgWMwKDWa 5XQw== X-Gm-Message-State: AOJu0YzzldsoPU3DKEb04qEDdkb9SKi3lDADCkuq3tarya7O/kauAR86 c1uMydt6eUMk4hLU4PtY4NTe2WdeS63EAaDy9QHOewJ+TWoUEp9ITYJVzQOh44/muL8yr/CHz0+ luF8EHCdhMwW9bw== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a25:188a:0:b0:dbd:42d:c8da with SMTP id 132-20020a25188a000000b00dbd042dc8damr43200yby.3.1705588615161; Thu, 18 Jan 2024 06:36:55 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:42 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=16048; i=aliceryhl@google.com; h=from:subject; bh=yX/ZwkgYzbxxLvkuqXDUvn3cJQoE1c7p99e10I71Jao=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPOVGDxqasUhx7PTdkjD1XpJie2dlFb6FqC F99M5ww5cSJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 Rpn/EACAeTr1AnLN3E0wZkpgK1w3U9Xa0ImdmK8qdpA5LygvD+khh31EY86Nye7L/ZsFKEuU08U pwlkGX3ICkxKYYPYgROlqbsQmhBfnlqFcNwYCw1Nx8mw2OnMN7FhKaiSe9wAWnYekcbiVX6r6Lk 3N0DdqY2h8sv/W42ERCNAo/vGsSEBQnHTF5ngjBfUB/5V0dHcYlGWJxOoSyeoFquLANBvuQzD9q xOjpQyWQCM7QobWS+8VmDfx+PxbGGLfuIhz+gq1G4usq1PEhVmjVfgqy2f3DlIgiB/wFOmqOU8Z xNHm9fh2IxNlki/6YItzXWhmkokebZqy4pRK2W3d7zJH4h0Qq/J5HbfZFCFY9e1YCm7t5T9RgiX MvPROe7BHPdU5RKur0lExGksboiOjd454CoJ3ZlMd5JbG9AcTzDgSUbtmBat6fBHMfuN05RDtEK c7GDZHRjIKr3UsTC5TF5aL7bKRkQd4KuUjAqRvvPxYudKprZPnG9/cjA6NHeJAt410gHw5luuJI WFR6Ja76f31y1Z1wQ7DhCrMzjeT5wJo+q3kwdCqFLUwn2ItXH15s/3YlRbEFI3005E0JYq4hdP/ 7ScgeyyASqt7yUoJN+uYJOVd2IxoJe7G95XlsG9MLazZQFGz/7CZwgTiaGNyziiN7YTKB2toWK+ 2RuGdQdx7dLTytA== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-1-9694b6f9580c@google.com> Subject: [PATCH v3 1/9] rust: file: add Rust abstraction for `struct file` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439371052701450 X-GMAIL-MSGID: 1788439371052701450 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 --- fs/file.c | 7 + rust/bindings/bindings_helper.h | 2 + rust/helpers.c | 7 + rust/kernel/file.rs | 251 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 5 files changed, 268 insertions(+) create mode 100644 rust/kernel/file.rs diff --git a/fs/file.c b/fs/file.c index 5fb0b146e79e..b69b2b1316f7 100644 --- a/fs/file.c +++ b/fs/file.c @@ -1101,18 +1101,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 b5714fb69fe3..ed06970d789a 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -8,6 +8,8 @@ #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..b7ded0cdd063 --- /dev/null +++ b/rust/kernel/file.rs @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Files and file descriptors. +//! +//! C headers: [`include/linux/fs.h`](../../../../include/linux/fs.h) and +//! [`include/linux/file.h`](../../../../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 there are no more light refcounts created from the fd that got +/// closed. +/// * A light refcount must be dropped before returning to userspace. +#[repr(transparent)] +pub struct File(Opaque); + +// SAFETY: By design, the only way to access a `File` is via an immutable reference or an `ARef`. +// This means that the only situation in which a `File` can be accessed mutably is when the +// refcount drops to zero and the destructor runs. It is safe for that to happen on any thread, so +// it is ok for this type to be `Send`. +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 e6aff80b521f..ce9abceab784 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 Thu Jan 18 14:36: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: 189234 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp385456dyb; Thu, 18 Jan 2024 06:41:30 -0800 (PST) X-Google-Smtp-Source: AGHT+IE+9mW4F5573bQhxVFfAy9a6uTmgDCijaCeEDuXY8hSBanVCX9Enrxt66b84dNj9PC2w9FQ X-Received: by 2002:a05:6359:639e:b0:175:77e8:6c31 with SMTP id sg30-20020a056359639e00b0017577e86c31mr763097rwb.42.1705588889843; Thu, 18 Jan 2024 06:41:29 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588889; cv=pass; d=google.com; s=arc-20160816; b=nBvOyt1VWeOzufFyI96jGc8zqofHQlFpFlNupHGLXFcGa6RnZnNq1ToS2aMhookhg6 PxTsj59HhpVEeLMUcBhzWIQ2QyAkoqh/d0ijBcYLVQ/eDqQPr6D0NU562eSarEuHix96 2wdBOwx7HNUQGMbpMZkPE8iPGPmNKxxl6a2dSC43tP8rp8GgeCQnI6eLsjpPtM/Wd9yM HpnA0bpucKdsRXQRZ1yx3x2I1TZhx8CG4sbOVgwHW58zOe+oBAmlGylKtm/V3DrzOzHu i25ha/Vyb4oYi+T8M1iEHRTosje3rWais4R0xUonYFXjxJokkYiNpy4BjjInQAmtg/My U9zw== 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=MPT3y0cclopsYFKSwknUSvd4eXQiBoVC6AuAC2YQuxc=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=LlMKt1p5DmkrZPt/aSy7Zvqxe7d6DMk3LQ847wlSIuhHc9KEpPwVxFbCS67KlmMSn4 fq96Sbr6ZBLo/NKTFW3sc62A0PGrRiqp/prXdJgpgWpBeAHRDz+GmzWx8CdcGuYwmvcB TVjFF14lxAAeW4MLbG60VJuaSrgJ9PsA+BxSTPsDA2d1zm8EpOlEcga9HLskjDSnnOuq +QM5KTipKIVxDUPIfrepPJSR/l0krMmQt7UYvpb4gFsr94WdfS2u0w9ZvzOOeMInyVFW wojMlCen+WkOaDULPQsKejhyCZfO9wmCpW1Be1OAYQKKsyf278QG/3gMCrqhm2FEQTR1 awAA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=HzzfvKRl; 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-30203-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30203-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id w6-20020a636206000000b005cdec4d997fsi1554495pgb.539.2024.01.18.06.41.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:41:29 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30203-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=HzzfvKRl; 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-30203-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30203-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 0E062B24679 for ; Thu, 18 Jan 2024 14:38:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 95E96631; Thu, 18 Jan 2024 14:37:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="HzzfvKRl" 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 C27DC28DA7 for ; Thu, 18 Jan 2024 14:36:59 +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=1705588621; cv=none; b=JyuEzWwTrMXoXXnYgfxpIKA7GH41i1I0rVS4yzDYEfQLDj1ex5pvJ/+iyK6DyE+siYDAhM+exH8+8sxLM4u/xoZSDmOXa2fpYL0iKAvSThPDTAAa30TEdHkG1TDcylZmsynHFeJtjhf2+4zwOEGk59PQG3s96iO4QDsY4HJ8C8s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588621; c=relaxed/simple; bh=MCMPThk4qCeVKqs9KplV/1i671aQDaqWF1Xo9etvmF4=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=Pd7gwudXkalvUDV5dMEvT9ZKMVhR7MEvnTJpHPuvVht4ai4moFWKehsUBF4JV/VjAMvo9YvLvkkTzYurIjT5vXtuUSTxSqYklasfWx3b9mPGHmNotS0mXcFjDCPxTqN+LSgB7w84vHiSq498NDaGXBXH8ib8nDh/yNeEBJ2mdcw= 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=HzzfvKRl; 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-50e69fc4574so9688771e87.3 for ; Thu, 18 Jan 2024 06:36:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588618; x=1706193418; 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=MPT3y0cclopsYFKSwknUSvd4eXQiBoVC6AuAC2YQuxc=; b=HzzfvKRlysr6kaZ/E/yu1nOcQOS5Al3n2CdWIRS9FQjapZLQwb4j+s79HLirhl8SgP fT/qtattMmQphNw4g3ZpXcNM2rvNzQ3Xnc2y+jj1tx1cs0JDjApk+XSLfrjx5fag/SRp oPb16iFuNHHO1Eou1fYk61OE/pphFq/XVMZUfSj3p+RCVy7uOC8bJvnQxLWa4tIxbHme Z6P6Mo8ybpWCoi3kcodnLL5hsIgJfjhDNdrYcTdD537Q/6qhnJzjRVOnV76OAJnzJtzX EgGIHcMX5koxIzGCPalOPGYm7jy1v2X2/RDMAAxiZuEUWevc/tLisMT1wRmDE42a/R0a 1PlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588618; x=1706193418; 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=MPT3y0cclopsYFKSwknUSvd4eXQiBoVC6AuAC2YQuxc=; b=HH/wYPprAOcYcoICCXYAfiryMOhS0Ft1102dNSiG7II7FwJV0HCDzPsjyKkaOozy1g L/H5scJr2lmR6AZAZMgP1bseXRKED/G0fJVxJTD393TcGvlDR9hLVpB/B93vD3lMLG9d ckJGcLrk4KPnenTRmEifJBGL3uhmAmwMTOCf77bleASAKmxi94KV30yq9h699BwpH5wI GxbjL/dV28EzxVQ1Ye9FbY2UL8ioWVZ2K1/lDjaWQaq8fue2p7b4t4tA1uUBC+F5G9// g2lEiFiBuRJAa2p0yaZCrpCQpHXt3l8aTKWcu7wBuOr0VXXqE6umRKLfiqFkIDXd4zJm vm8w== X-Gm-Message-State: AOJu0YyXuGy4Lec/KRIZUpbVRdO4z/PNSK6qjs6FX08KTqhJoowHXp4y pssQMze/47XTb3T/2aQq6TlaXVbJGaOIEtbF3+dDgFQQJpAtOKuJ7IfV0Xe/t8ObQVRJLFa6oG1 QSlSgifdIiE/4JQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:ac2:58d1:0:b0:50e:25d6:6d9b with SMTP id u17-20020ac258d1000000b0050e25d66d9bmr1971lfo.3.1705588617887; Thu, 18 Jan 2024 06:36:57 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:43 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=6615; i=aliceryhl@google.com; h=from:subject; bh=tCyuNgFn7TPQHklagxldT/6Bs98ZKp1WEpROGS6P6do=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPuDEa2yZ2CfHTWr2PsWx0sUDCwwoG2AdRK nuNDDGfgdaJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 RgGGD/4+t8eiDahntx4ytpXdbz1iSH4578O3lrGZw5WIjj70MLassPy0ZdUycwGerPd1lJ8dYhk yoT+AXbWRRKO/F/MdoG9XLIrZDP9Pt3140eBP82uRifD3bGTZCmvvz6wUp2daYsuTlarxLRKRib bqIKgCbXdipIs9gh6ZT3C6PuebKW2suobjzQpt9rDNjYQD9vHErj4Ww3b9jFGERBY6ZEB7Ay3by w/zZIt/zx9ABROQ21BWPHJygxfWp7oG2Rrg0CuFX26eqtOwbRO9Tn8jkXXtqTU6TxM9W1Q8pGmx r9cDxnMYvKRJ4TX/GqB33cVUrEfQWsBk6JJn5kiVh8CasT7LZVcfhK89BzXE4ez0dNuFyIJHg+F G1qf2dOrjfqGyfLIhxlnEyXG0L6k1VVMqtn+gDdQHHQeQIFuYsRojwuG+XAExwXHxy8bNB+3BbO JQKQbfRApvFnjIJ+IHEqRQ/Xyxyto3EB/KZ2TaEj25Jt5uq2iyq+Q3HMD+5AHAPUdtMzsrn188j tPO0WSyKZFsDhSAhe0J2nrTW56f/nlNK3B7cmBdkHemcAkwwzl3eslk6cS85rH42Qk2p5DMJx1S MHjdkG3W9z0WnJYE50aL0vRZvR/UrvuH9h1Gc7smL09a2xrZ9C+qYQ1A9BB4L9jVruVlgPjtHmv 8/QP1wNVpciQZAA== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-2-9694b6f9580c@google.com> Subject: [PATCH v3 2/9] rust: cred: add Rust abstraction for `struct cred` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439575799699662 X-GMAIL-MSGID: 1788439575799699662 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 --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 13 +++++++ rust/kernel/cred.rs | 65 +++++++++++++++++++++++++++++++++ rust/kernel/file.rs | 13 +++++++ rust/kernel/lib.rs | 1 + 5 files changed, 93 insertions(+) create mode 100644 rust/kernel/cred.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index ed06970d789a..fb7d4b0b0554 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..ccec77242dfd --- /dev/null +++ b/rust/kernel/cred.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Credentials management. +//! +//! C header: [`include/linux/cred.h`](../../../../include/linux/cred.h) +//! +//! Reference: + +use crate::{ + bindings, + types::{AlwaysRefCounted, Opaque}, +}; + +/// Wraps the kernel's `struct cred`. +/// +/// # 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`. +#[repr(transparent)] +pub struct Credential(Opaque); + +// SAFETY: By design, the only way to access a `Credential` is via an immutable reference or an +// `ARef`. This means that the only situation in which a `Credential` can be accessed mutably is +// when the refcount drops to zero and the destructor runs. It is safe for that to happen on any +// thread, so it is ok for this type to be `Send`. +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. + 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 b7ded0cdd063..a2ee9d82fc8c 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}, }; @@ -204,6 +205,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 ce9abceab784..097fe9bb93ed 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 Thu Jan 18 14:36:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189227 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp383983dyb; Thu, 18 Jan 2024 06:38:46 -0800 (PST) X-Google-Smtp-Source: AGHT+IFHVLbrDC8yLuia0W2CvOoyKTpDJ5hodiqNr2qHsVHvXcapnUbHmvoPSVi/TV8BYBDso4Ge X-Received: by 2002:aa7:9a0e:0:b0:6d9:bd4f:9212 with SMTP id w14-20020aa79a0e000000b006d9bd4f9212mr667830pfj.21.1705588726029; Thu, 18 Jan 2024 06:38:46 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588726; cv=pass; d=google.com; s=arc-20160816; b=qmWFwpkl/s7QEWYEGbM8h6KwEHM9+GmUmirPeXAJWhct8ql9pJkr80oEK0DVeYMqJo YaME3LSf+IGJPWC9fOlVULoRrRVYv9Hotmlf4MKfb67AV4x9ZBFBf07ZkB1S4Pmx93UR mwPmlo9FwB4TWpo+F26e5O7BYaqVOD6lwDT5gA8yyZCqbudhufl+yKUNkuCH5ReePq+d OsiS6qTW8q1DDZhCISxyi6nDKEQtpSiqxZiShJbuDmf8KVkDU7WyAadjLrxglIm9rjZO 2ViO6nDYdwNJU9ZSetrfvG3mwetkusVttnr3ZEbrRG4DnFIiRRDGs3vq+9QTMDeo+3TU lMDg== 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=jmgH0qa3XVbjpGQhdkp6BesDtjCOSEZUBkhyiBWTkXg=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=KzOtRGOD9Pr7A4wWPHGTv8KJ4iVmhqGZ0a43glOBroPiUSAi2MIjyCgVV5VRztoJav DN3xeJIwhueTYQbg5v9m1LiRNXmPk+Cs3S8CvEHdI3Nbrx8bFarvJORsZJdIfR6fECLL LxcaERyrqU1gkvJnGzJgrZLkA7cv25nsHwqSzUhreOQIOTBpqjfdjCqCendLPura3DvY dW3RsKP96wexNw0UuCQZUdJ/gohylfTVT4iTq+PMI1Gq28v+Gbf7XP4nAnFSwJIMjrYp RO8rW3uRewxhgQHO1qxI6ji4DS3NQfyBgaJwyv7jr6vnW4ezzm21eage1LpkJmK7vcOv TieA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=bYtXRFKX; 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-30204-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30204-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id e26-20020a65679a000000b005cf88b03757si1507352pgr.70.2024.01.18.06.38.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:38:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30204-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=bYtXRFKX; 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-30204-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30204-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 BC83328417B for ; Thu, 18 Jan 2024 14:38:45 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 078262C1B9; Thu, 18 Jan 2024 14:37:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bYtXRFKX" 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 E3E8728DC6 for ; Thu, 18 Jan 2024 14:37:01 +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=1705588625; cv=none; b=A1kYOiWKMOTggeES0Cug+tkCjxD7dX2uIMa+VBvK6lYlrZZ3sV4Zcy4UfT7WkMYmVcGIyOvMnnVlGEEI2b9HHAwd190Wl7spd8/FlOMJJLEtQUvJhglQQpFGuy2a6Y0F/EfekuG9bTwJHhdul8AF5wnhKH8nswW50ZnwGgODh5U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588625; c=relaxed/simple; bh=CsfuAls1TL2YV7CMFadTLsxtXkXtmg2JI5t9uRUkTZc=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=aE8UqiCOPln0ifR4g0ZdOA4EgflBXbP8+CE9WRTDB7esJdLkn/idaSJbWOLOSvYjpg0jojUSLO10lOosee2PLSPqSLlPgZO75MSmtO0e6r3rXVHqzXgygDmpZ2Dyp2MAZFbdVPvQJ57MiWvFms/i6keElS+GD0JaHWay8TbT+dM= 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=bYtXRFKX; 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-dc21b7f41a1so5207283276.2 for ; Thu, 18 Jan 2024 06:37:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588621; x=1706193421; 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=jmgH0qa3XVbjpGQhdkp6BesDtjCOSEZUBkhyiBWTkXg=; b=bYtXRFKX20WqqUNCOdLv5Q7Y/17bqb57fPhKDwLlTsgI34LY35PbHoUruVForWiowk eofZOhLD4xhjsNG63qJJjCx4i2p3elFlhoqE4Yao/RInjoeo6LJjv+TTIGThGzTsNRaa P96a7ew20nUND5yS2kcgv0ruHDzD/i4KO8kxS7ep1dNl+ww4c/FNQMabptsE3JAJxwxr xkjqW7VfxO62MFisgLAflhUfTgu3Q5WCfwj6PNDl5pmr5X8+JT/tS3SJMYqCq5JA9k7j OIETocJUxgEarAJbM4o67KJIS8k6XwB1mhH5qKHkpNXWyKaEBwGRsRnDGksd3yGn8JKm 6FMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588621; x=1706193421; 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=jmgH0qa3XVbjpGQhdkp6BesDtjCOSEZUBkhyiBWTkXg=; b=ivNtMKUv6oxRQDucpcMjT2jcdJ8KKFNLrGBVQNvv+cUjGx9gmdNhBlc7vmjVxJh67k cjAgNgGrrdg50YSpLVW3EVsOPGn2Q0ljyk9nHluZm3omESXVQXvg+fH/EBeG+4l9pPOd cQxK2PV3r5Zwy0YghhKBmTO75QJayGeDz2lg+3ql8h8ZWwk74IzREt3VrgnjYhSMFwpw 3KIv3Yi44941slFfe/4r0kz/YfkgbYKiFFUvHrT6mw1mnjVgIygWnHS3OogSj8o8N6P+ MfA38niMZhn4THd0tnsZ4Qtj2x+kxwwMch13/5bsTnITvk7SibYhCSN+7HhnezP7SrWV Hfyw== X-Gm-Message-State: AOJu0Yw6ob9tRXk/uOwUv3a2uqPRAyacQDNDd6JemOuSgv/OTPniRBsZ gwjpP3S6f3hArYt83NDRMr7G0yMWgMQno3VaxWwoFMgvq0S2g3Srb9M7Z/PJxDLi2X0Xm5PBqvQ 324AyMc4+8BAmyQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a25:d7cb:0:b0:dc2:4cca:7577 with SMTP id o194-20020a25d7cb000000b00dc24cca7577mr42715ybg.8.1705588620910; Thu, 18 Jan 2024 06:37:00 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:44 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=6255; i=aliceryhl@google.com; h=from:subject; bh=CsfuAls1TL2YV7CMFadTLsxtXkXtmg2JI5t9uRUkTZc=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPjVUL1zehP8gc1SMJfGp9FtGF+NYrfZ3D8 /AoIuEsBTyJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 Ro02D/9kTb/8CRLZRUrxFSKqM82brI9ojK0ut4bbufbYBgISSYjp0boAOwrdi+OADA/EKJioacU B77Grno1bpyVpGB7WkixKv7QAwQcZGBLLrKvVWe1oBKpBaRuztogNZte3dFMT2yh+i8aZfEIKj7 ixn0Km3PaEzkGYeMx925pyHL17H3LWgLDImSgTuorrnbxnDl0B9NlKHeMBihWFDwYBQQVmupw+Z 61+Q3pKi0aXK+w8AcVQjo06N/DLgCQSHlgc8K+8vq3ClFu9XaSmyTFXq8ktEo201F+x3pRUdtUe QQFii/m01ASttjeQWXfMG7WEw0t8CUVu8itN5TFqsjk/puZTEYZALPJshFJREtCeMnYYrsoFa3w asFMeQ7TywEAzRHbKaLF8IMwRJVEijCsr+pJdZABZDUgDyH90SIVsu86AwerEG7CdC+Ju0dJ5eZ DHT/V8Agt8PZ+Qyj/ScctUUEyogo8AhYOHe1d/T3Hu5wtt17mFhGrt5b23oJlduzqJrThcyz5oS XrMbFQyssebdKpmE8ajDgl5wLRyY+CZf4+LCOjOXd2pwCsDwaIxDl485d0Rpr9aRrXUWK6xgyLG Fp20oqVvA1cJ9WkfnqxN71VF3ULdKgQgAZXfuvF/4+ti/GcNzwxQkbSYXRdurIMb1Lp+f7836dG U7qBuzoDTrJAueA== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-3-9694b6f9580c@google.com> Subject: [PATCH v3 3/9] rust: security: add abstraction for secctx From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439403815546792 X-GMAIL-MSGID: 1788439403815546792 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. Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 21 ++++++++++ rust/kernel/cred.rs | 8 ++++ rust/kernel/lib.rs | 1 + rust/kernel/security.rs | 71 +++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 rust/kernel/security.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index fb7d4b0b0554..0e2a9b46459a 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -11,6 +11,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 ccec77242dfd..8017525cf329 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -43,6 +43,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. diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 097fe9bb93ed..342cb02c495a 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -42,6 +42,7 @@ pub mod kunit; 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..e3cbbab6405a --- /dev/null +++ b/rust/kernel/security.rs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Linux Security Modules (LSM). +//! +//! C header: [`include/linux/security.h`](../../../../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: 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 Thu Jan 18 14:36:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189228 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp384095dyb; Thu, 18 Jan 2024 06:39:00 -0800 (PST) X-Google-Smtp-Source: AGHT+IHL4RFi76CPVIL2cD2wVg1cPs3tEmPILIrAy6z1rrOL/Veffu09XDnUBv9Kl+s3nhVM9w6J X-Received: by 2002:a05:6a21:318c:b0:19a:fa8d:2067 with SMTP id za12-20020a056a21318c00b0019afa8d2067mr1101227pzb.18.1705588740508; Thu, 18 Jan 2024 06:39:00 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588740; cv=pass; d=google.com; s=arc-20160816; b=rrLROOgYFGGL/eRI6Mm0KVzawj03pUWg1fHUCnplhkppwBuGrPQ0zGf3Dx5fjjHFZ/ XNzcKjePxS9pzXu2kh9/BHyWaB/Y44yrMDY3uQdtFfnrNT9Z5/wNtTvaL8ADueWtx09Q kgGgnWzqqqGHFwQE4AaUZDQKG3aoS7pedGP3znOq8TWLPMRnH9GkbmFZKQN3tCQ70x4y c38XisCt3Uo/l7hCJPl1w/mbl1dgY/1J23o1g0hcFDRL7KqEJ3SClxCpS+SOlUhkUFXm YTjeBgCpzzO8Z4MOLeiNtF/fepwhIpZIbxyLiClVgjOkgdyBpY+aWxZqqFPvf41HkMCR NXGw== 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=U3ZIaTdIDVbGxgj61qLOgdlUIoPK1UIssk3iN71rz/s=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=xIPQnLVQAilvONznRsOhxyTbr/1gGXivN2p2M4g/1Ho9CSxxKyKKqMNvbrjTQ5W/vX 8StbvNpbSIdocme0c91DZhSlNvqqWeN3NrjH6bKJO8P644ZHs3SEDJH5g2ozo728eHvL /OjaWKlwrGr775zO8Xwtm/AxGGQPMNhosbT+BtnOJBboABwdaDjCMzeUc0V/OWMpgOe1 0Hh2fmpoh+zNJtYnYoGM1/AyKqFM2Fv4TxVV1kr4/yXFrhiuXrZ1uh4DtD9jn3Fs+CY5 xDLfmge6opJZxoCA456SRtxnK7GPFWjHWQT3wq41cAAZQvzyNFuFPDuRDQgxOQ7i3Wc0 aivg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=c28O7AC+; 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-30205-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30205-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id kp3-20020a056a00464300b006dadc44566bsi3996174pfb.58.2024.01.18.06.39.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:39:00 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30205-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=c28O7AC+; 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-30205-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30205-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 3C403288AB0 for ; Thu, 18 Jan 2024 14:39:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5BD832C6BC; Thu, 18 Jan 2024 14:37:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="c28O7AC+" 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 04F992C19B for ; Thu, 18 Jan 2024 14:37:04 +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=1705588626; cv=none; b=GaeTaEYsNVtyf8cHkrUSdJ+wKii4Cb0QhZY5a6uoiOUySq4RyrYnSTiQcyrcQ8JOLEnYSBL52H0uXCbcKRB2WtbcqJOGEZGoFkMvGskTRuIOj6UowCCAW1iKjhLiIGwbLVrO2kAprkGAjFnxbgiWdq0k7BGkIl1ItJddg82/QJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588626; c=relaxed/simple; bh=Sn4iv+1Sqmbmlo1CanL38VvE8Hbx2qZrDf9IB96IkL0=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=HVJ0zrrAkQGA1LNvfI564Z4cc/uZM8WmVGhopxnMJjaTATArWq30X4KYkpxBj8T//UbdHfsovU5eGqHOYo3NXf4k7opheTMGoCEZap/AD6XVCBbjuHDsJInBxJgVeCCybGfdRgrC24lMmgIj99TkAdrMusOmJlXW4Qi29A0erVc= 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=c28O7AC+; 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-dc21b7f41a1so5207341276.2 for ; Thu, 18 Jan 2024 06:37:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588624; x=1706193424; 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=U3ZIaTdIDVbGxgj61qLOgdlUIoPK1UIssk3iN71rz/s=; b=c28O7AC+fkiCThWEpL9kIIeCsbMYrzJNSca5yK9TeWdfCgM7QxmaqBkBwMYfYWXMNg eoWRQu7d2sWSygrdpBytlT5lYOc8vv7caZ2m1EujY27A8PHaBIaQsLuwcZVLs6/RZcuI Vw6v2c60Np38jonfaE9lQ9YzuI9TVGu0idWgBFomOJnWu5zciUE76j6zA4ZZNfXooNGW 48nshGoIOOl+0ZYLoHIc8CSxrdQoSRQDsv22/hffQ91fL/ssEKuRtAxuy53ESleyJvYY /tvlSkr9/xoDyrVMFED5fA71WZt9m2b8+GGkbdunrH7qOAqb82VBhG6BBPf22nFzpYvE JXsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588624; x=1706193424; 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=U3ZIaTdIDVbGxgj61qLOgdlUIoPK1UIssk3iN71rz/s=; b=r6vz56rE9lOOc1Rq1DRpvcajeyaseODR5vPWUuZeZGzqkEBz+1N2okv/K2VNMkpJ7D HmGWknT/nlECMWK6x8tSz8XYnw/03Hb0sjLrBrXMllmNZh70rTKdM3r5bgpRc+WT4vF0 fvAbghRCOC7iz+x4tyBvSGmEyKL5EyYQ8LHFYeZp7h4FvkDIyswi/sPrJ/7MXyuItvwg Lji3kHWJwrkym0pDVphGCtTlAsEH7eD4lk8YC9MSkWZKRB8H6ypWbjECELwtZXcd8m/P OQXp1umDjBALCyz0eGgR8FtYEA647a718mIG8u6EqkGgV6Vk4JSX/I4FjgnvcuOMCd0f g9tQ== X-Gm-Message-State: AOJu0Yw8yLnp9L0Omik9Cj+TX43ad5/79bdMSzg9m8Bc+Qq03aQpj+Q4 X7tL46fnEUlsVlKwl1Ifzt3dapbdjtkFlghbf+0ApzKXaRasyXhbGtG0dSNRh5bWVaiIHUKcyES WncfGjymjuPKEag== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:564:b0:dbd:f7e4:c7f5 with SMTP id a4-20020a056902056400b00dbdf7e4c7f5mr42508ybt.10.1705588623987; Thu, 18 Jan 2024 06:37:03 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:45 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5161; i=aliceryhl@google.com; h=from:subject; bh=Sn4iv+1Sqmbmlo1CanL38VvE8Hbx2qZrDf9IB96IkL0=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPhq+JGtgXIqkMw8yk1y7rymKao+Lrdw6jY qn7dHXBANGJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 Ro+8D/9mUD4uzehFHVDXuHzTQOnbov3Ne0XfQfXYnDSAoTZsiYTjZlUzKwnExkpj62RL3ayUBG2 KDedWT2hGLntQ5mPzYxJRNr9FaOS4M3B/EhRq0aAbkVsPJzK8wPtaNY97KW38szSvs3bG6xmjea Ks0GwboWSEFp09VXPY7cidfmIzO9I+iU+qt9AI1+55lEyzgzIwW+mdWK3vjKWHOHj8jADqhbXak j0qeUSIirRa2kEkekzA7VNwVYvj5rtziMr5AGDWa7HurBoLwlDHQ2RSHPtSHivZAsSnSDzYINrp DwYfPD3Lu20wrJ1QAUFc3W2BLPJ3gU8zET0hJsOtsLdJ7jKiZoaKqNXUNN+ue4JnTwLAnErbDVO fN6pIW+RM57IyBwEnIOS93dg/2Oz94qq/9hP6JXiVwPhZ4D9lISXcWbk2FXRf3aOWGCHGPQurKP K+n6KQFaNnNCkL7P0o/sFPYAC8/tREzLKS7oieGRe74Ia0DxhOA3CRI9mYyqksVoTyLvm4QsosP pREeitT8Pt+hQGRa9nayjKJunYxdknvFdIV3J4sTtQpq7zZd9uaw1rrtxHWsMePrwiftQzyoGyg BpY910R4bI0iFsXHBilBK/YpXdnytZj1sA4Ll4k3lYOtRIywAS+t47IzhWw/FVbrtLXfQ1TLpnL M3W2M+u9mOftN1w== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-4-9694b6f9580c@google.com> Subject: [PATCH v3 4/9] rust: types: add `NotThreadSafe` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439418874178462 X-GMAIL-MSGID: 1788439418874178462 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 Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin --- rust/kernel/sync/lock.rs | 15 +++++++++++---- rust/kernel/task.rs | 11 +++++++---- rust/kernel/types.rs | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index f12a684bc957..2a808aedc9ee 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 9451932d5d86..4665ff86ec00 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -4,8 +4,11 @@ //! //! C header: [`include/linux/sched.h`](srctree/include/linux/sched.h). -use crate::{bindings, types::Opaque}; -use core::{marker::PhantomData, ops::Deref, ptr}; +use crate::{ + bindings, + types::{NotThreadSafe, Opaque}, +}; +use core::{ops::Deref, ptr}; /// Returns the currently running task. #[macro_export] @@ -90,7 +93,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<'_> { @@ -109,7 +112,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 Thu Jan 18 14:36:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189229 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp384281dyb; Thu, 18 Jan 2024 06:39:23 -0800 (PST) X-Google-Smtp-Source: AGHT+IG7PJZfoJxaA6d5sUZx3/l6zaJDUnZrH751vC7tW5gJJXmkbqcNWgOy0YSBKy0PDKkTZvzx X-Received: by 2002:a17:903:48c:b0:1d4:157c:52c0 with SMTP id jj12-20020a170903048c00b001d4157c52c0mr869092plb.7.1705588762944; Thu, 18 Jan 2024 06:39:22 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588762; cv=pass; d=google.com; s=arc-20160816; b=jMbQWJgLF0gS1xxBHuFpvy7MwcOQK0TW0Yz/Y2RAfWbof1UPYKUjtkFQY/TauWX5AG j186o9kBHqAIfegn1NyC406LwYZ9MaabMfvDz1wm9Ko4Dg1Wsv78SoHHw7x3NfF8nZB3 674hf2YXHTAR4hlkGFWOp8GfS1UoF2e42Okh5RQydC5EKDnZkcIyTgxS9D8WqoZPSc0m a+0VR6fu4PygFDKrZIJYFT6dyvBmxpKll4jTaZtUACl1xQQLjhitUOw6QRkPKU2IHR2n 4ky3fVN8L8HbXDaYUhbfCPiTWbI7JIgqpZD3Aa4smTYi7KsmgkuyxhjHqhy7mnF12r/e sv/A== 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=/zksQHteOqmwiH8Woeh3fMsvz589jdcXJfGHk3odNxA=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=MIsDsBLT3AcbUgeg5+OJsShzQKBnq0+EQtBIoeAgar76qX85HZO4mWe3vYFgcpkXYd rteJSA4P95gr77yMN/ANIlsFnZ1rbSLiUZMqHZ1xC4T4uSjTAx4yS3mW2nNgQr1/KtA4 wWpEkDR6Fnp3WcsGGC8o8+LV4HylWe0oA7xl+KbLODE7WNfMRoc9G7MD3g1/riN1TgdY AjpxhM2fW/Hqh8S7IxZQ3KhWYYaVATbZ9yhev/BdFSHjzDlPSgON/zWdKYFMBjYCv6b3 2ElAa2KsymBMNvbwGeOn9blOi26cl//xTjkmiwPtRqWN92R1CUtmE9hcFl+GEg9/pndD 2f4w== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=kbQWgdjU; 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-30206-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30206-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id k17-20020a170902c41100b001d5efe34085si1614771plk.251.2024.01.18.06.39.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:39:22 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30206-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=kbQWgdjU; 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-30206-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30206-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 A7E00283F56 for ; Thu, 18 Jan 2024 14:39:22 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 71C792C852; Thu, 18 Jan 2024 14:37:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="kbQWgdjU" 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 9E72E2C190 for ; Thu, 18 Jan 2024 14:37: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=1705588629; cv=none; b=faT67vMzBiAmHpAR8vXheFyRrK+7N0dhEd6CJgB9PVsTtKoiK2I960f8NlA8BHxU4ukPsUUPMPm3MHPDiib6xjvIVtpVQ9lNZx/vKcyHMZ6DnJ/J8Ysoye3Q27wOfb+ofNOBK7VFzajKNiFAGhzAp7uOS20/xXul43AqwbTHtOg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588629; c=relaxed/simple; bh=Rjntesxc4Gp7fQsAcEOP8Q1PetN0laArCpHrp7LWq10=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=VJ76ffNKYPLvEHi0zcGcUgXA+2QO7QTakWpFzTm9QwIUo3PdCzFbItAUigbofubISdDuvVmrFd7r5H+ZK6h7JNesn/IUrVLNuIlqZm+uNQxHmPuwBoYY2HrRMQmJhjBlToI4M7hg2/gV6EIqXNNqUWREZ+6e5wYhJpA3hmeHFbY= 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=kbQWgdjU; 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-5e9de9795dfso227081637b3.0 for ; Thu, 18 Jan 2024 06:37:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588626; x=1706193426; 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=/zksQHteOqmwiH8Woeh3fMsvz589jdcXJfGHk3odNxA=; b=kbQWgdjUkSg22FTp0jLf3z/quZTL8PZSUbAGYIjsENXnLOwvImLvez31PPVdh3tCjF +mnbWHy8SrJHgRsVXpCVh6wP/19JwVjxBY2ALNElpGe6N1t4nYYWEyaJt2GkArvPr+kj yH0WN6hx9enihyirTL5DDvkcF9JKf/TdDQBGn6lVL0Nv6bJbCxzXwmpAbTJx0o2d+gKX 5buwOvQyC70227sfEqAwXMJXdpI0d2GkEBXpmM3QWsgU2aJEQK3NeL+wWRo3V/tHvGFl BErQ2D5lF+GyNq0lTawJEb1pyP2fh2ionNoPm4CswWuaH5Lh4EoGnrgN3NvzE3KPevZw sY1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588626; x=1706193426; 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=/zksQHteOqmwiH8Woeh3fMsvz589jdcXJfGHk3odNxA=; b=RSrtMhvbxIBajlncgYH8zopX8E9f+T+6MibzewE8wSbI67C3YMQYO5uFQz+JPxnLJY nH1cPA2g1TIATfUeKsxCuCOjb6ztOEvqvop9JjKvdKcM+5w0BUJ/HI3dUFS8+AeYEUea qyiiO99W1VLvV4TBJfgIx4MpeLZG9EvBK870TusOfeoDR7y4MC9OUvwGYJuK7meonvb4 Bqlz+Z3d87jTI+dImxRCi/4AhkW+8JT3YQYEey/ZdVQTz3ihaMcby7icPV6Q45XXi35j GcSI2PrnC8iiWqe7WS22ZrlWDpCU8BrknVX8vzC7KhLomT3uuPaxPCb9DMBR/rSjTgmn 93Xg== X-Gm-Message-State: AOJu0YxKwgPzuAf1D4avdNlQS3UR3rrut0cvSHJ5N3ZYWtPtDKJUKVXh K4H98/4BBuazlZZDg904yXB1lGyi40eEvBfnyFXL2m9HuDJG6AMGgS2XU58PfndRETXhNkEjG2X Qet9Gl0w6XtKduA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a81:9851:0:b0:5f8:bd56:176f with SMTP id p78-20020a819851000000b005f8bd56176fmr405938ywg.2.1705588626767; Thu, 18 Jan 2024 06:37:06 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:46 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=4931; i=aliceryhl@google.com; h=from:subject; bh=kNwOkaV5Ia31XQPZJQTI0yhdRPo15fqa5k6zJvfVgXg=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPDKdb7jNUOZgmUfWPgNvDVE6eaX4RWU5Zy bdHEBvHrc6JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 RlRcD/9Pfdw5ZyeHjQMrfDqVlF2EJsl7k1szpDxWHbLCa2UP8RqF7+XIr3mGO+hk9dCCNajvQ4j NKBRxTd1A5qm49D1/dZnycpjcYdCyx/NqPn3fC5uvIRqCIcmI1bHWKnuF9wfzH9M4SGxVhrOqWy 4IkB5cGqIE+gG+4C5R0aJvLHaBT5V7r0CKk2nreku5w8H63DEYjWbDXVcwji4Kf7QRoDlOwyHcU 0/X1a8Hbh813vqxBztHwq0kCBcV8j24xTBvAzRg0C21c1psxidMjMs1vtw8HqVn0jiDrY30Wr7L cNaoUvPvzJXQ1QEEFARgPIeFJxacrryDa5hjbyv/fcNVEDMSXbqvDTy2oqy6mq3ZfbQ1OHDMh6q oHhUjhgW2L5VDLRt2G7mTpTmi1OAGDgH/BKLh7+92fjnzjWbvR3cX32ooZcaNdVG6j80Tt+/zaA pYDKg1qE9JlZ23w115zXe3hqqTIwsJuIyDVJ8zYwY4ldQgSu4TqGt9i3dM5plhsBntRzHoipATr QeVXIojpPaobUtETrJNkct+UgfDWRhPfWySavPL7u+XEJb6OJI1AdRH/zI6cPLP1GEiabOFOYmw D9/Y3JhLfb512OlgM1E+7g76kzyG13CTj6c4vHqDe02U3faI2z7a0DKXyQBh4TX0sRD2b3PD7EC XYmcB+yaIOAhZwA== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-5-9694b6f9580c@google.com> Subject: [PATCH v3 5/9] rust: file: add `FileDescriptorReservation` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439442752994511 X-GMAIL-MSGID: 1788439442752994511 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 Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin --- 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 a2ee9d82fc8c..4213d1af2c25 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; @@ -245,6 +245,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: `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 Thu Jan 18 14:36:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189230 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp384448dyb; Thu, 18 Jan 2024 06:39:43 -0800 (PST) X-Google-Smtp-Source: AGHT+IEXwCVmwzaSiXoM2LJQ4XQ7/4JgPJbdM8BWyOQQLg7kcCoLRb66qWYu1CjXBiSkjyFv1Pho X-Received: by 2002:a05:6402:b9e:b0:559:e789:dbfc with SMTP id cf30-20020a0564020b9e00b00559e789dbfcmr405470edb.98.1705588782860; Thu, 18 Jan 2024 06:39:42 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588782; cv=pass; d=google.com; s=arc-20160816; b=P0y0h8xXbVI+2Sr9GxWKFKq6cH1S85IGyf8VluWITY5wZ44LSXOJ+u89376OGcmwYd sTLFZnmFyJErMP603GE0Myc/OJ+vmnQ9hcjwscHQ35H5RwbETpdbvo80ILKCRx8//97O gsbzEtQad8LreeSRyQJvDkJ1NK0D7/ey52WwneBmXWhbwifAtY1W24Tt05MEVPYS2iSp GrJPvpbuGSU72glyf5f+7le3XNRsrDPjDytMLJEilGtUx4IJy1zm2ffzAiebkO4JRDbL 4cCNPpoT+S7uPSqjwT7MKUBe2bGk5rsQiDMZwmO+7SvxxHTCMWbRWPzOFw55LXicyAJ0 d2Cg== 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=uzVko5ey5XomiaTP/3j+Aylzt4fKZA9AvfFuwkATRlQ=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=kRQ4KK1yhYGadyy3Pj0vATezRbnctK9kd6vNupDP10JymTsqlMochslM0N6Mb6sDbd gwJncyqVxHTTQXCeEcmoG2qmA+jXFI5HHqMrJkFm+CI+RZ4De7HUO5pVV2xjz8F7PQ3t rAzWNJn0mFt9qDIn3TIe30p5qSOQbJKoH1gSpat3Ns5s1PttDJyQCU7ZFFFq2EcBihhJ nTJN2giQHaC/k3bPLc1+0PT0TXDUZyO2bhopu2Hr6WSz7qehe36BuOIQMdvVSMznJcK+ Pq9BHoZYWOk1HrWLC9Zz2cAhU6mtU26WKheFT0tRV0na1w3wS6Sf5RseJBFmuE2xH5u4 /rtQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=AthP+9F8; 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-30207-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30207-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id en13-20020a056402528d00b00558740d4f83si7111747edb.101.2024.01.18.06.39.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:39:42 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30207-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=AthP+9F8; 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-30207-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30207-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 515491F23E2D for ; Thu, 18 Jan 2024 14:39:42 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9D21E2D03D; Thu, 18 Jan 2024 14:37:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="AthP+9F8" 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 E1E892C847 for ; Thu, 18 Jan 2024 14:37: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=1705588632; cv=none; b=rh64uWO2Tk2XNbNSdST1Im96ZWF9gxAweP5fgZSm5HvRSISALEM/dsQ0XRX6IUffnOfxk242XN0+eypxLsXVidwvprsQdDth3CDfS0ppZ3DwMB0WPQ2Cm8NnkKZYx539aV4Ge5tku3M22bwZGUPeIEmHsslPVszDM6lO3F3TM00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588632; c=relaxed/simple; bh=VXii4VQu3CEARTA//TXCHQIIjHMrXvbh1ihXw7gxrpE=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=rhJuxNHtqlIKFRCUF56+Jw0+5zFFvaOZ9qQICJOFRdP23gBxAIJaORNwiobNOqiAwAZe4gwU3VIkCr162GREaAuT0q1gZgLVP62R6Vb7eaQb0g3FN6Bu0rCv/JVY7qEBkdZAj4Zql9Lo6vUe19oyJcX87RFk3N13X2T1gpLbe+Y= 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=AthP+9F8; 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-50e73a3a280so8731831e87.3 for ; Thu, 18 Jan 2024 06:37:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588629; x=1706193429; 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=uzVko5ey5XomiaTP/3j+Aylzt4fKZA9AvfFuwkATRlQ=; b=AthP+9F8Cv7XJAh0jqkXGp+bUtR+oa68RlHq8DpxraDmMIkr7fhbfyZ+lfzJv5FIMk nm05ItDqVYiHoUounpGaiCioHLWBNGuZOLaK0Y/29ocNMQkxe1qhwoKAN0q5HrQjbxZY 4EZi2j3x1si96F6nDOqEWEG5geaHHub0DeuxbRyVc1DJGYTU5IODRDJdIf5wQ7pHYLv1 kNpSseVG3FQE+l0Akds0r5+L2LagQLFlTjdtnPnplElruax06cqLl7rE/P9491gDksO9 rRJYW6Ki9YdUevBizHR89fxckEvpDyUOwZm/jjTKW8yPyjy5X2R7s12UHofEPmoQC53A paPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588629; x=1706193429; 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=uzVko5ey5XomiaTP/3j+Aylzt4fKZA9AvfFuwkATRlQ=; b=wJBFmZuKUxpwzqsPA6U9tjz+osLzPYkY6icY1JOBXFMVyFUGE6SYak8J8S/UQGFHu/ XNH6obhnDmbFQlXC0zyIDX7fC64VaXqzgwZkvi6tvRUbuqRkHO6D8JqJTHUIs0J/9cOb LGWMCGkiFPvmDxw1dYpSUcllYWF6bJtP/T7ole8WAimqmtmySo5/eDWEwi0CSUIUz46n +WM0nZr0tFQkg7iUFslOhmvlpN+OSRCfMP/OLFiyWmxhc0QifmE/0O+VAcyhZK3LlFOP xVdMogT+5VBUaaTsA/aUP7YEVD0kpqaq5uRPWdTYz71hJtjCKHfUi++hhf6aXqa2iWfQ l7oQ== X-Gm-Message-State: AOJu0YwzXPuAPm7ncS75RKj1ls/9HGYzbEEC9jhi+UFR/kDUNivPxxwG YD+EnTm88sgrWKSkhXQCoEDihlxsIwoStCKfDWZ7/5zrG3CWp1dESCQt9pZQ6gOoe9mwgDKJt36 YbUsprbS+Cj+waQ== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:6512:1326:b0:50f:14fd:5a2 with SMTP id x38-20020a056512132600b0050f14fd05a2mr1242lfu.9.1705588629212; Thu, 18 Jan 2024 06:37:09 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:47 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=2220; i=aliceryhl@google.com; h=from:subject; bh=VXii4VQu3CEARTA//TXCHQIIjHMrXvbh1ihXw7gxrpE=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPE2OQ5MxNmkDx/d0OyvyE9y0jK5TyOb1gz zrC083CUEyJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 RjpdEACVtZzvrDY55UxSJ0r3VfIxbuH2lJ60e5lYPYESp/NSHZUevhadVVJ5vNaqGItTbasjvh1 tGN5hPIH0oOAfcQsOueBMQHjqksSSKFZDTtPMJWj020IPO38EU7p+4nmFMCIb+jaImA97N+1DDW A/MR6DzqWFkHMa1/+Xe/Zc4VgvPz5+SWEiCR0jU2im3moJN1uX8ZqHU51N9EhAo0VBkT8nkYOyI bCDJrRgssbd663cT0mZhWamzB8IiQYOTgGMmrOZ0XwBxVQsVFKK8apkEI8ApgNyat+Co9T6p1cF wkzcoRcGLHp7298srMnW5NNnvwpnCCGaP7CzswE7C9UD6ghCiPEa/55CT0UoOWaZ4+JXZHnvq4j Igre90ckd2KIf+IK1g6j8r1QelcY3EOI0xFQzO4inFl1luCvZ7/C5hez22JzuBzjgxU/rf3LfXA eoWczckrhL9h5W9YYcCgJcdeclNGH9gs6bitekVktpOadWm9GTk1aq3O1yMOHuVDqq/AnUlyKiJ QZvuEWyK51mlWtYlf7TCjiHYanRUrnRmF6e+iNWQkE/3/sIf/X0P+izYMzfgLlltS5tTC1Dn3ct XctOVPFmJAjZf4gWlkQ6goBCTyyda6IjbMK0zeVA/+X162OA8vdYa3lL30+c0L/bfjUO6ZJOt9p SHBCBHHndkwyigg== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-6-9694b6f9580c@google.com> Subject: [PATCH v3 6/9] rust: task: add `Task::current_raw` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439463307580631 X-GMAIL-MSGID: 1788439463307580631 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/ Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin --- 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 4665ff86ec00..396fe8154832 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -82,6 +82,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 @@ -104,14 +113,12 @@ fn deref(&self) -> &Self::Target { } } - // SAFETY: Just an FFI call with no additional safety requirements. - let ptr = unsafe { bindings::get_current() }; - + let current = Task::current_raw(); TaskRef { // SAFETY: If the current thread is still running, the current task is valid. Given // that `TaskRef` is not `Send`, we know it cannot be transferred to another thread // (where it could potentially outlive the caller). - task: unsafe { &*ptr.cast() }, + task: unsafe { &*current.cast() }, _not_send: NotThreadSafe, } } From patchwork Thu Jan 18 14:36:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189231 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp384653dyb; Thu, 18 Jan 2024 06:40:01 -0800 (PST) X-Google-Smtp-Source: AGHT+IFyQxABoCZoZ6FlBMxacwsoZhX+WRdrVszzxUKJDfmjYXAVrB4/zYLK9v7gqqiuBQakggOy X-Received: by 2002:a05:6a20:1604:b0:19a:7899:8238 with SMTP id l4-20020a056a20160400b0019a78998238mr1104946pzj.7.1705588801262; Thu, 18 Jan 2024 06:40:01 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588801; cv=pass; d=google.com; s=arc-20160816; b=tjxXZv8o2L8QbS8ExHLBP2Y+yA5z8bgfT3r2OoIs1ptYKEOAJdJfJRU8+Ov0ghh0aN 09sPBZWFkDYIq1F3DHAxQCIXZl+XXaPBsiGhETWhuZSjWteivwBxDarHtskoGOBmUqdz 5apEBdjkU41oYgjLiR3oTDKhgYEk3BZyyJagltr1LUfkOEGXo4tdFEQWLA60FGt2zhqH j2/Ngx9PHA8kQqjrg/u1XgkmvrQkFVi0OtGZNaiArIaCbZgAN8JiGmVWRxS45GH2GxFh yenSKf2QZwd5NXSthSxtkIrgkyWiVQAKlSF32jjaV2JKco+vAVXVAI+nKog7S8h8upqF usJg== 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=yUOoP4whgKHdC0dBs+MNrfLiOAjtU4Hh4swg4JUqoYk=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=NYtOAUHfE8dN/cEHP8Ojpj+T5JhfvyFS1+BIM05e5QeXroLL1ae7FFT2xVtKW8b0ey ABoqlQMydr9QXc6OlSjsRKG7sj8oQSlBarGhrRTWYNEg8dzc2IXLvlfZ2AeJ5I2LI1wW NBlvXcVtBnno/kb+S1mfmOagWyjn2707c70OWXZm6v8I3CYPwhtxqKg+aAx71+gnEYrh 5zE+p1RH+BHqp8aLms0sVOpqZ/iFLKL6hiqk7Q8H8sR8L+29AzYWsRNll4SfiZjxCr8G 7vnkiqQpSzcsnTNFbs7xAiBID9E7O7b704olQEoc7HkoAlQHuZ/lJ3717iMBENiyx4H2 nvtg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="lygnp1J/"; 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-30208-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30208-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id 35-20020a631463000000b005c5e2165e37si1621091pgu.125.2024.01.18.06.40.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:40:01 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30208-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="lygnp1J/"; 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-30208-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30208-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 EE060288F55 for ; Thu, 18 Jan 2024 14:40:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E7D7A2D610; Thu, 18 Jan 2024 14:37:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lygnp1J/" Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F9852C871 for ; Thu, 18 Jan 2024 14:37:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588634; cv=none; b=ZM6esSeYtT/4hVZPjqwe4MF60ngSg72FE4Tqphjx0+uDVGWxBdsmnbzujoAH0hGnaJ+HEsBLeRHZMyc9EbYWXi4TcFV77jrR3nIBUY8zQP3ju1AlBVMsw32JSR4d/Tnd4EOc40Qxg09L997NtBWJXFU5N3XMlkOqHY3V6PA4Av8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588634; c=relaxed/simple; bh=iOTVc308M1nIqnqlnsbYAX42462qOIT+qeK5JAfUWBM=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=XUUu1vOyyPJOjhZegULRnSOs20l2hedi6e2BVdbek357t7/treVEARhQyMMQO1nBl10GBsK8HjWHS81CqF2iGHdlv7oWsdgrZJdndaeoO7lNyq+Ei0MRngiBLIrxB2KLmIwptiWWIJ+pVT22OGDC9HxUG3q/BM+U4Uz5mEAPaSU= 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=lygnp1J/; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-db410931c23so16473514276.2 for ; Thu, 18 Jan 2024 06:37:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588632; x=1706193432; 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=yUOoP4whgKHdC0dBs+MNrfLiOAjtU4Hh4swg4JUqoYk=; b=lygnp1J/cK0uFErzwEfOEuuxvxBe20xUYZNTjxXsBg1g3E1CjHCgPpe56YPFlQuZFu m2G/pgmTtNul6SQb3LeThfaCiPjDR2YiHSGSZ/K5lQx3oe18musjgi3GzRVpEDqZS7K9 4i6U7frm89l29iTMbeJLdC6IFHkjN0669+dG1DtfwFI7tuNWC8MKlhTl25I7rVeLrGoZ TyPU+Wh095bp/dXYlOi8fpVRdmYQQ1V7kEQ4JlveE5bfN1DJz9nuxKXo43scJdYOcqOx BhyRsYUiZdtJ6xGXfPSvQQKBJxM7D/7cG8Ss7T22wAdPemThF16BP3ILzSVfMW8IJjT7 nrNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588632; x=1706193432; 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=yUOoP4whgKHdC0dBs+MNrfLiOAjtU4Hh4swg4JUqoYk=; b=bcmFMdmhGnNdr00gY81bIKPoylNjSICxIi2yFUSw9Ck+CGRnHOoX/AsFNJzYsDBc0p 8IWE4NFtFlfFSMj5QFvlhZoGhV0VcVAnOFbDOj3Uxiojyb4mypQbmgFVdP1KXl+S+B4b HLxF0YcuwLby0AfjkMC4JUxA12UeDeSgLCKmtH+O8TfzyOOU9pESKc4GPe9vIywEdZlx 2XFYLI7Iwc2SF2dxHdUL7ZE1aPs3UBEjMSqRVBfC4JieGoCNVxGfC/2Wq5tdekO8nw3K Q8JZPmVwd0XRFLzqDrkIGD7A3M3QxdbY/BJVXK9+vRyaYBC23kh0cQzObrPCOsNfSwMj WHrg== X-Gm-Message-State: AOJu0YwNCEkwERDTmkeOh4UHEQ4JuQzrD/BzoObZrr1Hg1EiERQ2XGjG 88cAb/BcDzKTxNTczzIbo6BPuh1hNLDyqwd9QqQvVrWKVT58cAd+v2ipCWYKX77ryGw2kvUr1YD ZCfArQTLUx3opug== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a25:f807:0:b0:dbe:a220:68f9 with SMTP id u7-20020a25f807000000b00dbea22068f9mr398828ybd.0.1705588632055; Thu, 18 Jan 2024 06:37:12 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:48 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7816; i=aliceryhl@google.com; h=from:subject; bh=iOTVc308M1nIqnqlnsbYAX42462qOIT+qeK5JAfUWBM=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHP7dWmmun1RJa/jFe0TSW4BcGhSsZbxYjTg li7AUdjExCJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 RuGnEAChjbPR1FijqwPj+bzom4AGjLjPpstNi1duk++5Rs92pKVv/2UgIfS1ag1IplBT5fTGrDP zXedAWo34iBWSH/8yzG/Y7tF9dXYKk1tn5iAxXZhcXvR5VJS4+Cu2K7SrPWf6pmMfZe7vAJ94uc U4T4sx/Z0MJ2uSbuaUPplXu0mde5/g/WgsJtMZWAk2mblTG8tBcK65q5uetrHHEI6klAqM6METN EW06FgjfyDGYd1qY1Xjt0wx4zl/B3Tq7qNqZO0WcSIJ6/iCzJGCDDnej+bL1poJK3hb5Fhcmk41 FLYs/5RU4infv4WsIKWA7zkrMI9RMrxQ+i2cSELfkbvQamGc3A1ic2ZI2ljmstdDcMy/4TQzwHp c1BpNsDaCnoIctXkDaeT9jW58jzOY+MBxdrqlcs/nHyvm2km2Hr9CmBFYu3g3FE46RfZoEjWnls O3hi7ptyuo3qTfEqU+4g14C+OS3Uh5RtFLn2UMoa69z2QAyaAIcua1jBpts4+pUEaQRVJK3xWdJ YyNgCBcscaLqC9VR9GD3ZDD6q4S7khZErqd/9Ue1YG1ubT6CAIGwa3X4+TpMiifIBGrAsj3nMuK EyRk8lqtjw8rsdhljg3EuRYRgy06Uo4ZqpQGTX8luEopW7N0Pc7tpvKvvIR2oQMuDOElN9TrVXz DutNsOMMUgSrERA== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-7-9694b6f9580c@google.com> Subject: [PATCH v3 7/9] rust: file: add `Kuid` wrapper From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439482908110374 X-GMAIL-MSGID: 1788439482908110374 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] Signed-off-by: Alice Ryhl Reviewed-by: Benno Lossin --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 45 ++++++++++++++++++++ rust/kernel/cred.rs | 5 ++- rust/kernel/task.rs | 74 ++++++++++++++++++++++++++++++++- 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 0e2a9b46459a..0499bbe3cdc5 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -11,6 +11,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 8017525cf329..8320e271232d 100644 --- a/rust/kernel/cred.rs +++ b/rust/kernel/cred.rs @@ -8,6 +8,7 @@ use crate::{ bindings, + task::Kuid, types::{AlwaysRefCounted, Opaque}, }; @@ -52,9 +53,9 @@ 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. - 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 396fe8154832..17c02370869b 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -8,7 +8,11 @@ bindings, types::{NotThreadSafe, Opaque}, }; -use core::{ops::Deref, ptr}; +use core::{ + cmp::{Eq, PartialEq}, + ops::Deref, + ptr, +}; /// Returns the currently running task. #[macro_export] @@ -81,6 +85,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. /// @@ -142,12 +152,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. @@ -157,6 +189,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 Thu Jan 18 14:36:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189233 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp385174dyb; Thu, 18 Jan 2024 06:41:00 -0800 (PST) X-Google-Smtp-Source: AGHT+IHAq+WAx/AudXdf7iLCzsi7WSZU7vPKdnf2njdKzuKetbgngO/Mk7/95D6CrdEohJOUg05S X-Received: by 2002:a05:6808:7c8:b0:3bd:732d:1943 with SMTP id f8-20020a05680807c800b003bd732d1943mr831256oij.33.1705588860578; Thu, 18 Jan 2024 06:41:00 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588860; cv=pass; d=google.com; s=arc-20160816; b=YubeBuWVesQR+Zn6IfW0lM977hIQC9nRw4PHM5+TCEat0Ck8JHvRBZAoWNTsydkvG/ bJrVxhCwRU+Vm4+F6aBZ+dpdfvGR5H2fCq92RtF5Q1jbp1cu8ZwY/aVTIFzTxyFQic3f 1P86bAUCYbS0a96mP9l7YCls3eVk3dRF1TGY6Tfr0LFhPNqS4r+1LN7nBlTetvFsNuXS nJlWNZ14Qzh7Sg2DcWL+PmS1gM+wgyIzBHH4CmpAff6AHGdcccQ5+TET7ubBNetaTJqO S+KT+DUjNrvK4bAKToVSAO44PUZ0LWc2QqwDHNz0Fl7eH6WkcRQRJ+i/kTGA6G0cC8hk EAng== 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=+blVL8ZBy6jqOBmqELtFpOeZUV9tKCkmfo+mU16u+CQ=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=YQUgr34v3JXF4fE4gKg+gsOIBRooYeY4AfiKtVgS7K0Hfpihx1MJhzFz+TwxjtFFzt LB8VWV+6SG3Y3yGnTJa5Dh8GlgvLcuNqs7Bs3WYsSoQZ9HS6dMc0TkNzO/fvYDO3Qjpr M4/wPS2m2KetaDazFOp5xP2oggz5xnKXPp3D0JR0YTne6cuQO2UVzxDCPfvnqSp8nDX/ 4SOG11YB/xNK14evSAHCp3rzoZtEnz71dTMPkvHNHuw6feytVpv9yWagkjk0TlkZDp1N RE6g/e3cjWCJYX2Ar5TnJYd4YeudnLRSRIhw41PdawAGw2g4mBL97DhgjiIxvyGq0k5P b7qg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=G8vIBX4+; 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-30209-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30209-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id c18-20020ac87d92000000b00429fee348c2si6083351qtd.644.2024.01.18.06.41.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:41:00 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30209-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=G8vIBX4+; 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-30209-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30209-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 7C3521C25C83 for ; Thu, 18 Jan 2024 14:40:28 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D930D2D78D; Thu, 18 Jan 2024 14:37:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="G8vIBX4+" 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 C5EB62D041 for ; Thu, 18 Jan 2024 14:37:15 +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=1705588637; cv=none; b=fGLaOLC/IMydu+CVBqoFsWUU6THSPf5mLgfWEToC8EWGwvm5CxOqj/0iFlpq+rLAOaHPMPO1tSotsjbgcL5HnxzaPW58mv81GtKoRwiUe+fxey1OJSjF7mJ5Tk0eMVHwKgLO4a8ndCk7oeK7R/D2cgMGCQE/XjPxbCgHjU21nSM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588637; c=relaxed/simple; bh=Wfr5zVjOG3UE709Szk8cKn0CtUNKm/A57P+u9YprkUk=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=PzDeLgO/MJstDAjYmHKdaceNeI0XW7/kW/fISxOEYEFScNLESSBdF+/fEGrtYdToljwcrpgtXqlmtXHbsY2HO3jSpchoGVqheHbXk2k8K+vJgoRzuiVLSP+G+3Rta84vgzFx2UY2063FOFSbkNwd9r6sPe11wCK/iSFhNJJr01I= 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=G8vIBX4+; 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-5ff7eabfd94so20415377b3.3 for ; Thu, 18 Jan 2024 06:37:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588635; x=1706193435; 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=+blVL8ZBy6jqOBmqELtFpOeZUV9tKCkmfo+mU16u+CQ=; b=G8vIBX4+zMK7kB+v+5jRkLNgwGQbTO7+SLS+ps2TnX0IBsqfYqA0qpeEfNKs7QH1EK L4ME7Id53UVH7gLcZGc/tAeOq7bQ4KUw3mVZ9xTDXY6AG3Lamg+w5inam0f+X5Yy7iu9 BwCiqLoISjERl6EcRmHmA8nvHYbN7He0HVcSCtwshF1tWFyzVj1n21eUzJtYkERdiGOW nHeVwRfM9SvJZoE+bqiHjsFB1ExxXTKgCg/j1Zir7ErGPZlKpw28SXDuon10BJPlEDhK dxUMtCIGjZKFlqiYeqcD7sJLyPj70q5jkZN7HGwR3JELhJi/ZL3mj08MbH5V9HCifcBe jo/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588635; x=1706193435; 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=+blVL8ZBy6jqOBmqELtFpOeZUV9tKCkmfo+mU16u+CQ=; b=aNDng1GwrUKTEerQNPK8fA5fL+0T38Bj8F+fR40IlODRyFo/IuovYJE+y74GGFS7we 7kWQRxWm+TVYIZ1VVa7OHCfontW06AtYEaJKqyS6JzBrem2O+T8iguE1TukjDveheevo HM/H5KXpVz1xivODmBVfY4RuwS0oWiTpR35a4gSn+14uHhBhHfQV4vdMQew6Dqc5MBXA IS9/DcnKmiZoBF29CemYuxiacE+bzPRmgGyPrdrE8L2U2NcbZzFtMDZSkZ2kYmZqipPW qTvTqO0iVDCI3MduawaL+03VgASbIImWCeAR8Z+EKMDtk8kuV6ZQ9GVH+1yNwSem/BxE Gn0A== X-Gm-Message-State: AOJu0Yzsg+GYI/BjQdqhA5geQ3/DMZp0p3OIvZ+4pg4Vs02zBoOFSduA 485yMmEBkhVuwj3DPokpiShVyui5YySZwHtiNDRe5pWl36EZA2StGyKV6WxeXMeOvCKp9uYfgCm +0OxrjZiNORN1Yw== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a25:abc1:0:b0:dbf:19f1:cebd with SMTP id v59-20020a25abc1000000b00dbf19f1cebdmr371231ybi.12.1705588634908; Thu, 18 Jan 2024 06:37:14 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:49 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=13733; i=aliceryhl@google.com; h=from:subject; bh=Wfr5zVjOG3UE709Szk8cKn0CtUNKm/A57P+u9YprkUk=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHPtZXbCxpHNbaCYBy9CArf5mPIJ7e2rOqN0 tlBygIEu3mJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 RkLGD/967wZ0wgXtdAQJ/jfLlVeOB+mCOVoSxwIgfiWRxIXP2+hvDYfzUnW9Bt116lxL5YZlu3C odCoR2wfM6vUy3EOlccDohyspyLBdWbi6OVg30mXEeXPEwaWEV+nWhZOk7W7kIQuXi3s7fQPixh rxtBp4LRpPQ47yXvbgbOCrBXfL13Zsn2RCsdZxOedQtBZushemcSI1TNQLut2lvB5umi5oyWwgU 7v88ZHgFtjENFPLn+UihunwI2h2m/zDiTrXhF1PxVJ4AaVNJmrL+KuXmPgRAauBJKzdSdLu0URI kXDsxX2u4waHhzZVBHKaEgJyL2uxPgv1Jtm7dqDFX0wFvM4O0a7FQHmYxH8A7qwmVpZPDooj4Fw HEwiQ78Ellr/1QWrLeLn8LfRMJCYHHvDD6tk5Pz+sAD/rZhnwB0q3GumT7hkXXMuZ2aHlOjnR6q WMGehYx3NsThbuUQ6xZK1V/ojmDFWTi4X3KDi2KOQ6N5DAqXkIazSKdN4yoWfLtR55eJXXle7Xg 2LJrXOx5Qj3hozaAblwDC00CcIajFj17YtkjnDPEqrBwaYLYQKtHJKBViCv6RKhPLoemzniMJYz ZZa6FLIiCFy884Si0jczxU0CWJTnSjbDDBLrxRpQXUfHAR1Dc1gblmG/TxJqMGxdiKgPl+vBr9D 6cX89XlvsodY5FQ== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-8-9694b6f9580c@google.com> Subject: [PATCH v3 8/9] rust: file: add `DeferredFdCloser` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439545034320920 X-GMAIL-MSGID: 1788439545034320920 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 --- rust/bindings/bindings_helper.h | 2 + rust/helpers.c | 8 ++ rust/kernel/file.rs | 180 +++++++++++++++++++++++++++++++- rust/kernel/task.rs | 14 +++ 4 files changed, 203 insertions(+), 1 deletion(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 0499bbe3cdc5..6b5616499b6d 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,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 4213d1af2c25..1a669e84dfe0 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 { @@ -315,6 +316,183 @@ 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); + } + + // 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 + // `close_fd_get_file`. + let file = unsafe { bindings::close_fd_get_file(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 refcount to the file. + // + // SAFETY: The `file` pointer points at a file with a non-zero refcount. + unsafe { bindings::get_file(file) }; + + // 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 `close_fd_get_file` which also uses + // `current->files`. + // + // This method closes the fd. 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. + // + // 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`. + // + // 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. + // + // 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. + 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 17c02370869b..a294fe9645fe 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -133,6 +133,12 @@ fn deref(&self) -> &Self::Target { } } + /// Returns a raw pointer to the task. + #[inline] + pub fn as_raw(&self) -> *mut bindings::task_struct { + self.0.get() + } + /// Returns the group leader of the given task. pub fn group_leader(&self) -> &Task { // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always @@ -180,6 +186,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 Thu Jan 18 14:36:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 189232 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:2bc4:b0:101:a8e8:374 with SMTP id hx4csp384940dyb; Thu, 18 Jan 2024 06:40:35 -0800 (PST) X-Google-Smtp-Source: AGHT+IHLtCpNhabModiTZAYoguH61hMTvtVjQLQGuP/mxgP3a63E7qyBGHulJnSi8QmYFJUq3xBi X-Received: by 2002:a05:6359:2a5:b0:175:c2e1:87c9 with SMTP id ek37-20020a05635902a500b00175c2e187c9mr946104rwb.28.1705588834866; Thu, 18 Jan 2024 06:40:34 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705588834; cv=pass; d=google.com; s=arc-20160816; b=TuPjYE8qQQlxFJxukcMLgsiFjWnwTxnO0lSZoAgxW9KoBtKjQRgI6ZUv48wB6LGWXQ iXaMUHp5EfaHe7NROfRtsoU+MqkUpai2HDN8SjPJk8cnp9qv0OTqdvPqmFAC2kv+zc+W x8yePjEvrfExB1pgLQOy7Fj7JKfXJNaw5zeiq1QbemdUQErglTut30yajrBCgZsqeawZ QMtlrWGG7M/IcLfvK59AY5VYGSpiI56rAXyJF4tp91NZiS+D7xroputvH9o6+9f5Xx7F 0i89W7YRBST1HOM67h1RbsF1PtXLqVtRzWVMcNQP/7mz57IosYYzGudAgEqChS7iIjdL LjJQ== 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=Im2eze6BefJj1h9/utHPCxEpN5HThewTotaQF/gyF20=; fh=OP+vvG9ih/wBlPG6J6WwyVN77+HGWDbQuR6Uf4lsYyg=; b=qHEXAFPJrxBlU/5oqnaG+dsPz6/Cu7RnZyIv8Uf/HDLSzoSoavE/eFqBXBCtirOO9w zjIJVX7BPiB6WIjXbnXnofXp7Hih6wCVt2Dz0u/SicLG5AFA1Nfn09wlmtyd+Zla4Prd CXn+DNeybRSD09Pd1i5aqezBq1Lx3mtKmqT4EYcOXdTG8Sy9hJoPi/PQdAiTEQO73Mjf EK891jvM9D9ZboWpeYAzbyilVhmrd6COBu9QAWHOlDEquDLNYgIkMtEx0h/B1lzmiIkS TPl8pT/CTVCU3N0qo18D9Mp3ZV+xREia163fg0EtbZ9QVPijUBrl4UyxBRbC7tL4zx3I covA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=wZEAkGfp; 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-30210-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30210-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id e26-20020a65679a000000b005cf88b03757si1507352pgr.70.2024.01.18.06.40.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jan 2024 06:40:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-30210-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=wZEAkGfp; 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-30210-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-30210-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 90059283A3E for ; Thu, 18 Jan 2024 14:40:34 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 213172D7AA; Thu, 18 Jan 2024 14:37:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="wZEAkGfp" Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98C202D60C for ; Thu, 18 Jan 2024 14:37:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588640; cv=none; b=Gonk0ld+6V9WK+xcsiv5a7On3KTqpzuSEU2GBcQMkAGNY6GGVSRoUgsRq7a8gY2zd4YsNPtQxUoM53goimCFlM5yxmYlWisq/ZJIu95LXkO26l4ZkLhcQ+EZGMNgKxcwzWd/IudFMl5z+qT4PXoHe+MlHuCDRLruw+VX9tTqTLw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705588640; c=relaxed/simple; bh=U0kbF9n+OCIj5nAmZ8f74BVmM+kgojhD1k4K8VuFoB4=; h=Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Google-Smtp-Source:X-Received:Date: In-Reply-To:Mime-Version:References:X-Developer-Key: X-Developer-Signature:X-Mailer:Message-ID:Subject:From:To:Cc: Content-Type; b=qgmPaAVMJAkjvFv0KlRdj3/i1yYbPaaICGRD5ka5CGZYWaEus8Me3F3n+F+sE3SBjOpfwExIGKJIQtdKvXp3D9t+RINKQF1BvAJ1ow40CuWSRcgNkLmvER5hAkuHClAxRj8y0+SiM9winKIrO+hNUEPWLW/l3087FegpKz33qmU= 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=wZEAkGfp; arc=none smtp.client-ip=209.85.219.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dbf618042daso6504193276.0 for ; Thu, 18 Jan 2024 06:37:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705588637; x=1706193437; 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=Im2eze6BefJj1h9/utHPCxEpN5HThewTotaQF/gyF20=; b=wZEAkGfpuMjRpE1+6dwYHA+yS/JnPH7iFnZnfvjWaWkUW1l768E5XywiBfavFs/lZk nv0lTuqPwlOLIuyIBnC01KE0C/uQIEIhamisNIoghYFbfDiMpOrcJBAUIPxESCkynsfO WV7FVk4H0Fc8MTDwnOvIxuRaqyvlA4jiSNtpRU2vaClN+AWxeqLjqYefdA+FZtL87m0y 5DbKU5canLqyi7gm9a/ylAKeDWfcy+nChbGWSbGirLR7YMieI5uE7H4SQHG1g4NRXwwM 3dZ1o7/cw8QZBt8rRG/myVS2KFzp5hhiwjLCKe/xFtrUhZFSFi5OK0ELk30cCuMO0doB 2Xrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705588637; x=1706193437; 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=Im2eze6BefJj1h9/utHPCxEpN5HThewTotaQF/gyF20=; b=EYS1LVi9P1I7yRZtcJzq59Bpm1PwNW3fQH3FDAbnhA8DeeF7eMyZt352HqbfZAHnXe 6rc9U/5Jpls28yBI9mk4Nx5wJJ4Lbz//aYA2EYmtdiQB33li/ENQIUDKqcnSHzzQZcJ7 Y2bl6YoVwRTc3d1p+KrPRtacmPMMhp1cQLjXaYr8TxC8X1gmXs4zHF872TgDUdeFCR+1 3dxvtrUyZwyckrnh82FQCXf2hwrj8dAwLTjUjfJyT5OfU+glF0sesaa6i6pUIXZcUevM 8BM7+luVPpzRjdNdAIgo2tTnnkouhkc0mhd5jlBQnr9jV9wmbCaz1NomnXL05UrX4LLK 6Pjg== X-Gm-Message-State: AOJu0Yxmg3RD0jMhF5qkA7BFLpbYP6IZu/LsW/zHJFxhnKDz2tUeZMxB 7JyfBYCdJTRKJnf0ARHbJ9HHZaLqaJ70ideKerQ6HX0Sk2ILoD9Rh0ImeGpNxY1iMZkWGgN5pXP Ov/jxdeq0gOSYsA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a25:ab11:0:b0:dc2:5273:53f9 with SMTP id u17-20020a25ab11000000b00dc2527353f9mr38278ybi.1.1705588637528; Thu, 18 Jan 2024 06:37:17 -0800 (PST) Date: Thu, 18 Jan 2024 14:36:50 +0000 In-Reply-To: <20240118-alice-file-v3-0-9694b6f9580c@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240118-alice-file-v3-0-9694b6f9580c@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=6894; i=aliceryhl@google.com; h=from:subject; bh=U0kbF9n+OCIj5nAmZ8f74BVmM+kgojhD1k4K8VuFoB4=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlqTHP1B0f9FEveRyGvHFIpDR82qIOZvzI0h0Dh +gXrFTQQkOJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZakxzwAKCRAEWL7uWMY5 RvAlEACEQG3zoHHCnyU+9ljr+4eCS0WAPem8ctmmonLTjsvGstWq9lFCCdBAc/0DMdLauRdTUGO mHtCVk6tZMWBOKyBNSxNiAzLV+v5Q5gIREOwh3hYLXvxVg3Xns/JeAdhXpxdtFEF9zuieO7vjAq BpHCxnuaPL/YFHFyYnDBo8bUZ5VhK0pzsM1ske9YQ5PEhyrx+geH9bzzDHl4JmCtrHltrtP/sLz Cn3TmAkW4th4USkhTxFxBHbGrHsgi+LayvLtYCHhWrUM99d6VtV5AAU8MTbGP3zV1X6P4sQPYS/ ki3ChcPczJBFP5GEesM6QsMz0lPLngu57/jHKArSkrZ2fkU2JEFfbaAJlfoVxmd6ngxDxLJH193 Sbi1M3sOqyR02eiJHybU6vJUqpZoPFHloMC8S5vPWKNcVFAngUB5jEXtaW2KiRV4QgccDTIwBxY jgLAO2yzUx6E3+Xp4Qtm3qhegaMr0SEQs+wWlxcLtddbi1COkAAJ1ebrc+vVCN6ro3RWLcW7Aox GzUFpnuqAT5U0ZvQ3bPCiM49MoOdUmujk/D2O84TfLkFMYdJ2k0uFl/FuCnMKwoxB6ann9NOgY3 OLLnq4SgOImxiGcRCl23sNk+opYWTejwCXcq7Wiz9+qceQQ0Hitu7SZOODb/2uLDRXSeAow/eJU O2Sr+4iWJpdKUvw== X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118-alice-file-v3-9-9694b6f9580c@google.com> Subject: [PATCH v3 9/9] rust: file: add abstraction for `poll_table` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan Cc: Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner , Daniel Xu , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1788439518399875931 X-GMAIL-MSGID: 1788439518399875931 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 --- rust/bindings/bindings_helper.h | 1 + rust/kernel/sync.rs | 1 + rust/kernel/sync/poll.rs | 113 ++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 rust/kernel/sync/poll.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 6b5616499b6d..56c1471fc03c 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index d219ee518eff..84726f80c406 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; diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs new file mode 100644 index 000000000000..157341a69854 --- /dev/null +++ b/rust/kernel/sync/poll.rs @@ -0,0 +1,113 @@ +// 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. It must ensure that when the waiter is removed and a 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_list` pointer must be valid until an rcu grace period after the waiter + // is removed. The `PollCondVar` is pinned, so before `cv.wait_list` can be destroyed, + // the destructor must run. That destructor first removes all waiters, and then waits + // for an rcu grace period. Therefore, `cv.wait_list` is valid for long enough. + unsafe { qproc(file.as_ptr() as _, cv.wait_list.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_list.get()) }; + + // Wait for epoll items to be properly removed. + // + // SAFETY: Just an FFI call. + unsafe { bindings::synchronize_rcu() }; + } +}