Revert "BACKPORT: FROMLIST: task: rust: rework how current is accessed"

This reverts commit 98c8011159.

Bug: 429146594
Change-Id: Ib6968a1a63aafb9fea3e485c39d451b70cf320b4
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
Alice Ryhl
2025-07-02 12:13:34 +00:00
parent 5913c80b22
commit b7f54dd23b

View File

@@ -7,7 +7,6 @@
use crate::{
bindings,
ffi::{c_int, c_long, c_uint},
mm::MmWithUser,
types::{NotThreadSafe, Opaque},
};
use core::{
@@ -33,16 +32,8 @@ pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
#[macro_export]
macro_rules! current {
() => {
// SAFETY: This expression creates a temporary value that is dropped at the end of the
// caller's scope. The following mechanisms ensure that the resulting `&CurrentTask` cannot
// leave current task context:
//
// * To return to userspace, the caller must leave the current scope.
// * Operations such as `begin_new_exec()` are necessarily unsafe and the caller of
// `begin_new_exec()` is responsible for safety.
// * Rust abstractions for things such as a `kthread_use_mm()` scope must require the
// closure to be `Send`, so the `NotThreadSafe` field of `CurrentTask` ensures that the
// `&CurrentTask` cannot cross the scope in either direction.
// SAFETY: Deref + addr-of below create a temporary `TaskRef` that cannot outlive the
// caller.
unsafe { &*$crate::task::Task::current() }
};
}
@@ -85,7 +76,7 @@ macro_rules! current {
/// impl State {
/// fn new() -> Self {
/// Self {
/// creator: ARef::from(&**current!()),
/// creator: current!().into(),
/// index: 0,
/// }
/// }
@@ -105,44 +96,6 @@ unsafe impl Send for Task {}
// synchronised by C code (e.g., `signal_pending`).
unsafe impl Sync for Task {}
/// Represents the [`Task`] in the `current` global.
///
/// This type exists to provide more efficient operations that are only valid on the current task.
/// For example, to retrieve the pid-namespace of a task, you must use rcu protection unless it is
/// the current task.
///
/// # Invariants
///
/// Each value of this type must only be accessed from the task context it was created within.
///
/// Of course, every thread is in a different task context, but for the purposes of this invariant,
/// these operations also permanently leave the task context:
///
/// * Returning to userspace from system call context.
/// * Calling `release_task()`.
/// * Calling `begin_new_exec()` in a binary format loader.
///
/// Other operations temporarily create a new sub-context:
///
/// * Calling `kthread_use_mm()` creates a new context, and `kthread_unuse_mm()` returns to the
/// old context.
///
/// This means that a `CurrentTask` obtained before a `kthread_use_mm()` call may be used again
/// once `kthread_unuse_mm()` is called, but it must not be used between these two calls.
/// Conversely, a `CurrentTask` obtained between a `kthread_use_mm()`/`kthread_unuse_mm()` pair
/// must not be used after `kthread_unuse_mm()`.
#[repr(transparent)]
pub struct CurrentTask(Task, NotThreadSafe);
// Make all `Task` methods available on `CurrentTask`.
impl Deref for CurrentTask {
type Target = Task;
#[inline]
fn deref(&self) -> &Task {
&self.0
}
}
/// The type of process identifiers (PIDs).
pub type Pid = bindings::pid_t;
@@ -169,29 +122,28 @@ impl Task {
///
/// # Safety
///
/// Callers must ensure that the returned object is only used to access a [`CurrentTask`]
/// within the task context that was active when this function was called. For more details,
/// see the invariants section for [`CurrentTask`].
pub unsafe fn current() -> impl Deref<Target = CurrentTask> {
struct TaskRef {
task: *const CurrentTask,
/// Callers must ensure that the returned object doesn't outlive the current task/thread.
pub unsafe fn current() -> impl Deref<Target = Task> {
struct TaskRef<'a> {
task: &'a Task,
_not_send: NotThreadSafe,
}
impl Deref for TaskRef {
type Target = CurrentTask;
impl Deref for TaskRef<'_> {
type Target = Task;
fn deref(&self) -> &Self::Target {
// SAFETY: The returned reference borrows from this `TaskRef`, so it cannot outlive
// the `TaskRef`, which the caller of `Task::current()` has promised will not
// outlive the task/thread for which `self.task` is the `current` pointer. Thus, it
// is okay to return a `CurrentTask` reference here.
unsafe { &*self.task }
self.task
}
}
let current = Task::current_raw();
TaskRef {
// CAST: The layout of `struct task_struct` and `CurrentTask` is identical.
task: Task::current_raw().cast(),
// SAFETY: If the current thread is still running, the current task is valid. Given
// that `TaskRef` is not `Send`, we know it cannot be transferred to another thread
// (where it could potentially outlive the caller).
task: unsafe { &*current.cast() },
_not_send: NotThreadSafe,
}
}
@@ -317,38 +269,6 @@ impl Task {
}
}
impl CurrentTask {
/// Access the address space of the current task.
///
/// This function does not touch the refcount of the mm.
#[inline]
pub fn mm(&self) -> Option<&MmWithUser> {
// SAFETY: The `mm` field of `current` is not modified from other threads, so reading it is
// not a data race.
let mm = unsafe { (*self.as_ptr()).mm };
if mm.is_null() {
return None;
}
// SAFETY: If `current->mm` is non-null, then it references a valid mm with a non-zero
// value of `mm_users`. Furthermore, the returned `&MmWithUser` borrows from this
// `CurrentTask`, so it cannot escape the scope in which the current pointer was obtained.
//
// This is safe even if `kthread_use_mm()`/`kthread_unuse_mm()` are used. There are two
// relevant cases:
// * If the `&CurrentTask` was created before `kthread_use_mm()`, then it cannot be
// accessed during the `kthread_use_mm()`/`kthread_unuse_mm()` scope due to the
// `NotThreadSafe` field of `CurrentTask`.
// * If the `&CurrentTask` was created within a `kthread_use_mm()`/`kthread_unuse_mm()`
// scope, then the `&CurrentTask` cannot escape that scope, so the returned `&MmWithUser`
// also cannot escape that scope.
// In either case, it's not possible to read `current->mm` and keep using it after the
// scope is ended with `kthread_unuse_mm()`.
Some(unsafe { MmWithUser::from_raw(mm) })
}
}
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
unsafe impl crate::types::AlwaysRefCounted for Task {
fn inc_ref(&self) {