aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2017-07-06 22:47:16 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-06 22:47:16 +0200
commitad63102943d3f648b37b65f5c734b2c345a3b280 (patch)
tree444262f9af66ab40a9669bb906241bb8df9124ba
parent10c53b85c992afca47e7a70f05379a5038bdaeb9 (diff)
downloadbusybox-w32-ad63102943d3f648b37b65f5c734b2c345a3b280.tar.gz
busybox-w32-ad63102943d3f648b37b65f5c734b2c345a3b280.tar.bz2
busybox-w32-ad63102943d3f648b37b65f5c734b2c345a3b280.zip
setpriv: dump inheritable capability set
The setpriv executable from util-linux also dumps out information on the different capability sets known by the kernel. By default, these are the inheritable capabilities, bounding capabilities and (not yet released) the ambient capabilities, which have been introduced with Linux 4.3. This patch introduces the ability to dump the set of inheritable capabilities. By default, setpriv(1) identifies capabilities by their human-readable name, for example 'net_admin'. For unknown capabilities, though, it does instead use the capability's value, for example 'cap_12', which is equivalent to 'net_admin'. As there is no kernel interface to retrieve capability names by their index, we have to declare these ourselves, which adds to setpriv's size. To counteract, using the human-readble name has been made configurable. The following sizes are with the 'FEATURE_SETPRIV_CAPABILITY_NAMES' enabled: function old new delta .rodata 145969 146405 +436 setpriv_main 467 842 +375 capabilities - 304 +304 And with 'FEATURE_SETPRIV_CAPABILITY_NAMES' disabled: function old new delta setpriv_main 467 838 +371 .rodata 145969 146101 +132 Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/setpriv.c151
1 files changed, 147 insertions, 4 deletions
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index 8d3f25875..a509204a2 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -23,6 +23,26 @@
23//config: help 23//config: help
24//config: Enables the "--dump" switch to print out the current privilege 24//config: Enables the "--dump" switch to print out the current privilege
25//config: state. This is helpful for diagnosing problems. 25//config: state. This is helpful for diagnosing problems.
26//config:
27//config:config FEATURE_SETPRIV_CAPABILITIES
28//config: bool "Support capabilities"
29//config: default y
30//config: depends on SETPRIV
31//config: help
32//config: Capabilities can be used to grant processes additional rights
33//config: without the necessity to always execute as the root user.
34//config: Enabling this option enables "--dump" to show information on
35//config: capabilities.
36//config:
37//config:config FEATURE_SETPRIV_CAPABILITY_NAMES
38//config: bool "Support capability names"
39//config: default y
40//config: depends on SETPRIV && FEATURE_SETPRIV_CAPABILITIES
41//config: help
42//config: Capabilities can be either referenced via a human-readble name,
43//config: e.g. "net_admin", or using their index, e.g. "cap_12". Enabling
44//config: this option allows using the human-readable names in addition to
45//config: the index-based names.
26 46
27//applet:IF_SETPRIV(APPLET(setpriv, BB_DIR_BIN, BB_SUID_DROP)) 47//applet:IF_SETPRIV(APPLET(setpriv, BB_DIR_BIN, BB_SUID_DROP))
28 48
@@ -55,6 +75,10 @@
55// --selinux-label <label> set SELinux label 75// --selinux-label <label> set SELinux label
56// --apparmor-profile <pr> set AppArmor profile 76// --apparmor-profile <pr> set AppArmor profile
57 77
78#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
79#include <linux/capability.h>
80#include <sys/capability.h>
81#endif
58#include <sys/prctl.h> 82#include <sys/prctl.h>
59#include "libbb.h" 83#include "libbb.h"
60 84
@@ -74,13 +98,106 @@ enum {
74 OPT_NNP = (1 << OPTBIT_NNP), 98 OPT_NNP = (1 << OPTBIT_NNP),
75}; 99};
76 100
101#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
102struct caps {
103 struct __user_cap_header_struct header;
104 cap_user_data_t data;
105 int u32s;
106};
107
108#if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
109static const char *const capabilities[] = {
110 "chown",
111 "dac_override",
112 "dac_read_search",
113 "fowner",
114 "fsetid",
115 "kill",
116 "setgid",
117 "setuid",
118 "setpcap",
119 "linux_immutable",
120 "net_bind_service",
121 "net_broadcast",
122 "net_admin",
123 "net_raw",
124 "ipc_lock",
125 "ipc_owner",
126 "sys_module",
127 "sys_rawio",
128 "sys_chroot",
129 "sys_ptrace",
130 "sys_pacct",
131 "sys_admin",
132 "sys_boot",
133 "sys_nice",
134 "sys_resource",
135 "sys_time",
136 "sys_tty_config",
137 "mknod",
138 "lease",
139 "audit_write",
140 "audit_control",
141 "setfcap",
142 "mac_override",
143 "mac_admin",
144 "syslog",
145 "wake_alarm",
146 "block_suspend",
147 "audit_read",
148};
149#endif /* FEATURE_SETPRIV_CAPABILITY_NAMES */
150
151#endif /* FEATURE_SETPRIV_CAPABILITIES */
152
77#if ENABLE_FEATURE_SETPRIV_DUMP 153#if ENABLE_FEATURE_SETPRIV_DUMP
154# if ENABLE_FEATURE_SETPRIV_CAPABILITIES
155static void getcaps(struct caps *caps)
156{
157 int versions[] = {
158 _LINUX_CAPABILITY_U32S_3,
159 _LINUX_CAPABILITY_U32S_2,
160 _LINUX_CAPABILITY_U32S_1,
161 };
162 int i;
163
164 caps->header.pid = 0;
165 for (i = 0; i < ARRAY_SIZE(versions); i++) {
166 caps->header.version = versions[i];
167 if (capget(&caps->header, NULL) == 0)
168 goto got_it;
169 }
170 bb_simple_perror_msg_and_die("capget");
171 got_it:
172
173 switch (caps->header.version) {
174 case _LINUX_CAPABILITY_VERSION_1:
175 caps->u32s = _LINUX_CAPABILITY_U32S_1;
176 break;
177 case _LINUX_CAPABILITY_VERSION_2:
178 caps->u32s = _LINUX_CAPABILITY_U32S_2;
179 break;
180 case _LINUX_CAPABILITY_VERSION_3:
181 caps->u32s = _LINUX_CAPABILITY_U32S_3;
182 break;
183 default:
184 bb_error_msg_and_die("unsupported capability version");
185 }
186
187 caps->data = xmalloc(sizeof(caps->data[0]) * caps->u32s);
188 if (capget(&caps->header, caps->data) < 0)
189 bb_simple_perror_msg_and_die("capget");
190}
191# endif /* FEATURE_SETPRIV_CAPABILITIES */
192
78static int dump(void) 193static int dump(void)
79{ 194{
195 IF_FEATURE_SETPRIV_CAPABILITIES(struct caps caps;)
196 const char *fmt;
80 uid_t ruid, euid, suid; 197 uid_t ruid, euid, suid;
81 gid_t rgid, egid, sgid; 198 gid_t rgid, egid, sgid;
82 gid_t *gids; 199 gid_t *gids;
83 int ngids, nnp; 200 int i, ngids, nnp;
84 201
85 getresuid(&ruid, &euid, &suid); /* never fails in Linux */ 202 getresuid(&ruid, &euid, &suid); /* never fails in Linux */
86 getresgid(&rgid, &egid, &sgid); /* never fails in Linux */ 203 getresgid(&rgid, &egid, &sgid); /* never fails in Linux */
@@ -100,8 +217,7 @@ static int dump(void)
100 if (ngids == 0) { 217 if (ngids == 0) {
101 printf("[none]"); 218 printf("[none]");
102 } else { 219 } else {
103 const char *fmt = ",%u" + 1; 220 fmt = ",%u" + 1;
104 int i;
105 for (i = 0; i < ngids; i++) { 221 for (i = 0; i < ngids; i++) {
106 printf(fmt, (unsigned)gids[i]); 222 printf(fmt, (unsigned)gids[i]);
107 fmt = ",%u"; 223 fmt = ",%u";
@@ -109,8 +225,35 @@ static int dump(void)
109 } 225 }
110 printf("\nno_new_privs: %d\n", nnp); 226 printf("\nno_new_privs: %d\n", nnp);
111 227
112 if (ENABLE_FEATURE_CLEAN_UP) 228# if ENABLE_FEATURE_SETPRIV_CAPABILITIES
229 getcaps(&caps);
230 printf("Inheritable capabilities: ");
231 fmt = "";
232 for (i = 0; cap_valid(i); i++) {
233 unsigned idx = CAP_TO_INDEX(i);
234 if (idx >= caps.u32s) {
235 printf("\nindex: %u u32s: %u capability: %u\n", idx, caps.u32s, i);
236 bb_error_msg_and_die("unsupported capability");
237 }
238 if (caps.data[idx].inheritable & CAP_TO_MASK(i)) {
239# if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
240 if (i < ARRAY_SIZE(capabilities))
241 printf("%s%s", fmt, capabilities[i]);
242 else
243# endif
244 printf("%scap_%u", fmt, i);
245 fmt = ",";
246 }
247 }
248 if (!fmt[0])
249 printf("[none]");
250 bb_putchar('\n');
251# endif
252
253 if (ENABLE_FEATURE_CLEAN_UP) {
254 IF_FEATURE_SETPRIV_CAPABILITIES(free(caps.data);)
113 free(gids); 255 free(gids);
256 }
114 return EXIT_SUCCESS; 257 return EXIT_SUCCESS;
115} 258}
116#endif /* FEATURE_SETPRIV_DUMP */ 259#endif /* FEATURE_SETPRIV_DUMP */