#[allow(missing_docs)]
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Deserialize, Serialize)]
#[derive(EnumIter)]
#[serde(deny_unknown_fields)]
pub enum Capability
{
AuditControl = CAP_AUDIT_CONTROL,
AuditRead = CAP_AUDIT_READ,
AuditWrite = CAP_AUDIT_WRITE,
BlockSuspend = CAP_BLOCK_SUSPEND,
Broadcast = CAP_NET_BROADCAST,
Chown = CAP_CHOWN,
DiscretionaryAccessControlBypass = CAP_DAC_OVERRIDE,
DiscretionaryAccessControlFileReadBypass = CAP_DAC_READ_SEARCH,
FileOwnerBypass = CAP_FOWNER,
FileSetId = CAP_FSETID,
LockMemory = CAP_IPC_LOCK,
IpcOwner = CAP_IPC_OWNER,
Kill = CAP_KILL,
Lease = CAP_LEASE,
Immutable = CAP_LINUX_IMMUTABLE,
MandatoryAccessControlBypass = CAP_MAC_ADMIN,
MandatoryAccessControlOverride = CAP_MAC_OVERRIDE,
MakeNodes = CAP_MKNOD,
SystemAdministration = CAP_SYS_ADMIN,
NetworkAdministration = CAP_NET_ADMIN,
BindPortsBelow1024 = CAP_NET_BIND_SERVICE,
NetRaw = CAP_NET_RAW,
SetUid = CAP_SETUID,
SetGid = CAP_SETGID,
SetFileCapabilities = CAP_SETFCAP,
SetProcessCapabilities = CAP_SETPCAP,
RebootAndKexecLoad = CAP_SYS_BOOT,
Chroot = CAP_SYS_CHROOT,
KernelModule = CAP_SYS_MODULE,
Nice = CAP_SYS_NICE,
ProcessAccounting = CAP_SYS_PACCT,
PTrace = CAP_SYS_PTRACE,
RawIO = CAP_SYS_RAWIO,
Resource = CAP_SYS_RESOURCE,
Time = CAP_SYS_TIME,
TtyConfig = CAP_SYS_TTY_CONFIG,
Syslog = CAP_SYSLOG,
WakeAlarm = CAP_WAKE_ALARM,
}
bit_set_aware!(Capability);
impl Into<u16> for Capability
{
#[inline(always)]
fn into(self) -> u16
{
self as u8 as u16
}
}
impl BitSetAware for Capability
{
const LinuxMaximum: u32 = CAP_LAST_CAP as u32;
const InclusiveMinimum: Self = unsafe { transmute(0u8) };
const InclusiveMaximum: Self = unsafe { transmute(Self::LinuxMaximum as u8) };
#[inline(always)]
fn from_validated_u16(value: u16) -> Self
{
debug_assert!((value as u32) < Self::LinuxMaximum);
unsafe { transmute(value as u8) }
}
}
impl Capability
{
#[inline(always)]
pub fn add_to_current_thread_ambient_set(self) -> Result<(), AmbientCapabilityError>
{
use self::AmbientCapabilityError::*;
process_control_wrapper3
(
PR_CAP_AMBIENT,
PR_CAP_AMBIENT_RAISE as usize,
self as usize,
result_must_be_zero,
|error_number| match error_number.0
{
EPERM => Err(PermissionDenied),
EINVAL => Err(CapabilityNotKnownByThisLinuxKernel),
unexpected @ _ => panic!("Unexpected error code '{}' from prctl()", unexpected),
}
)
}
#[inline(always)]
pub fn remove_from_current_thread_ambient_set(self) -> Result<(), AmbientCapabilityError>
{
use self::AmbientCapabilityError::*;
process_control_wrapper3
(
PR_CAP_AMBIENT,
PR_CAP_AMBIENT_LOWER as usize,
self as usize,
result_must_be_zero,
|error_number| match error_number.0
{
EPERM => Err(PermissionDenied),
EINVAL => Err(CapabilityNotKnownByThisLinuxKernel),
unexpected @ _ => panic!("Unexpected error code '{}' from prctl()", unexpected),
}
)
}
#[inline(always)]
pub fn is_in_current_thread_ambient_set(self) -> Result<bool, AmbientCapabilityError>
{
use self::AmbientCapabilityError::*;
process_control_wrapper3
(
PR_CAP_AMBIENT,
PR_CAP_AMBIENT_IS_SET as usize,
self as usize,
|non_negative_result| match non_negative_result
{
0 => Ok(false),
1 => Ok(true),
_ => unreachable_code(format_args!("Non-boolean result from `prctl()`"))
},
|error_number| match error_number.0
{
EINVAL => Err(CapabilityNotKnownByThisLinuxKernel),
unexpected @ _ => panic!("Unexpected error code '{}' from prctl()", unexpected),
}
)
}
#[inline(always)]
pub fn is_in_current_thread_bounding_set(self) -> Option<bool>
{
let result: Result<Option<bool>, io::Error> = process_control_wrapper2
(
PR_CAPBSET_READ,
self as usize,
|non_negative_result| match non_negative_result
{
0 => Ok(Some(false)),
1 => Ok(Some(true)),
_ => unreachable_code(format_args!("Non-boolean result from `prctl()`"))
},
|error_number| match error_number.0
{
EINVAL => Ok(None),
unexpected @ _ => panic!("Unexpected error code '{}' from prctl()", unexpected),
}
);
result.unwrap()
}
#[inline(always)]
pub fn remove_from_current_thread_bounding_set(self) -> Result<(), ()>
{
process_control_wrapper2
(
PR_CAPBSET_DROP,
self as usize,
result_must_be_zero,
|error_number| match error_number.0
{
EPERM => Err(()),
EINVAL => panic!("Kernel does not support 'file' capabilities. Or capability `{:?}` is not a valid capability on this kernel", self),
unexpected @ _ => panic!("Unexpected error code '{}' from prctl()", unexpected),
}
)
}
}