Skip to content

Commit aee0f6d

Browse files
authored
Merge pull request raspberrypi#723 from wedsonaf/cred-aref
rust: convert `Credential` to use `ARef`
2 parents 3033118 + b6f9c12 commit aee0f6d

File tree

4 files changed

+41
-66
lines changed

4 files changed

+41
-66
lines changed

drivers/android/process.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ pub(crate) struct Process {
247247
pub(crate) task: Task,
248248

249249
// Credential associated with file when `Process` is created.
250-
pub(crate) cred: Credential,
250+
pub(crate) cred: ARef<Credential>,
251251

252252
// TODO: For now this a mutex because we have allocations in RangeAllocator while holding the
253253
// lock. We may want to split up the process state at some point to use a spin lock for the
@@ -265,7 +265,7 @@ unsafe impl Send for Process {}
265265
unsafe impl Sync for Process {}
266266

267267
impl Process {
268-
fn new(ctx: Ref<Context>, cred: Credential) -> Result<Ref<Self>> {
268+
fn new(ctx: Ref<Context>, cred: ARef<Credential>) -> Result<Ref<Self>> {
269269
let mut process = Pin::from(UniqueRef::try_new(Self {
270270
ctx,
271271
cred,
@@ -811,7 +811,7 @@ impl file::Operations for Process {
811811
kernel::declare_file_operations!(ioctl, compat_ioctl, mmap, poll);
812812

813813
fn open(ctx: &Ref<Context>, file: &File) -> Result<Self::Data> {
814-
Self::new(ctx.clone(), file.cred().clone())
814+
Self::new(ctx.clone(), file.cred().into())
815815
}
816816

817817
fn release(obj: Self::Data, _file: &File) {

rust/kernel/cred.rs

Lines changed: 23 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,41 @@
66
//!
77
//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>
88
9-
use crate::bindings;
10-
use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref};
9+
use crate::{bindings, AlwaysRefCounted};
10+
use core::cell::UnsafeCell;
1111

1212
/// Wraps the kernel's `struct cred`.
1313
///
1414
/// # Invariants
1515
///
16-
/// The pointer `Credential::ptr` is non-null and valid. Its reference count is also non-zero.
17-
pub struct Credential {
18-
pub(crate) ptr: *const bindings::cred,
19-
}
20-
21-
impl Clone for Credential {
22-
fn clone(&self) -> Self {
23-
// SAFETY: The type invariants guarantee that `self.ptr` has a non-zero reference count.
24-
let ptr = unsafe { bindings::get_cred(self.ptr) };
25-
26-
// INVARIANT: We incremented the reference count to account for the new `Credential` being
27-
// created.
28-
Self { ptr }
29-
}
30-
}
31-
32-
impl Drop for Credential {
33-
fn drop(&mut self) {
34-
// SAFETY: The type invariants guarantee that `ptr` has a non-zero reference count.
35-
unsafe { bindings::put_cred(self.ptr) };
36-
}
37-
}
16+
/// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the
17+
/// allocation remains valid at least until the matching call to `put_cred`.
18+
#[repr(transparent)]
19+
pub struct Credential(pub(crate) UnsafeCell<bindings::cred>);
3820

39-
/// A wrapper for [`Credential`] that doesn't automatically decrement the refcount when dropped.
40-
///
41-
/// We need the wrapper because [`ManuallyDrop`] alone would allow callers to call
42-
/// [`ManuallyDrop::into_inner`]. This would allow an unsafe sequence to be triggered without
43-
/// `unsafe` blocks because it would trigger an unbalanced call to `put_cred`.
44-
///
45-
/// # Invariants
46-
///
47-
/// The wrapped [`Credential`] remains valid for the lifetime of the object.
48-
pub struct CredentialRef<'a> {
49-
cred: ManuallyDrop<Credential>,
50-
_p: PhantomData<&'a ()>,
51-
}
52-
53-
impl CredentialRef<'_> {
54-
/// Constructs a new [`struct cred`] wrapper that doesn't change its reference count.
21+
impl Credential {
22+
/// Creates a reference to a [`Credential`] from a valid pointer.
5523
///
5624
/// # Safety
5725
///
58-
/// The pointer `ptr` must be non-null and valid for the lifetime of the object.
59-
pub(crate) unsafe fn from_ptr(ptr: *const bindings::cred) -> Self {
60-
Self {
61-
cred: ManuallyDrop::new(Credential { ptr }),
62-
_p: PhantomData,
63-
}
26+
/// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
27+
/// returned [`Credential`] reference.
28+
pub(crate) unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Self {
29+
// SAFETY: The safety requirements guarantee the validity of the dereference, while the
30+
// `Credential` type being transparent makes the cast ok.
31+
unsafe { &*ptr.cast() }
6432
}
6533
}
6634

67-
impl Deref for CredentialRef<'_> {
68-
type Target = Credential;
35+
// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
36+
unsafe impl AlwaysRefCounted for Credential {
37+
fn inc_ref(&self) {
38+
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
39+
unsafe { bindings::get_cred(self.0.get()) };
40+
}
6941

70-
fn deref(&self) -> &Self::Target {
71-
self.cred.deref()
42+
unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
43+
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
44+
unsafe { bindings::put_cred(obj.cast().as_ptr()) };
7245
}
7346
}

rust/kernel/file.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
use crate::{
99
bindings, c_types,
10-
cred::CredentialRef,
10+
cred::Credential,
1111
error::{code::*, from_kernel_result, Error, Result},
1212
io_buffer::{IoBufferReader, IoBufferWriter},
1313
iov_iter::IovIter,
@@ -68,13 +68,13 @@ impl File {
6868
}
6969

7070
/// Returns the credentials of the task that originally opened the file.
71-
pub fn cred(&self) -> CredentialRef<'_> {
71+
pub fn cred(&self) -> &Credential {
7272
// SAFETY: The file is valid because the shared reference guarantees a nonzero refcount.
7373
let ptr = unsafe { core::ptr::addr_of!((*self.0.get()).f_cred).read() };
74-
// SAFETY: The lifetimes of `self` and `CredentialRef` are tied, so it is guaranteed that
74+
// SAFETY: The lifetimes of `self` and `Credential` are tied, so it is guaranteed that
7575
// the credential pointer remains valid (because the file is still alive, and it doesn't
7676
// change over the lifetime of a file).
77-
unsafe { CredentialRef::from_ptr(ptr) }
77+
unsafe { Credential::from_ptr(ptr) }
7878
}
7979

8080
/// Returns the flags associated with the file.

rust/kernel/security.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,30 @@ use crate::{bindings, cred::Credential, file::File, to_result, Result};
99
/// Calls the security modules to determine if the given task can become the manager of a binder
1010
/// context.
1111
pub fn binder_set_context_mgr(mgr: &Credential) -> Result {
12-
// SAFETY: By the `Credential` invariants, `mgr.ptr` is valid.
13-
to_result(|| unsafe { bindings::security_binder_set_context_mgr(mgr.ptr) })
12+
// SAFETY: `mrg.0` is valid because the shared reference guarantees a nonzero refcount.
13+
to_result(|| unsafe { bindings::security_binder_set_context_mgr(mgr.0.get()) })
1414
}
1515

1616
/// Calls the security modules to determine if binder transactions are allowed from task `from` to
1717
/// task `to`.
1818
pub fn binder_transaction(from: &Credential, to: &Credential) -> Result {
19-
// SAFETY: By the `Credential` invariants, `from.ptr` and `to.ptr` are valid.
20-
to_result(|| unsafe { bindings::security_binder_transaction(from.ptr, to.ptr) })
19+
// SAFETY: `from` and `to` are valid because the shared references guarantee nonzero refcounts.
20+
to_result(|| unsafe { bindings::security_binder_transaction(from.0.get(), to.0.get()) })
2121
}
2222

2323
/// Calls the security modules to determine if task `from` is allowed to send binder objects
2424
/// (owned by itself or other processes) to task `to` through a binder transaction.
2525
pub fn binder_transfer_binder(from: &Credential, to: &Credential) -> Result {
26-
// SAFETY: By the `Credential` invariants, `from.ptr` and `to.ptr` are valid.
27-
to_result(|| unsafe { bindings::security_binder_transfer_binder(from.ptr, to.ptr) })
26+
// SAFETY: `from` and `to` are valid because the shared references guarantee nonzero refcounts.
27+
to_result(|| unsafe { bindings::security_binder_transfer_binder(from.0.get(), to.0.get()) })
2828
}
2929

3030
/// Calls the security modules to determine if task `from` is allowed to send the given file to
3131
/// task `to` (which would get its own file descriptor) through a binder transaction.
3232
pub fn binder_transfer_file(from: &Credential, to: &Credential, file: &File) -> Result {
33-
// SAFETY: By the `Credential` invariants, `from.ptr` and `to.ptr` are valid. Similarly, by the
34-
// `File` invariants, `file.ptr` is also valid.
35-
to_result(|| unsafe { bindings::security_binder_transfer_file(from.ptr, to.ptr, file.0.get()) })
33+
// SAFETY: `from`, `to` and `file` are valid because the shared references guarantee nonzero
34+
// refcounts.
35+
to_result(|| unsafe {
36+
bindings::security_binder_transfer_file(from.0.get(), to.0.get(), file.0.get())
37+
})
3638
}

0 commit comments

Comments
 (0)