From patchwork Fri Feb 9 11:18:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 198823 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:50ea:b0:106:860b:bbdd with SMTP id r10csp780868dyd; Fri, 9 Feb 2024 03:22:57 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUSIlmtFII4rmFQ05q8KRT0aerl2rOYBCOlELliDRUJoe8WcKE6UxHroOScDHYG7FZqW77ElkYnViQmYyabGJ+hdf8pyQ== X-Google-Smtp-Source: AGHT+IFbTZuiBzfO6IgkHEWHDpx0+rHVZzDn6sQT3/glFJ2543VGJlNYqE1AbVAW5YS8+EFb4P41 X-Received: by 2002:aa7:c417:0:b0:55f:e35e:137c with SMTP id j23-20020aa7c417000000b0055fe35e137cmr985711edq.25.1707477776857; Fri, 09 Feb 2024 03:22:56 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707477776; cv=pass; d=google.com; s=arc-20160816; b=QJwPAhUlvdeLt92FwkCs6nigvhelUS7RbTmTH2Yzx7rtB6ZOPzpAMXH61FYOsCXiE3 mBjpZoKjU2O7sEJR0VQxNIed/87yu0qA9H2jrOnWHL2uRRd/+rX3hV+ASy7vnhZa4XOg k7ScohFsLjXQDi2KCvpoOwJ+85vBikf8SDl3IGL2r+9PakBmh+kDGhQ7Wi8hO66wQxfI AK4rfzyRCm5xaskmeo6+GvzFuB8JzK8i6WJ76pvP82DR1XlfiavHgp0+3zEEBqNwLtp/ AOv+Z7GrZj7+sOtKsgEITvAJtqf3t5cswd8C895XuuXFnOmYf6V1SMGkpzL2Yu3KwJ3V +JdQ== 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=dH78NmaaVu9DkNui20oQ6e4x0KTKrZZbiJBCrE6Owok=; fh=C1S12IdyxpN8cCr3fpJqzmzSXssQQIbel2mvace1t1A=; b=gapxHAraYuSPqm/V+5JJ8nS/7Gmvjucmqyw2AyFCmMaGQjPY1UzILvEQn+lT/oNQK7 Db0Ao62f9jPVxY6jA8HUHhxZ7F1IsmuDNUpJS199DB5Ox7F+oTJdoniPOntPFBrV1Gpv cqtXxf/XjtRALo+euq1PKvhLL06+sKIW+z43HpzFCH5osc+HwzwEIc1Iy991L/Hh1s3Z hR+bL27ozbDGOnRE6j/MeJjB/EWqGniCKrznU71V3fxktSJJ4QPNV7Nu8aP8nQJ7dPXP awjuddixunIoRvX58kAomwWaL13Gahw5OZvq4xY1d0cpW9FY+yO4yzdC4x04hWqui81g Mpiw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=fMwpJ181; 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-59284-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59284-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=2; AJvYcCWdp6JEeVIUZJs1HVCNZv4iN9ECgId49/lpvtTb+MO3IuWjyAsI5Er46iEUmEXKAbuxaw+gg19QAnj/lxaEVErZOohzkQ== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id m15-20020a056402430f00b0055fefcc4bb9si802713edc.404.2024.02.09.03.22.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Feb 2024 03:22:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-59284-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=fMwpJ181; 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-59284-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-59284-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 EE6B41F29C11 for ; Fri, 9 Feb 2024 11:22:16 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E1ED43F9CC; Fri, 9 Feb 2024 11:19:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fMwpJ181" Received: from mail-lj1-f201.google.com (mail-lj1-f201.google.com [209.85.208.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECF2D37716 for ; Fri, 9 Feb 2024 11:19:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477549; cv=none; b=NTBcBpn6pVxFaduR+wnmdK7lnLSCdP4rPhM65c8/ghkU+iPWVLWWS3P9dQlvKHXHEMwW8UxVKXEDHDwitGOhzqBvwAaYDaxkJfc6ZyV4JZN58A9g1ZniO7WUByiOGUbPPtDyoHfES1i8lHSQ2kAjw5JyrIgRyYaxCJRjI5VJnx8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707477549; c=relaxed/simple; bh=jpdPd0bnKJx0v5IohdnvKzMyKCUyMI+4XjIMSwBUtJM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=aI7W4NzzYEyvtRfCtPV4owRnZ5FL2L3youSyvA6nbuCZmheiU8DZ9UQTbCQXrlmR08gLZlTIYlug9L/gK4ZpLUoTCHUZAw4dNx2HxOWP1A20SHB67aHBfPEvFPc3zrQrc9TBBIV4eFRftb/HXzKUqfCFK0k0/Ub+FzIP+NWaaEU= 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=fMwpJ181; arc=none smtp.client-ip=209.85.208.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-lj1-f201.google.com with SMTP id 38308e7fff4ca-2d0c1ef2966so6637041fa.1 for ; Fri, 09 Feb 2024 03:19:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1707477546; x=1708082346; 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=dH78NmaaVu9DkNui20oQ6e4x0KTKrZZbiJBCrE6Owok=; b=fMwpJ181JsBSwEf+xWaG3/SYXBV5CQTgm1fer7YnRjhCUr5NquV/xRfFcboy8INDkb Wnx1ERJ9xVZhflkG7NnCDayOEv8HGbkC52S2tl/rqNP3VIQbVRoMIuGV9yFRKBa2lsyR 9Rj2kUB/1jwG/MMtrUpoHc4voNBRpwQuWhMybDKLG8FtpPnQz3Ic3DTBjc1WVsJKqd/u nnAaqg1jv9r1wV/VOkJFE83Q/Lm0GLUfodwwIoGzCj9/tqJEfTVrUmeps2YgaBQI3mYS YJ7nrUsXUUcT8Epn9pBekTXpz1vkD+hO0YxeHftcIMFgHQSsC6wSIhLCIeTx2aFQzvmT EwUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707477546; x=1708082346; 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=dH78NmaaVu9DkNui20oQ6e4x0KTKrZZbiJBCrE6Owok=; b=s5HVnFhOWYUFOiTnRk25+X/X7UemDyiTHR4LUpf7dkSz3fYSlwRaoXA6ivzSLzJqwn K8+YaRCGvA0g3AjGsmyIo1/TqExVfPN6Lwn5NCAh2fQjj9MnSXWuiShDb4F1Z6FZ85Hl liofEkaJ6PI7YvwzOseLHCf8+xVLMBj3UCBD92618MJpsqiaytWOg6q2aKUDXkvPMAgF 0IH2uSjXzcmL8LrI5ubOCwiJz8/CxLYLO4F3cTm5ae3d5FX89sWmj1l7GiRoMVKiiUTf IBY+AdQkaQvVE6xXFnm/oUtJNPA5INhfJKnmgeMOqoMpfdD0e3PZgy4DCyxwe5UaVaSW QY6w== X-Forwarded-Encrypted: i=1; AJvYcCVJ8D+lRq2+BGD81c78ZGLLV0VMoTGNc4E3DKKjBsbLvwcFt1tU5jSbB0wsBmxtcPHNcS9PWWW2MwqDG4XNQgh4NeutrhB42x72vj99 X-Gm-Message-State: AOJu0Yyci8MfWQEi9tErQfVvl5f2sFN57BBO/+4uD94B7x4ccfWVwuba /2jKIc7bbt/ng0IhNJTmSwzOQc53blIoJkXnvjtRwLPmBRtc/eDMw8VYZHnlIhxrxw84M4+wmaQ 5uMRcUtGldtYdyg== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a05:651c:3c5:b0:2d0:d4d5:ae1c with SMTP id f5-20020a05651c03c500b002d0d4d5ae1cmr1228ljp.3.1707477545846; Fri, 09 Feb 2024 03:19:05 -0800 (PST) Date: Fri, 09 Feb 2024 11:18:19 +0000 In-Reply-To: <20240209-alice-file-v5-0-a37886783025@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240209-alice-file-v5-0-a37886783025@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5091; i=aliceryhl@google.com; h=from:subject:message-id; bh=4MEaahIDL8tWEqa8QqxP69ykw7VMt4xM9gXmsdnnpis=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlxgoTvYPgkAnbZVxHmgiO+gQPznHds8k46wwuJ MredE562XyJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZcYKEwAKCRAEWL7uWMY5 RtJQD/sEDIZSqHxDN3nJargoXJ16TZZD2XdbWOh/p5vtwMsyAeGLE9OeZDO+l4qmX/vzv1c2Shm JwyjAWkpt2FRHvpmP3XXi/3JIefGh98lCSC345lEzOWIMkk1gOa/PdxzPT+vU/f3VahQTmCaKHv oBPiBtlh6qYQiM+gUE0KzRgWPfNphRjYc5ZX7EFKL+3Z9Pkpxsc3a+BDxhhF5rsfaaFyQMQ56zS Nr887zw1Q5B/A9NOShHBQYe9TwazetkTKpQGBru+2TiYEqqKdohhWoTTqMF5Cb3YCUldHySQTNv FIEYF7Ix/wa1GnwChc9xfCiojLbJY1beQw5wRmDJ9Xj5pNZDDni6XlQ6evAxSaOMMraDEbNiHs5 VnAYKCgEA9BAMYAL7vW9yq5Zjxzn2pzE6NnS1Th+mbb8PTQ8L9v1sPknUdr60rU1M7B2zDZaIkA jw84LQ+PxUeZJk5ilgtzk6MO5Cb40lMYJ7S9efrYIXaZb6OBfvRtWWaYizRsCpphAX2Z3p3P/R6 9mhNHhSHJkVWE3Bo86kKyKz8lp1d48r2OepUJsyxAL0rz5AcOsQnp4T7+1otubS9PQ/PJCJdwrW MNAokD2n0VSroP021QoRGx6IJvRTAS10mN+pDIDaNX5N4+F76IotOXUe8V8Rat52C6n+94RpgRT pb5OJWjKzH4EhkA== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240209-alice-file-v5-6-a37886783025@google.com> Subject: [PATCH v5 6/9] rust: file: add `FileDescriptorReservation` From: Alice Ryhl To: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Andreas Hindborg , Peter Zijlstra , Alexander Viro , Christian Brauner , Greg Kroah-Hartman , " =?utf-8?q?Arve_Hj=C3=B8n?= =?utf-8?q?nev=C3=A5g?= " , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan 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 , Martin Rodriguez Reboredo X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790420217010459053 X-GMAIL-MSGID: 1790420217010459053 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 Signed-off-by: Alice Ryhl Reviewed-by: Trevor Gross --- 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 3a64c5022941..fb903b7f23fe 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; @@ -248,6 +248,76 @@ unsafe fn dec_ref(obj: ptr::NonNull) { } } +/// A file descriptor reservation. +/// +/// This allows the creation of a file descriptor in two steps: first, we reserve a slot for it, +/// then we commit or drop the reservation. The first step may fail (e.g., the current process ran +/// out of available slots), but commit and drop never fail (and are mutually exclusive). +/// +/// Dropping the reservation happens in the destructor of this type. +/// +/// # Invariants +/// +/// The fd stored in this struct must correspond to a reserved file descriptor of the current task. +pub struct FileDescriptorReservation { + fd: u32, + /// Prevent values of this type from being moved to a different task. + /// + /// The `fd_install` and `put_unused_fd` functions assume that the value of `current` is + /// unchanged since the call to `get_unused_fd_flags`. By adding this marker to this type, we + /// prevent it from being moved across task boundaries, which ensures that `current` does not + /// change while this value exists. + _not_send: NotThreadSafe, +} + +impl FileDescriptorReservation { + /// Creates a new file descriptor reservation. + pub fn get_unused_fd_flags(flags: u32) -> Result { + // SAFETY: FFI call, there are no safety requirements on `flags`. + let fd: i32 = unsafe { bindings::get_unused_fd_flags(flags) }; + if fd < 0 { + return Err(Error::from_errno(fd)); + } + Ok(Self { + fd: fd as u32, + _not_send: NotThreadSafe, + }) + } + + /// Returns the file descriptor number that was reserved. + pub fn reserved_fd(&self) -> u32 { + self.fd + } + + /// Commits the reservation. + /// + /// The previously reserved file descriptor is bound to `file`. This method consumes the + /// [`FileDescriptorReservation`], so it will not be usable after this call. + pub fn fd_install(self, file: ARef) { + // SAFETY: `self.fd` was previously returned by `get_unused_fd_flags`. We have not yet used + // the fd, so it is still valid, and `current` still refers to the same task, as this type + // cannot be moved across task boundaries. + // + // Furthermore, the file pointer is guaranteed to own a refcount by its type invariants, + // and we take ownership of that refcount by not running the destructor below. + unsafe { bindings::fd_install(self.fd, file.as_ptr()) }; + + // `fd_install` consumes both the file descriptor and the file reference, so we cannot run + // the destructors. + core::mem::forget(self); + core::mem::forget(file); + } +} + +impl Drop for FileDescriptorReservation { + fn drop(&mut self) { + // SAFETY: By the type invariants of this type, `self.fd` was previously returned by + // `get_unused_fd_flags`. We have not yet used the fd, so it is still valid, and `current` + // still refers to the same task, as this type cannot be moved across task boundaries. + unsafe { bindings::put_unused_fd(self.fd) }; + } +} + /// Represents the `EBADF` error code. /// /// Used for methods that can only fail with `EBADF`.