File: manipulate_sys_nice.rs

package info (click to toggle)
rust-caps 0.5.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 208 kB
  • sloc: makefile: 2
file content (70 lines) | stat: -rw-r--r-- 2,465 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! A simple example showing how to manipulate capabilities.
//!
//! It drops and raises `CAP_SYS_NICE` to show its interaction
//! with `getpriority(2)`.
//!
//! This is an example ONLY: do NOT panic/unwrap/assert
//! in production code!

type ExResult<T> = Result<T, Box<dyn std::error::Error + 'static>>;

fn main() -> ExResult<()> {
    use caps::{CapSet, Capability};

    // Any process can lower its own priority.
    println!("-> Current process priority is {}.", proc_nice());
    let r = renice(19);
    assert_eq!(r, 0);
    println!("Lowered priority to +19.");
    println!("-> Current process priority is {}.", proc_nice());

    // Without `CAP_SYS_NICE` increasing priority is not possible.
    let r = caps::drop(None, CapSet::Effective, Capability::CAP_SYS_NICE);
    assert!(r.is_ok());
    println!("Dropped CAP_SYS_NICE.");
    let has_sys_nice = caps::has_cap(None, CapSet::Effective, Capability::CAP_SYS_NICE);
    assert!(has_sys_nice.is_ok());
    assert_eq!(has_sys_nice.unwrap_or(true), false);
    let r = renice(-20);
    assert_eq!(r, -1);
    println!("Unprivileged, unable to raise priority to -20.");

    // If `CAP_SYS_NICE` is still in permitted set, it can be raised again.
    let perm_sys_nice = caps::has_cap(None, CapSet::Permitted, Capability::CAP_SYS_NICE);
    assert!(perm_sys_nice.is_ok());
    if !perm_sys_nice? {
        return Err(
            "Try running this again as root/sudo or with CAP_SYS_NICE file capability!".into(),
        );
    }
    let r = caps::raise(None, CapSet::Effective, Capability::CAP_SYS_NICE);
    assert!(r.is_ok());
    println!("Raised CAP_SYS_NICE.");

    // With CAP_SYS_NICE, priority can be raised further.
    let r = renice(-20);
    assert_eq!(r, 0);
    println!("Privileged, raised priority to -20.");
    println!("-> Current process priority is {}.", proc_nice());

    Ok(())
}

#[cfg(target_env = "musl")]
const PRIO_PROCESS: i32 = libc::PRIO_PROCESS;
#[cfg(not(target_env = "musl"))]
const PRIO_PROCESS: u32 = libc::PRIO_PROCESS as u32;

fn renice(prio: libc::c_int) -> libc::c_int {
    // This is not proper logic, as it does not record errno value on error.
    unsafe { libc::setpriority(PRIO_PROCESS, 0, prio) }
}

fn proc_nice() -> libc::c_int {
    // This is not proper logic, as it does not special-case -1 nor record errno.
    let r = unsafe { libc::getpriority(PRIO_PROCESS as u32, 0) };
    if r == -1 {
        panic!("getpriority failed.");
    }
    r
}