Skip to content

rust: add debugfs abstraction #1041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: rust-next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
rust: cred: add Rust abstraction for struct cred
Add a wrapper around `struct cred` called `Credential`, and provide
functionality to get the `Credential` associated with a `File`.

Rust Binder must check the credentials of processes when they attempt to
perform various operations, and these checks usually take a
`&Credential` as parameter. The security_binder_set_context_mgr function
would be one example. This patch is necessary to access these security_*
methods from Rust.

Signed-off-by: Wedson Almeida Filho <[email protected]>
Co-developed-by: Alice Ryhl <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
wedsonaf authored and fbq committed Dec 14, 2023
commit 83b7658e77d5dadfcfa672696fa6688b6483a67b
1 change: 1 addition & 0 deletions rust/bindings/bindings_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

#include <kunit/test.h>
#include <linux/cred.h>
#include <linux/errname.h>
#include <linux/file.h>
#include <linux/fs.h>
Expand Down
13 changes: 13 additions & 0 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <kunit/test-bug.h>
#include <linux/bug.h>
#include <linux/build_bug.h>
#include <linux/cred.h>
#include <linux/err.h>
#include <linux/errname.h>
#include <linux/fs.h>
Expand Down Expand Up @@ -164,6 +165,18 @@ struct file *rust_helper_get_file(struct file *f)
}
EXPORT_SYMBOL_GPL(rust_helper_get_file);

const struct cred *rust_helper_get_cred(const struct cred *cred)
{
return get_cred(cred);
}
EXPORT_SYMBOL_GPL(rust_helper_get_cred);

void rust_helper_put_cred(const struct cred *cred)
{
put_cred(cred);
}
EXPORT_SYMBOL_GPL(rust_helper_put_cred);

/*
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
* use it in contexts where Rust expects a `usize` like slice (array) indices.
Expand Down
64 changes: 64 additions & 0 deletions rust/kernel/cred.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0

//! Credentials management.
//!
//! C header: [`include/linux/cred.h`](../../../../include/linux/cred.h)
//!
//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>

use crate::{
bindings,
types::{AlwaysRefCounted, Opaque},
};

/// Wraps the kernel's `struct cred`.
///
/// # Invariants
///
/// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the
/// allocation remains valid at least until the matching call to `put_cred`.
#[repr(transparent)]
pub struct Credential(pub(crate) Opaque<bindings::cred>);

// SAFETY: By design, the only way to access a `Credential` is via an immutable reference or an
// `ARef`. This means that the only situation in which a `Credential` can be accessed mutably is
// when the refcount drops to zero and the destructor runs. It is safe for that to happen on any
// thread, so it is ok for this type to be `Send`.
unsafe impl Send for Credential {}

// SAFETY: It's OK to access `Credential` through shared references from other threads because
// we're either accessing properties that don't change or that are properly synchronised by C code.
unsafe impl Sync for Credential {}

impl Credential {
/// Creates a reference to a [`Credential`] from a valid pointer.
///
/// # Safety
///
/// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
/// returned [`Credential`] reference.
pub unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Credential {
// SAFETY: The safety requirements guarantee the validity of the dereference, while the
// `Credential` type being transparent makes the cast ok.
unsafe { &*ptr.cast() }
}

/// Returns the effective UID of the given credential.
pub fn euid(&self) -> bindings::kuid_t {
// SAFETY: By the type invariant, we know that `self.0` is valid.
unsafe { (*self.0.get()).euid }
}
}

// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
unsafe impl AlwaysRefCounted for Credential {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
unsafe { bindings::get_cred(self.0.get()) };
}

unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
unsafe { bindings::put_cred(obj.cast().as_ptr()) };
}
}
16 changes: 16 additions & 0 deletions rust/kernel/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use crate::{
bindings,
cred::Credential,
error::{code::*, Error, Result},
types::{ARef, AlwaysRefCounted, Opaque},
};
Expand Down Expand Up @@ -151,6 +152,21 @@ impl File {
self.0.get()
}

/// Returns the credentials of the task that originally opened the file.
pub fn cred(&self) -> &Credential {
// SAFETY: Since the caller holds a reference to the file, it is guaranteed that its
// refcount does not hit zero during this function call.
//
// It's okay to read the `f_cred` field without synchronization as `f_cred` is never
// changed after initialization of the file.
let ptr = unsafe { (*self.as_ptr()).f_cred };

// SAFETY: The signature of this function ensures that the caller will only access the
// returned credential while the file is still valid, and the C side ensures that the
// credential stays valid at least as long as the file.
unsafe { Credential::from_ptr(ptr) }
}

/// Returns the flags associated with the file.
///
/// The flags are a combination of the constants in [`flags`].
Expand Down
1 change: 1 addition & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern crate self as kernel;
#[cfg(not(testlib))]
mod allocator;
mod build_assert;
pub mod cred;
pub mod error;
pub mod file;
pub mod init;
Expand Down