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