diff --git a/rust/helpers/task.c b/rust/helpers/task.c index 7d66487db831..5874032b3e70 100644 --- a/rust/helpers/task.c +++ b/rust/helpers/task.c @@ -55,3 +55,9 @@ pid_t rust_helper_task_tgid_nr_ns(struct task_struct *tsk, { return task_tgid_nr_ns(tsk, ns); } + +unsigned long rust_helper_task_rlimit(const struct task_struct *task, + unsigned int limit) +{ + return task_rlimit(task, limit); +} diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 0f3add12f499..36d787bf7567 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -251,6 +251,70 @@ impl Task { // running. unsafe { bindings::wake_up_process(self.as_ptr()) }; } + + /// Check if the task has the given capability without logging to the audit log. + pub fn has_capability_noaudit(&self, capability: i32) -> bool { + // SAFETY: By the type invariant, we know that `self.0.get()` is valid. + unsafe { bindings::has_capability_noaudit(self.0.get(), capability) } + } + + /// Returns the current scheduling policy. + pub fn policy(&self) -> u32 { + // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount. + // + // This uses a volatile read because C code may be modifying this field in parallel using + // non-atomic unsynchronized writes. This corresponds to how the C macro READ_ONCE is + // implemented. + unsafe { core::ptr::addr_of!((*self.0.get()).policy).read_volatile() } + } + + /// Returns the current normal priority. + pub fn normal_prio(&self) -> i32 { + // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount. + // + // This uses a volatile read because C code may be modifying this field in parallel using + // non-atomic unsynchronized writes. This corresponds to how the C macro READ_ONCE is + // implemented. + unsafe { core::ptr::addr_of!((*self.0.get()).normal_prio).read_volatile() } + } + + /// Get the rlimit value for RTPRIO. + pub fn rlimit_rtprio(&self) -> i32 { + // SAFETY: By the type invariant, we know that `self.0.get()` is valid, and RLIMIT_RTPRIO + // is a valid limit type. + unsafe { bindings::task_rlimit(self.0.get(), bindings::RLIMIT_RTPRIO) as i32 } + } + + /// Get the rlimit value for NICE, converted to a nice value. + pub fn rlimit_nice(&self) -> i32 { + // SAFETY: By the type invariant, we know that `self.0.get()` is valid, and RLIMIT_NICE + // is a valid limit type. + let prio = unsafe { bindings::task_rlimit(self.0.get(), bindings::RLIMIT_NICE) as i32 }; + // Convert rlimit style value [1,40] to nice value [-20, 19]. + bindings::MAX_NICE as i32 - prio + 1 + } + + /// Set the scheduling properties for this task without checking whether the task is allowed to + /// set them. + pub fn sched_setscheduler_nocheck( + &self, + policy: i32, + sched_priority: i32, + reset_on_fork: bool, + ) { + let params = bindings::sched_param { sched_priority }; + + let mut policy = policy; + if reset_on_fork { + policy |= bindings::SCHED_RESET_ON_FORK as i32; + } + unsafe { bindings::sched_setscheduler_nocheck(self.0.get(), policy, ¶ms) }; + } + + /// Set the nice value of this task. + pub fn set_user_nice(&self, nice: i32) { + unsafe { bindings::set_user_nice(self.0.get(), nice as _) }; + } } impl CurrentTask {