1 // Copyright 2021 The Chromium OS Authors. All rights reserved. 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 // Safe because this doesn't modify any memory and we check the return value. 117 let caps = unsafe { cap_get_proc() }; 118 if caps.is_null() { 119 Err(io::Error::last_os_error()) 120 } else { 121 Ok(Caps(caps)) 122 } 123 } 124 125 /// Update the capabilities described by `self` by setting or clearing `caps` in `set`. update(&mut self, caps: &[Capability], set: Set, value: Value) -> io::Result<()>126 pub fn update(&mut self, caps: &[Capability], set: Set, value: Value) -> io::Result<()> { 127 // Safe because this only modifies the memory pointed to by `self.0` and we check the return 128 // value. 129 let ret = unsafe { 130 cap_set_flag( 131 self.0, 132 set.into(), 133 caps.len() as c_int, 134 // It's safe to cast this pointer because `Capability` is #[repr(u32)] 135 caps.as_ptr() as *const cap_value_t, 136 value.into(), 137 ) 138 }; 139 140 if ret == 0 { 141 Ok(()) 142 } else { 143 Err(io::Error::last_os_error()) 144 } 145 } 146 147 /// Apply the capabilities described by `self` to the current thread. apply(&self) -> io::Result<()>148 pub fn apply(&self) -> io::Result<()> { 149 if unsafe { cap_set_proc(self.0) } == 0 { 150 Ok(()) 151 } else { 152 Err(io::Error::last_os_error()) 153 } 154 } 155 } 156 157 impl Drop for Caps { drop(&mut self)158 fn drop(&mut self) { 159 unsafe { 160 cap_free(self.0); 161 } 162 } 163 } 164