Skip to content

Commit 5bb6ba4

Browse files
committed
Merge tag 'vfs-6.13.rust.file' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs rust file abstractions from Christian Brauner: "This contains the file abstractions needed by the Rust implementation of the Binder driver and other parts of the kernel. Let's treat this as a first attempt at getting something working but I do expect the actual interfaces to change significantly over time. Simply because we are still figuring out what actually works. But there's no point in further theorizing. Let's see how it holds up with actual users" * tag 'vfs-6.13.rust.file' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: rust: task: adjust safety comments in Task methods rust: add seqfile abstraction 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`
2 parents 70e7730 + fe95f58 commit 5bb6ba4

File tree

18 files changed

+1035
-24
lines changed

18 files changed

+1035
-24
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)