setpriv: code shrink, and grouping capability code together

function                                             old     new   delta
static.versions                                        -       3      +3
getcaps                                              174     149     -25

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-07-07 16:00:07 +02:00
parent 6842d00ceb
commit cf5748cc89

View File

@ -167,15 +167,12 @@ static const char *const capabilities[] = {
};
# endif /* FEATURE_SETPRIV_CAPABILITY_NAMES */
#endif /* FEATURE_SETPRIV_CAPABILITIES */
#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
static void getcaps(struct caps *caps)
{
int versions[] = {
_LINUX_CAPABILITY_U32S_3,
_LINUX_CAPABILITY_U32S_2,
_LINUX_CAPABILITY_U32S_1,
static const uint8_t versions[] = {
_LINUX_CAPABILITY_U32S_3, /* = 2 (fits into byte) */
_LINUX_CAPABILITY_U32S_2, /* = 2 */
_LINUX_CAPABILITY_U32S_1, /* = 1 */
};
int i;
@ -206,6 +203,91 @@ static void getcaps(struct caps *caps)
if (capget(&caps->header, caps->data) < 0)
bb_simple_perror_msg_and_die("capget");
}
static void parse_cap(unsigned long *index, const char *cap)
{
unsigned long i;
switch (cap[0]) {
case '-':
break;
case '+':
break;
default:
bb_error_msg_and_die("invalid capability '%s'", cap);
break;
}
cap++;
if ((sscanf(cap, "cap_%lu", &i)) == 1) {
if (!cap_valid(i))
bb_error_msg_and_die("unsupported capability '%s'", cap);
*index = i;
return;
}
# if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
if (strcmp(capabilities[i], cap) != 0)
continue;
if (!cap_valid(i))
bb_error_msg_and_die("unsupported capability '%s'", cap);
*index = i;
return;
}
# endif
bb_error_msg_and_die("unknown capability '%s'", cap);
}
static void set_inh_caps(char *capstring)
{
struct caps caps;
getcaps(&caps);
capstring = strtok(capstring, ",");
while (capstring) {
unsigned long cap;
parse_cap(&cap, capstring);
if (CAP_TO_INDEX(cap) >= caps.u32s)
bb_error_msg_and_die("invalid capability cap");
if (capstring[0] == '+')
caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap);
else
caps.data[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap);
capstring = strtok(NULL, ",");
}
if ((capset(&caps.header, caps.data)) < 0)
bb_perror_msg_and_die("capset");
if (ENABLE_FEATURE_CLEAN_UP)
free(caps.data);
}
static void set_ambient_caps(char *string)
{
char *cap;
cap = strtok(string, ",");
while (cap) {
unsigned long index;
parse_cap(&index, cap);
if (cap[0] == '+') {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0)
bb_perror_msg("cap_ambient_raise");
} else {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, index, 0, 0) < 0)
bb_perror_msg("cap_ambient_lower");
}
cap = strtok(NULL, ",");
}
}
#endif /* FEATURE_SETPRIV_CAPABILITIES */
#if ENABLE_FEATURE_SETPRIV_DUMP
@ -317,93 +399,6 @@ static int dump(void)
}
#endif /* FEATURE_SETPRIV_DUMP */
#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
static void parse_cap(unsigned long *index, const char *cap)
{
unsigned long i;
switch (cap[0]) {
case '-':
break;
case '+':
break;
default:
bb_error_msg_and_die("invalid capability '%s'", cap);
break;
}
cap++;
if ((sscanf(cap, "cap_%lu", &i)) == 1) {
if (!cap_valid(i))
bb_error_msg_and_die("unsupported capability '%s'", cap);
*index = i;
return;
}
# if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES
for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
if (strcmp(capabilities[i], cap) != 0)
continue;
if (!cap_valid(i))
bb_error_msg_and_die("unsupported capability '%s'", cap);
*index = i;
return;
}
# endif
bb_error_msg_and_die("unknown capability '%s'", cap);
}
static void set_inh_caps(char *capstring)
{
struct caps caps;
getcaps(&caps);
capstring = strtok(capstring, ",");
while (capstring) {
unsigned long cap;
parse_cap(&cap, capstring);
if (CAP_TO_INDEX(cap) >= caps.u32s)
bb_error_msg_and_die("invalid capability cap");
if (capstring[0] == '+')
caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap);
else
caps.data[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap);
capstring = strtok(NULL, ",");
}
if ((capset(&caps.header, caps.data)) < 0)
bb_perror_msg_and_die("capset");
if (ENABLE_FEATURE_CLEAN_UP)
free(caps.data);
}
static void set_ambient_caps(char *string)
{
char *cap;
cap = strtok(string, ",");
while (cap) {
unsigned long index;
parse_cap(&index, cap);
if (cap[0] == '+') {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0)
bb_perror_msg("cap_ambient_raise");
} else {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, index, 0, 0) < 0)
bb_perror_msg("cap_ambient_lower");
}
cap = strtok(NULL, ",");
}
}
#endif /* FEATURE_SETPRIV_CAPABILITIES */
int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int setpriv_main(int argc UNUSED_PARAM, char **argv)
{