From patchwork Fri Feb 2 10:55:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 195799 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp344758dyc; Fri, 2 Feb 2024 02:58:11 -0800 (PST) X-Google-Smtp-Source: AGHT+IE5CiHFhHsZ7S6tyFBrq37/fwF3qwmWSe9OF3w3Gkx8iqQMYVoCtMbCP2eStxAFi5AN1mE0 X-Received: by 2002:ac8:7dc9:0:b0:42b:fda6:dbe8 with SMTP id c9-20020ac87dc9000000b0042bfda6dbe8mr3290701qte.17.1706871491619; Fri, 02 Feb 2024 02:58:11 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706871491; cv=pass; d=google.com; s=arc-20160816; b=WWvzPZSBdHYilJlTAPNjnntWH8fy+Ut4bMUTR7WkVSrswraJwpQthuXLChU0MUcUgX SgLiEawxuTKsy9Z6f+0hOli3Rl3o7oUKv+rbHDTHg1Axy13T0fTsp4Ka1I/Rn9cE99ie /4qqT9sIVB0YIP7tikh2JTqv8ectaiLBaYGtXH97JomU94KgsBdrlzf4uZczD2MpB17C Rl/Gg9g0D9bqMtDilItgsUxcaR1Fv/uac8BOfAnOg3ktJI9sbbloyaiUv72X7ybGuftC mN4cjIcOQMywYmBm+6WUu/ULhjtyWHv93pyvAHJ+YwYyFtyGJPbRrDw57mgZqt+GERe0 MIzw== 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=j0kQAYir3oZEIRDEnXelicKinA6h+DIjN/X4cL6IApI=; fh=3BCXC/vw3JLndguyf54b/GE+QxCR4zwwQsnks5vPmfE=; b=RrP7hLu1D0K31/OnIvN+PBaPQb+jYF//CeVJYboj+fKSjr1AbIMBDLwPswtRq1fh3L HKPEW5TWE/B5dDBSMEtl9V19gpcag8ZAhF+cPNM5y3wCrREjxAujZYm2MKIYkSYzb4b0 ZLljy0Hz88gGvOtO953egr4aiQoaHVewi9UzW5UNfOr5BtguY7mZSHV/uTF+9LjuA3T9 Bx1PcFBS1rAMdpCrtPIF7igQ+9nWnU9acy5NaS3UDuZGeFWhyPc8hh90WTBdUTmzH4TO nAS8FKhEoHX/0cRCxLi7OvPe/WAV7WMx7iX9Qa3yApskL0EG1XXIhL9hpi55XiWYnnDW DrTw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=KaDpZSN4; 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-49711-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49711-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com X-Forwarded-Encrypted: i=1; AJvYcCWW+JG8X8mremFuoLfthBMmeU4ozxI5Xz7yLWKiD+gTkd/Fiv5o8ibRoQBEsXf9ceZkR4Z7GhVEp5PDeRAOJAKUvEQ7lQ== Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id 11-20020ac84e8b000000b0042bed047689si1762039qtp.315.2024.02.02.02.58.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 02:58:11 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49711-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=KaDpZSN4; 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-49711-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49711-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 5D43C1C2676E for ; Fri, 2 Feb 2024 10:58:11 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 00F10141996; Fri, 2 Feb 2024 10:56:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KaDpZSN4" 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 3CEAF140771 for ; Fri, 2 Feb 2024 10:56:05 +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=1706871367; cv=none; b=qp0QxQooPrFUJJJMCRHYlmOn3RkQoggIBIojNDrprrAsvpgee7D0ZbvGj/nJ4qVpu0Yn4edXosMvlwPsCwwPbkDwqRZbc/LAxblWdEvxuqkmhLDOCbEOtNb87cYAf16KzWHnd9yB9nC2mx5/MtRRRMHvTExxSWf7qdGIgUM4O2A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706871367; c=relaxed/simple; bh=rtE/oxepQqksMoR2qP3TYN4awGZUE7hR5gf+H0B+bNQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=LrH8OTv1GmS7HidXlqHOrmosOWGgrdupE5XvHg6we82Xbx6YPaK9JsxpReab8P60GctPosETFclU0xI4I0jnxhZZFfT+Dd0JPHAE6u7vhD4g7Z+ZgR824jsKaF3IRg0d5JIhKQx20iKKfhZgAkTFrwvkQ3uvTapkRPSUzMAy+Bg= 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=KaDpZSN4; 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-2d07ef53265so13238701fa.1 for ; Fri, 02 Feb 2024 02:56:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1706871363; x=1707476163; 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=j0kQAYir3oZEIRDEnXelicKinA6h+DIjN/X4cL6IApI=; b=KaDpZSN4pKxnXUYxuj5/iF+QNSfN3yj5BUM5H9r7TXd2anKAOCvvNU79Y4Q6pNdI2c LFOmXYnut1BSr/M46c2xaB+cEMamMaEWh1XoGo8rN/sXZCuy69LxpkvU+HezDem+wgk5 L/VyPf+bwRIsjocpuHucBmtGAJm6mf6MqFqTEQ1JmzM8WgvqtdGo8LSLNIgQaW7WQ/5n BQ+PlZ/tq1tMe5utYIzc3tjVnBgu+4CQoeeXJP8vNbOtINx81icRqA1ZU6HEgLAXdUZP cfGZqsksaVGOoJ9ASytsqaTLl8V4FMFUZHiNIcH1aDAqMYwBmyKrBhnF8Bv+ybZxYmSg Spgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706871363; x=1707476163; 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=j0kQAYir3oZEIRDEnXelicKinA6h+DIjN/X4cL6IApI=; b=Yd9JI8P6lNe2TF1cfhPmV6FImGaBRZeaEGay9I+UFgMBoZWL0CHRo0DnaErin9A7Ak /jYOSvqLl0OOt5Jyus57qE3XFz6OGE+ugv0Qxsf4Tts8AaO8Se1FYHx+B2eZDBcNgS1x 2JNVS4wnDqseVXnhiRbo9pGm8f3cNdRkNTT+IN76/j2/zFHFcajcQHp3VZKzPxttEPAb qWCGd0AUNfKzhytP9yzm00qBUTYZW2l7qvoiaAkSiCtP2Nx2K3Q3CHZgvYs1Z6hshLPL g9uLbQVcKYkgcfpOnBYxUZlBc1RJgFONGMXe957imHGAhomWytChq0Lnmgb4t/8zKH6l 6hZw== X-Gm-Message-State: AOJu0YwPGSoRoXJpSD9Q7yha8GB76MxbuN4Y0SCDCpVsatvK1BtdPEa2 dr4AkSym27MxlZ5LbDn0PgOBdS2XUvwxqPMir0yWJe3DFUlyTQkhB0njgG66mWGE4ncegRoLHyz UV+qhPD+szIuqLA== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a2e:b74c:0:b0:2d0:8445:ed0 with SMTP id k12-20020a2eb74c000000b002d084450ed0mr1642ljo.1.1706871363112; Fri, 02 Feb 2024 02:56:03 -0800 (PST) Date: Fri, 2 Feb 2024 10:55:40 +0000 In-Reply-To: <20240202-alice-file-v4-0-fc9c2080663b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240202-alice-file-v4-0-fc9c2080663b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=5020; i=aliceryhl@google.com; h=from:subject:message-id; bh=YCd8Lz4NQ7loX+ZbPkzyOHKKxufRjuF+zON1dgx0uqI=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBlvMjJbqrZjLJl6uR5Bkp5+R171uPaIU6vFld2j bMoKBaFa+KJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZbzIyQAKCRAEWL7uWMY5 RrkLD/9+HcI/n4ZPrDD3BILD8zoSicDxCF9ACdPWFuJApsidYxMhtaI/iA9uM1hzg1MoAiotNr/ un7kzqyv0CyRf/+GkI9BVhxDjfsmc3vdKX9KwMHs/8UJ2/LYQX644ERm//D/Nc9av81/PEMIyj2 yUygfbPmRF13ridgReF6P+Bjj7F/aQJyP5GRewBhymFkRt4NFw51lS+PDqtTXQ99lHrp2xQLVOz MpUdSJKRlxnHJDVEX+tcgSJs3ffDLknbvXegWJ296c0gJZz1w2xpN5yslfrhfeYWXBuYbF53O7c ktdmltlm0EZfGyKvi+cvcOyh6TZHEoePWuAIw5NHJIYXC+4UzR0oXuXb3Gx9yyMz/zNjU0YA+lF BZTgxlbBCSExKmQJgEgJ56HQblQYqUnQnSQ9ZieDRGoOWPcS5hINxO16yYPxWMhJWK/6KzhNQXp tqDBH2pxmLHHhndhlXDq7BCtkB0hCIrdc8WGBbk/rzOCuLBkP0Vz5/Op/Z2xFzYWTFgNjlB+6Pj UbLlXkG9iJew2C9h4KnwsCLKTcz8uhppbqztkMuSxfqY9uRR42re2iwTi2Nc1sXrji4/+p/E8r4 uqeMOUneKKvT6whbLAFHT8GaqazYU6NvxjLfmL4aBKnxeVHaxIsbzeI4jfCFSKFXs5cb3kUhBbe TJ0DQpOlv8/5MjQ== X-Mailer: git-send-email 2.43.0.594.gd9cf4e227d-goog Message-ID: <20240202-alice-file-v4-6-fc9c2080663b@google.com> Subject: [PATCH v4 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 , Dan Williams , Kees Cook , Matthew Wilcox , Thomas Gleixner Cc: Daniel Xu , Alice Ryhl , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789784481491058763 X-GMAIL-MSGID: 1789784481491058763 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 Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo --- 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 095775411979..2004270a661c 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; @@ -243,6 +243,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`.