lsscsi: fix xchdir("..") from symlink in /sys/bus/scsi/devices
[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_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 }