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