aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 */