diff options
Diffstat (limited to 'libbb/capability.c')
-rw-r--r-- | libbb/capability.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/libbb/capability.c b/libbb/capability.c new file mode 100644 index 000000000..f60062bfc --- /dev/null +++ b/libbb/capability.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 by <assafgordon@gmail.com> | ||
3 | * | ||
4 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | //kbuild:lib-$(CONFIG_PLATFORM_LINUX) += capability.o | ||
7 | |||
8 | #include <linux/capability.h> | ||
9 | // #include <sys/capability.h> | ||
10 | // This header is in libcap, but the functions are in libc. | ||
11 | // Comment in the header says this above capset/capget: | ||
12 | /* system calls - look to libc for function to system call mapping */ | ||
13 | extern int capset(cap_user_header_t header, cap_user_data_t data); | ||
14 | extern int capget(cap_user_header_t header, const cap_user_data_t data); | ||
15 | // so for bbox, let's just repeat the declarations. | ||
16 | // This way, libcap needs not be installed in build environment. | ||
17 | #include "libbb.h" | ||
18 | |||
19 | static const char *const capabilities[] = { | ||
20 | "chown", | ||
21 | "dac_override", | ||
22 | "dac_read_search", | ||
23 | "fowner", | ||
24 | "fsetid", | ||
25 | "kill", | ||
26 | "setgid", | ||
27 | "setuid", | ||
28 | "setpcap", | ||
29 | "linux_immutable", | ||
30 | "net_bind_service", | ||
31 | "net_broadcast", | ||
32 | "net_admin", | ||
33 | "net_raw", | ||
34 | "ipc_lock", | ||
35 | "ipc_owner", | ||
36 | "sys_module", | ||
37 | "sys_rawio", | ||
38 | "sys_chroot", | ||
39 | "sys_ptrace", | ||
40 | "sys_pacct", | ||
41 | "sys_admin", | ||
42 | "sys_boot", | ||
43 | "sys_nice", | ||
44 | "sys_resource", | ||
45 | "sys_time", | ||
46 | "sys_tty_config", | ||
47 | "mknod", | ||
48 | "lease", | ||
49 | "audit_write", | ||
50 | "audit_control", | ||
51 | "setfcap", | ||
52 | "mac_override", | ||
53 | "mac_admin", | ||
54 | "syslog", | ||
55 | "wake_alarm", | ||
56 | "block_suspend", | ||
57 | "audit_read", | ||
58 | }; | ||
59 | |||
60 | unsigned FAST_FUNC cap_name_to_number(const char *cap) | ||
61 | { | ||
62 | unsigned i, n; | ||
63 | |||
64 | if ((sscanf(cap, "cap_%u", &n)) == 1) { | ||
65 | i = n; | ||
66 | goto found; | ||
67 | } | ||
68 | for (i = 0; i < ARRAY_SIZE(capabilities); i++) { | ||
69 | if (strcasecmp(capabilities[i], cap) != 0) | ||
70 | goto found; | ||
71 | } | ||
72 | bb_error_msg_and_die("unknown capability '%s'", cap); | ||
73 | |||
74 | found: | ||
75 | if (!cap_valid(i)) | ||
76 | bb_error_msg_and_die("unknown capability '%s'", cap); | ||
77 | return i; | ||
78 | } | ||
79 | |||
80 | void FAST_FUNC printf_cap(const char *pfx, unsigned cap_no) | ||
81 | { | ||
82 | if (cap_no < ARRAY_SIZE(capabilities)) { | ||
83 | printf("%s%s", pfx, capabilities[cap_no]); | ||
84 | return; | ||
85 | } | ||
86 | printf("%scap_%u", pfx, cap_no); | ||
87 | } | ||
88 | |||
89 | DEFINE_STRUCT_CAPS; | ||
90 | |||
91 | void FAST_FUNC getcaps(void *arg) | ||
92 | { | ||
93 | static const uint8_t versions[] = { | ||
94 | _LINUX_CAPABILITY_U32S_3, /* = 2 (fits into byte) */ | ||
95 | _LINUX_CAPABILITY_U32S_2, /* = 2 */ | ||
96 | _LINUX_CAPABILITY_U32S_1, /* = 1 */ | ||
97 | }; | ||
98 | int i; | ||
99 | struct caps *caps = arg; | ||
100 | |||
101 | caps->header.pid = 0; | ||
102 | for (i = 0; i < ARRAY_SIZE(versions); i++) { | ||
103 | caps->header.version = versions[i]; | ||
104 | if (capget(&caps->header, NULL) == 0) | ||
105 | goto got_it; | ||
106 | } | ||
107 | bb_simple_perror_msg_and_die("capget"); | ||
108 | got_it: | ||
109 | |||
110 | switch (caps->header.version) { | ||
111 | case _LINUX_CAPABILITY_VERSION_1: | ||
112 | caps->u32s = _LINUX_CAPABILITY_U32S_1; | ||
113 | break; | ||
114 | case _LINUX_CAPABILITY_VERSION_2: | ||
115 | caps->u32s = _LINUX_CAPABILITY_U32S_2; | ||
116 | break; | ||
117 | case _LINUX_CAPABILITY_VERSION_3: | ||
118 | caps->u32s = _LINUX_CAPABILITY_U32S_3; | ||
119 | break; | ||
120 | default: | ||
121 | bb_error_msg_and_die("unsupported capability version"); | ||
122 | } | ||
123 | |||
124 | if (capget(&caps->header, caps->data) != 0) | ||
125 | bb_simple_perror_msg_and_die("capget"); | ||
126 | } | ||