From nobody Fri Nov 29 21:54:36 2024 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.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 2DD8B1C9DDE for ; Sun, 15 Sep 2024 14:31:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726410714; cv=none; b=d7wEMWPjER6u0eBivJlyTef+e6IaGpIC7kZ/VmWvBDrr5dbuDjw+ccGmYvqmlIl1esTHKW5gLdZ6/iUm9+BuhfX1UW52j5/xhud4eiCoQwp+MiDNnUPpr5Wo09e1D/5mEwP6RYTCHskjrRrZBDB/q3yu1WEeJrYeBX9npqO6jPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726410714; c=relaxed/simple; bh=zqB7PMivLvaNHUeozQVnq1eG1vfCAIQC9md71JxVrLs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=b8A3hiRlcs8ZfOV/4TU62jLsIqSQHY868UuZgHt1PHAK4Tkk0gvIF2xqezRwqUoKZKbVAbOY8CiLRJWvh9XkcDOl1OPPiI1MyYscBV17x6N0MUaUur9CCZJsVfLiAdPEY2PLBRI7Unc+qjbvs017MXPUKg6GyezhMWCiFcuiQWE= 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=lP8c0Ltx; arc=none smtp.client-ip=209.85.128.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 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lP8c0Ltx" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-42cb471a230so27044745e9.3 for ; Sun, 15 Sep 2024 07:31:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1726410710; x=1727015510; 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=2+9+srUDgJEOquigCBUY1zqr31yRtNobeqSqwQ52i1M=; b=lP8c0LtxvyXX9FUYg1x52c5qBPk8ZegLMieOr54Qi10SK57ST3JMwY3y8vBp1T0ntU cKOtzCgfWcc1VwSwCQQ4mwAuCgGe3tN0N0TGw4whDN41g3qmAWXNmd3BNy5ujMw7FvOq ch7pa3gfNrKzhKAT27bsnsuo1HYABXuXu3kgrKmb+oOovD5gHFKXHNA1hjK5q2zecHjR DQXR66LeMFj0je2IMea3mHAuZNRGzNC4SUySWpjYvMNVhL5AjPScfO8PiZkjPXhQH5FM ZC+rOXIFqI2WWW4ZG8dQcKuRbYnyc0bSrEa24BiYYloMMPaIICqwRT+w0rZM6h0F6tBb cRGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726410710; x=1727015510; 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=2+9+srUDgJEOquigCBUY1zqr31yRtNobeqSqwQ52i1M=; b=J9iIuX7r2mXVgC06Ny7m4qPZ/pVHlFecNP+nX9p5C3q9qYB130I0hSPRPQRO1nM1du gVBpKn6ZC4Yc3TyEwHzeKxWuU1ZpWED/5vW5FBOJEKPXwAyvOCTx0agfBG7LvhOt8HNJ GPsRJT7HHqIBA/C2GV4MS+A+TB3b3GnUFau2G//mjWiYnYL4KpQP6ksG2sOeHUpdKQ44 pF1OX+HWTgYqLVPC3e8dl04tjn1mQ+DcIPhKG20+8lU9YEVmEBupIFYgXbsVwAAJqM5C kJc/IZcqcE9srMQn1UGmqb28W+p0SvLh5VrQ8vZmSlK9j12j3WeFVXmMWiim3NEmKUry 498w== X-Forwarded-Encrypted: i=1; AJvYcCXv9xJ7tP/thZuY3gLcY165q0Do1orJFGAafMapAmXiAUFrK/A5xKtb+z4rkku25Ph7P3r7iaiFAmh4D+c=@vger.kernel.org X-Gm-Message-State: AOJu0YyyNgvlM4/9i0k9gvMYYPt+7jcWbGW1Bezswb2P5WJ+SjjfZDB/ TAoIVOT6eC+e9O84XriLMfGODoCSk7bBfEcnt7Rzrx0s/CmptCd+un38iwVnbIOz8Bp4wjOD9dY L6K7A5SMy6NEC+Q== X-Google-Smtp-Source: AGHT+IEa4LNRUZs7U02EZPuMJYs3657T2iAsYFHpFziLsdiq+5y8nCs9e0TpPTZRP6H3NZwQoX4+Ge4se9q+Y6I= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:35bd]) (user=aliceryhl job=sendgmr) by 2002:a05:600c:4984:b0:42c:acab:d090 with SMTP id 5b1f17b1804b1-42cdb51153emr1817035e9.2.1726410710593; Sun, 15 Sep 2024 07:31:50 -0700 (PDT) Date: Sun, 15 Sep 2024 14:31:32 +0000 In-Reply-To: <20240915-alice-file-v10-0-88484f7a3dcf@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240915-alice-file-v10-0-88484f7a3dcf@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5412; i=aliceryhl@google.com; h=from:subject:message-id; bh=UusuKczZgpbZafCOu2SHAqb0ksf74QfeTn7LXrO42A0=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBm5u/DJeMSoYje+0B76NnFNXI/hIns7KoesrsKS 9PwYauTUkWJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZubvwwAKCRAEWL7uWMY5 RquqD/9TQ3EwSzosmOZT9P7R4KT0im5i2FrNhk8HJ76gol9DIi9UU4ScEWMCM+NFetVWf4RehPK LcXPxfYku7nxRS1Q0CpAKD1WXgbsImT3eD7/3DJ4wwgkMl6PXD6FSuNRb9dRmjAmjxK1Js5gG6b eJJ/LvGdExSCRFQ7h520CpWsagx324C7ZyuSn/xdJfaFMxCjYkxiVneQerAgqjuY5UKrqPQ+aOd B5EG3Hl7plv925Q7Ws7zDyAnT19mFD10H7Mj36M0C/AXt5VQbC4WmrxFt5iz+UPZVn0mT4uHRWq 2v8/pgihao9PgKIKBSJ9VvV8wOuwIpmZcY71mfndZSL3/0AY0UEQXXCg5ql7czStjxlbmTheNL8 8EUZ6qE3ycprb2DIg7GoLhPHblvUkFtPlp4874CNBcGyLHdfsvfvgcVDfnwt1q19ELxRZmC2zDg XZl7eKvZyXfQIH12aPJFCPzwGKOGxgNAEiBHCLXhIRAWiW336iLK9FH2d2wlkWTMA19/9HVN5Vk yvRkcHXR7Ksgd9z6DSqR0E7qBPfqtVa0X8EAOj6wsIGVRvRQ53oc4ghtapB6icS2v8MegGPHHKh y0QxlWRmLhKktA4SiVunzSA4WtQLGeJ0EqcADNPHXTxjg97pRfKBJCk34qJTlh0wYtEp+yaLIj1 VFIJRgUPq/BkiiQ== X-Mailer: b4 0.13.0 Message-ID: <20240915-alice-file-v10-6-88484f7a3dcf@google.com> Subject: [PATCH v10 6/8] rust: file: add `FileDescriptorReservation` From: Alice Ryhl To: Paul Moore , James Morris , "Serge E. Hallyn" , Miguel Ojeda , Christian Brauner Cc: 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 , Greg Kroah-Hartman , "=?utf-8?q?Arve_Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan , Dan Williams , Matthew Wilcox , Thomas Gleixner , Daniel Xu , Martin Rodriguez Reboredo , Trevor Gross , linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org, Alice Ryhl , Kees Cook Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Wedson Almeida Filho Allow for the creation of a file descriptor in two steps: first, we reserve a slot for it, then we commit or drop the reservation. The first step may fail (e.g., the current process ran out of available slots), but commit and drop never fail (and are mutually exclusive). This is needed by Rust Binder when fds are sent from one process to another. It has to be a two-step process to properly handle the case where multiple fds are sent: The operation must fail or succeed atomically, which we achieve by first reserving the fds we need, and only installing the files once we have reserved enough fds to send the files. Fd reservations assume that the value of `current` does not change between the call to get_unused_fd_flags and the call to fd_install (or put_unused_fd). By not implementing the Send trait, this abstraction ensures that the `FileDescriptorReservation` cannot be moved into a different process. Signed-off-by: Wedson Almeida Filho Co-developed-by: Alice Ryhl Reviewed-by: Benno Lossin Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Trevor Gross Reviewed-by: Gary Guo Signed-off-by: Alice Ryhl --- rust/kernel/fs/file.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs index 3c1f51719804..e03dbe14d62a 100644 --- a/rust/kernel/fs/file.rs +++ b/rust/kernel/fs/file.rs @@ -11,7 +11,7 @@ bindings, cred::Credential, error::{code::*, Error, Result}, - types::{ARef, AlwaysRefCounted, Opaque}, + types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, }; use core::ptr; =20 @@ -368,6 +368,79 @@ fn deref(&self) -> &LocalFile { } } =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. + // Additionally, the file is known to not have any non-shared `fdg= et_pos` calls, so even if + // this process starts using the file position, this will not resu= lt in a data race on the + // file position. + 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: By the type invariants of this type, `self.fd` was prev= iously returned by + // `get_unused_fd_flags`. We have not yet used the fd, so it is st= ill valid, and `current` + // still refers to the same task, as this type cannot be moved acr= oss 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.46.0.662.g92d0881bb0-goog