xref: /aosp_15_r20/external/crosvm/devices/src/virtio/fs/caps.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2021 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::ffi::c_void;
6 use std::io;
7 use std::os::raw::c_int;
8 
9 #[allow(non_camel_case_types)]
10 type cap_t = *mut c_void;
11 
12 #[allow(non_camel_case_types)]
13 pub type cap_value_t = u32;
14 
15 #[allow(non_camel_case_types)]
16 type cap_flag_t = u32;
17 
18 #[allow(non_camel_case_types)]
19 type cap_flag_value_t = i32;
20 
21 #[link(name = "cap")]
22 extern "C" {
cap_free(ptr: *mut c_void) -> c_int23     fn cap_free(ptr: *mut c_void) -> c_int;
24 
cap_set_flag( c: cap_t, f: cap_flag_t, ncap: c_int, caps: *const cap_value_t, val: cap_flag_value_t, ) -> c_int25     fn cap_set_flag(
26         c: cap_t,
27         f: cap_flag_t,
28         ncap: c_int,
29         caps: *const cap_value_t,
30         val: cap_flag_value_t,
31     ) -> c_int;
32 
cap_get_proc() -> cap_t33     fn cap_get_proc() -> cap_t;
cap_set_proc(cap: cap_t) -> c_int34     fn cap_set_proc(cap: cap_t) -> c_int;
35 }
36 
37 #[repr(u32)]
38 pub enum Capability {
39     Chown = 0,
40     DacOverride = 1,
41     DacReadSearch = 2,
42     Fowner = 3,
43     Fsetid = 4,
44     Kill = 5,
45     Setgid = 6,
46     Setuid = 7,
47     Setpcap = 8,
48     LinuxImmutable = 9,
49     NetBindService = 10,
50     NetBroadcast = 11,
51     NetAdmin = 12,
52     NetRaw = 13,
53     IpcLock = 14,
54     IpcOwner = 15,
55     SysModule = 16,
56     SysRawio = 17,
57     SysChroot = 18,
58     SysPtrace = 19,
59     SysPacct = 20,
60     SysAdmin = 21,
61     SysBoot = 22,
62     SysNice = 23,
63     SysResource = 24,
64     SysTime = 25,
65     SysTtyConfig = 26,
66     Mknod = 27,
67     Lease = 28,
68     AuditWrite = 29,
69     AuditControl = 30,
70     Setfcap = 31,
71     MacOverride = 32,
72     MacAdmin = 33,
73     Syslog = 34,
74     WakeAlarm = 35,
75     BlockSuspend = 36,
76     AuditRead = 37,
77     Last,
78 }
79 
80 impl From<Capability> for cap_value_t {
from(c: Capability) -> cap_value_t81     fn from(c: Capability) -> cap_value_t {
82         c as cap_value_t
83     }
84 }
85 
86 #[repr(u32)]
87 pub enum Set {
88     Effective = 0,
89     Permitted = 1,
90     Inheritable = 2,
91 }
92 
93 impl From<Set> for cap_flag_t {
from(s: Set) -> cap_flag_t94     fn from(s: Set) -> cap_flag_t {
95         s as cap_flag_t
96     }
97 }
98 
99 #[repr(i32)]
100 pub enum Value {
101     Clear = 0,
102     Set = 1,
103 }
104 
105 impl From<Value> for cap_flag_value_t {
from(v: Value) -> cap_flag_value_t106     fn from(v: Value) -> cap_flag_value_t {
107         v as cap_flag_value_t
108     }
109 }
110 
111 pub struct Caps(cap_t);
112 
113 impl Caps {
114     /// Get the capabilities for the current thread.
for_current_thread() -> io::Result<Caps>115     pub fn for_current_thread() -> io::Result<Caps> {
116         // SAFETY:
117         // Safe because this doesn't modify any memory and we check the return value.
118         let caps = unsafe { cap_get_proc() };
119         if caps.is_null() {
120             Err(io::Error::last_os_error())
121         } else {
122             Ok(Caps(caps))
123         }
124     }
125 
126     /// Update the capabilities described by `self` by setting or clearing `caps` in `set`.
update(&mut self, caps: &[Capability], set: Set, value: Value) -> io::Result<()>127     pub fn update(&mut self, caps: &[Capability], set: Set, value: Value) -> io::Result<()> {
128         // SAFETY:
129         // Safe because this only modifies the memory pointed to by `self.0` and we check the return
130         // value.
131         let ret = unsafe {
132             cap_set_flag(
133                 self.0,
134                 set.into(),
135                 caps.len() as c_int,
136                 // It's safe to cast this pointer because `Capability` is #[repr(u32)]
137                 caps.as_ptr() as *const cap_value_t,
138                 value.into(),
139             )
140         };
141 
142         if ret == 0 {
143             Ok(())
144         } else {
145             Err(io::Error::last_os_error())
146         }
147     }
148 
149     /// Apply the capabilities described by `self` to the current thread.
apply(&self) -> io::Result<()>150     pub fn apply(&self) -> io::Result<()> {
151         // SAFETY: trivially safe
152         if unsafe { cap_set_proc(self.0) } == 0 {
153             Ok(())
154         } else {
155             Err(io::Error::last_os_error())
156         }
157     }
158 }
159 
160 impl Drop for Caps {
drop(&mut self)161     fn drop(&mut self) {
162         // SAFETY: cap_t is allocated from `Self`
163         unsafe {
164             cap_free(self.0);
165         }
166     }
167 }
168