/* * Copyright (C) 2017 by <assafgordon@gmail.com> * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //kbuild:lib-$(CONFIG_PLATFORM_LINUX) += capability.o #include <linux/capability.h> // #include <sys/capability.h> // This header is in libcap, but the functions are in libc. // Comment in the header says this above capset/capget: /* system calls - look to libc for function to system call mapping */ extern int capset(cap_user_header_t header, cap_user_data_t data); extern int capget(cap_user_header_t header, const cap_user_data_t data); // so for bbox, let's just repeat the declarations. // This way, libcap needs not be installed in build environment. #include "libbb.h" static const char *const capabilities[] = { "chown", "dac_override", "dac_read_search", "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", "linux_immutable", "net_bind_service", "net_broadcast", "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", "sys_boot", "sys_nice", "sys_resource", "sys_time", "sys_tty_config", "mknod", "lease", "audit_write", "audit_control", "setfcap", "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", "audit_read", }; unsigned FAST_FUNC cap_name_to_number(const char *cap) { unsigned i, n; if ((sscanf(cap, "cap_%u", &n)) == 1) { i = n; goto found; } for (i = 0; i < ARRAY_SIZE(capabilities); i++) { if (strcasecmp(capabilities[i], cap) != 0) goto found; } bb_error_msg_and_die("unknown capability '%s'", cap); found: if (!cap_valid(i)) bb_error_msg_and_die("unknown capability '%s'", cap); return i; } void FAST_FUNC printf_cap(const char *pfx, unsigned cap_no) { if (cap_no < ARRAY_SIZE(capabilities)) { printf("%s%s", pfx, capabilities[cap_no]); return; } printf("%scap_%u", pfx, cap_no); } DEFINE_STRUCT_CAPS; void FAST_FUNC getcaps(void *arg) { static const uint8_t versions[] = { _LINUX_CAPABILITY_U32S_3, /* = 2 (fits into byte) */ _LINUX_CAPABILITY_U32S_2, /* = 2 */ _LINUX_CAPABILITY_U32S_1, /* = 1 */ }; int i; struct caps *caps = arg; caps->header.pid = 0; for (i = 0; i < ARRAY_SIZE(versions); i++) { caps->header.version = versions[i]; if (capget(&caps->header, NULL) == 0) goto got_it; } bb_simple_perror_msg_and_die("capget"); got_it: switch (caps->header.version) { case _LINUX_CAPABILITY_VERSION_1: caps->u32s = _LINUX_CAPABILITY_U32S_1; break; case _LINUX_CAPABILITY_VERSION_2: caps->u32s = _LINUX_CAPABILITY_U32S_2; break; case _LINUX_CAPABILITY_VERSION_3: caps->u32s = _LINUX_CAPABILITY_U32S_3; break; default: bb_error_msg_and_die("unsupported capability version"); } if (capget(&caps->header, caps->data) != 0) bb_simple_perror_msg_and_die("capget"); }