From nobody Thu Dec 25 10:34:41 2025 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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="kbQWgdjU" 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-Google-Smtp-Source: AGHT+IHiYqPMk1T2LRzBz+HcP4g/t376gt1K0Erodo59xIhSsLG8kAdYdN17gjS2uM71m4zh73QU4bVm1rDDabY= 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=20Roy=20Baron?=" , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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; =20 @@ -245,6 +245,76 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } =20 +/// 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 mutua= lly exclusive). +/// +/// Dropping the reservation happens in the destructor of this type. +/// +/// # Invariants +/// +/// The fd stored in this struct must correspond to a reserved file descri= ptor 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 val= ue 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 =3D 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 m= ethod 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_fla= gs`. 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 b= y its type invariants, + // and we take ownership of that refcount by not running the destr= uctor below. + unsafe { bindings::fd_install(self.fd, file.as_ptr()) }; + + // `fd_install` consumes both the file descriptor and the file ref= erence, 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_fla= gs`. 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`. --=20 2.43.0.381.gb435a96ce8-goog