Skip to content

Commit 70d7f7d

Browse files
committed
Merge patch series "File abstractions needed by Rust Binder"
Alice Ryhl <aliceryhl@google.com> says: This patchset contains the file abstractions needed by the Rust implementation of the Binder driver. Please see the Rust Binder RFC for usage examples: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-0-08ba9197f637@google.com Users of "rust: types: add `NotThreadSafe`": [PATCH 5/9] rust: file: add `FileDescriptorReservation` Users of "rust: task: add `Task::current_raw`": [PATCH 7/9] rust: file: add `Kuid` wrapper [PATCH 8/9] rust: file: add `DeferredFdCloser` Users of "rust: file: add Rust abstraction for `struct file`": [PATCH RFC 02/20] rust_binder: add binderfs support to Rust binder [PATCH RFC 03/20] rust_binder: add threading support Users of "rust: cred: add Rust abstraction for `struct cred`": [PATCH RFC 05/20] rust_binder: add nodes and context managers [PATCH RFC 06/20] rust_binder: add oneway transactions [PATCH RFC 11/20] rust_binder: send nodes in transaction [PATCH RFC 13/20] rust_binder: add BINDER_TYPE_FD support Users of "rust: security: add abstraction for secctx": [PATCH RFC 06/20] rust_binder: add oneway transactions Users of "rust: file: add `FileDescriptorReservation`": [PATCH RFC 13/20] rust_binder: add BINDER_TYPE_FD support [PATCH RFC 14/20] rust_binder: add BINDER_TYPE_FDA support Users of "rust: file: add `Kuid` wrapper": [PATCH RFC 05/20] rust_binder: add nodes and context managers [PATCH RFC 06/20] rust_binder: add oneway transactions Users of "rust: file: add abstraction for `poll_table`": [PATCH RFC 07/20] rust_binder: add epoll support This patchset has some uses of read_volatile in place of READ_ONCE. Please see the following rfc for context on this: https://lore.kernel.org/all/20231025195339.1431894-1-boqun.feng@gmail.com/ * patches from https://lore.kernel.org/r/20240915-alice-file-v10-0-88484f7a3dcf@google.com: rust: file: add abstraction for `poll_table` rust: file: add `Kuid` wrapper rust: file: add `FileDescriptorReservation` rust: security: add abstraction for secctx rust: cred: add Rust abstraction for `struct cred` rust: file: add Rust abstraction for `struct file` rust: task: add `Task::current_raw` rust: types: add `NotThreadSafe` Link: https://lore.kernel.org/r/20240915-alice-file-v10-0-88484f7a3dcf@google.com Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 8cf0b93 + ac68183 commit 70d7f7d

File tree

17 files changed

+965
-12
lines changed

17 files changed

+965
-12
lines changed

fs/file.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,13 @@ EXPORT_SYMBOL(task_lookup_next_fdget_rcu);
10961096
*
10971097
* The fput_needed flag returned by fget_light should be passed to the
10981098
* corresponding fput_light.
1099+
*
1100+
* (As an exception to rule 2, you can call filp_close between fget_light and
1101+
* fput_light provided that you capture a real refcount with get_file before
1102+
* the call to filp_close, and ensure that this real refcount is fput *after*
1103+
* the fput_light call.)
1104+
*
1105+
* See also the documentation in rust/kernel/file.rs.
10991106
*/
11001107
static inline struct fd __fget_light(unsigned int fd, fmode_t mask)
11011108
{

rust/bindings/bindings_helper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010
#include <linux/blk-mq.h>
1111
#include <linux/blk_types.h>
1212
#include <linux/blkdev.h>
13+
#include <linux/cred.h>
1314
#include <linux/errname.h>
1415
#include <linux/ethtool.h>
16+
#include <linux/file.h>
1517
#include <linux/firmware.h>
18+
#include <linux/fs.h>
1619
#include <linux/jiffies.h>
1720
#include <linux/mdio.h>
1821
#include <linux/phy.h>
22+
#include <linux/pid_namespace.h>
23+
#include <linux/poll.h>
1924
#include <linux/refcount.h>
2025
#include <linux/sched.h>
26+
#include <linux/security.h>
2127
#include <linux/slab.h>
2228
#include <linux/wait.h>
2329
#include <linux/workqueue.h>

rust/helpers/cred.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/cred.h>
4+
5+
const struct cred *rust_helper_get_cred(const struct cred *cred)
6+
{
7+
return get_cred(cred);
8+
}
9+
10+
void rust_helper_put_cred(const struct cred *cred)
11+
{
12+
put_cred(cred);
13+
}

rust/helpers/fs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2024 Google LLC.
5+
*/
6+
7+
#include <linux/fs.h>
8+
9+
struct file *rust_helper_get_file(struct file *f)
10+
{
11+
return get_file(f);
12+
}

rust/helpers/helpers.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111
#include "bug.c"
1212
#include "build_assert.c"
1313
#include "build_bug.c"
14+
#include "cred.c"
1415
#include "err.c"
16+
#include "fs.c"
1517
#include "kunit.c"
1618
#include "mutex.c"
1719
#include "page.c"
1820
#include "rbtree.c"
1921
#include "refcount.c"
22+
#include "security.c"
2023
#include "signal.c"
2124
#include "slab.c"
2225
#include "spinlock.c"

rust/helpers/security.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/security.h>
4+
5+
#ifndef CONFIG_SECURITY
6+
void rust_helper_security_cred_getsecid(const struct cred *c, u32 *secid)
7+
{
8+
security_cred_getsecid(c, secid);
9+
}
10+
11+
int rust_helper_security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
12+
{
13+
return security_secid_to_secctx(secid, secdata, seclen);
14+
}
15+
16+
void rust_helper_security_release_secctx(char *secdata, u32 seclen)
17+
{
18+
security_release_secctx(secdata, seclen);
19+
}
20+
#endif

rust/helpers/task.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,41 @@ void rust_helper_put_task_struct(struct task_struct *t)
1717
{
1818
put_task_struct(t);
1919
}
20+
21+
kuid_t rust_helper_task_uid(struct task_struct *task)
22+
{
23+
return task_uid(task);
24+
}
25+
26+
kuid_t rust_helper_task_euid(struct task_struct *task)
27+
{
28+
return task_euid(task);
29+
}
30+
31+
#ifndef CONFIG_USER_NS
32+
uid_t rust_helper_from_kuid(struct user_namespace *to, kuid_t uid)
33+
{
34+
return from_kuid(to, uid);
35+
}
36+
#endif /* CONFIG_USER_NS */
37+
38+
bool rust_helper_uid_eq(kuid_t left, kuid_t right)
39+
{
40+
return uid_eq(left, right);
41+
}
42+
43+
kuid_t rust_helper_current_euid(void)
44+
{
45+
return current_euid();
46+
}
47+
48+
struct user_namespace *rust_helper_current_user_ns(void)
49+
{
50+
return current_user_ns();
51+
}
52+
53+
pid_t rust_helper_task_tgid_nr_ns(struct task_struct *tsk,
54+
struct pid_namespace *ns)
55+
{
56+
return task_tgid_nr_ns(tsk, ns);
57+
}

rust/kernel/cred.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
// Copyright (C) 2024 Google LLC.
4+
5+
//! Credentials management.
6+
//!
7+
//! C header: [`include/linux/cred.h`](srctree/include/linux/cred.h).
8+
//!
9+
//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>
10+
11+
use crate::{
12+
bindings,
13+
task::Kuid,
14+
types::{AlwaysRefCounted, Opaque},
15+
};
16+
17+
/// Wraps the kernel's `struct cred`.
18+
///
19+
/// Credentials are used for various security checks in the kernel.
20+
///
21+
/// Most fields of credentials are immutable. When things have their credentials changed, that
22+
/// happens by replacing the credential instead of changing an existing credential. See the [kernel
23+
/// documentation][ref] for more info on this.
24+
///
25+
/// # Invariants
26+
///
27+
/// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the
28+
/// allocation remains valid at least until the matching call to `put_cred`.
29+
///
30+
/// [ref]: https://www.kernel.org/doc/html/latest/security/credentials.html
31+
#[repr(transparent)]
32+
pub struct Credential(Opaque<bindings::cred>);
33+
34+
// SAFETY:
35+
// - `Credential::dec_ref` can be called from any thread.
36+
// - It is okay to send ownership of `Credential` across thread boundaries.
37+
unsafe impl Send for Credential {}
38+
39+
// SAFETY: It's OK to access `Credential` through shared references from other threads because
40+
// we're either accessing properties that don't change or that are properly synchronised by C code.
41+
unsafe impl Sync for Credential {}
42+
43+
impl Credential {
44+
/// Creates a reference to a [`Credential`] from a valid pointer.
45+
///
46+
/// # Safety
47+
///
48+
/// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
49+
/// returned [`Credential`] reference.
50+
pub unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Credential {
51+
// SAFETY: The safety requirements guarantee the validity of the dereference, while the
52+
// `Credential` type being transparent makes the cast ok.
53+
unsafe { &*ptr.cast() }
54+
}
55+
56+
/// Get the id for this security context.
57+
pub fn get_secid(&self) -> u32 {
58+
let mut secid = 0;
59+
// SAFETY: The invariants of this type ensures that the pointer is valid.
60+
unsafe { bindings::security_cred_getsecid(self.0.get(), &mut secid) };
61+
secid
62+
}
63+
64+
/// Returns the effective UID of the given credential.
65+
pub fn euid(&self) -> Kuid {
66+
// SAFETY: By the type invariant, we know that `self.0` is valid. Furthermore, the `euid`
67+
// field of a credential is never changed after initialization, so there is no potential
68+
// for data races.
69+
Kuid::from_raw(unsafe { (*self.0.get()).euid })
70+
}
71+
}
72+
73+
// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
74+
unsafe impl AlwaysRefCounted for Credential {
75+
fn inc_ref(&self) {
76+
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
77+
unsafe { bindings::get_cred(self.0.get()) };
78+
}
79+
80+
unsafe fn dec_ref(obj: core::ptr::NonNull<Credential>) {
81+
// SAFETY: The safety requirements guarantee that the refcount is nonzero. The cast is okay
82+
// because `Credential` has the same representation as `struct cred`.
83+
unsafe { bindings::put_cred(obj.cast().as_ptr()) };
84+
}
85+
}

rust/kernel/fs.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Kernel file systems.
4+
//!
5+
//! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h)
6+
7+
pub mod file;
8+
pub use self::file::{File, LocalFile};

0 commit comments

Comments
 (0)