You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
3.7 KiB
174 lines
3.7 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/capability.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
/*
|
|
* tests for cap_launch.
|
|
*/
|
|
|
|
#define MORE_THAN_ENOUGH 20
|
|
#define NO_MORE 1
|
|
|
|
struct test_case_s {
|
|
int pass_on;
|
|
const char *chroot;
|
|
uid_t uid;
|
|
gid_t gid;
|
|
int ngroups;
|
|
const gid_t groups[MORE_THAN_ENOUGH];
|
|
const char *args[MORE_THAN_ENOUGH];
|
|
const char **envp;
|
|
const char *iab;
|
|
cap_mode_t mode;
|
|
int result;
|
|
};
|
|
|
|
#ifdef WITH_PTHREADS
|
|
#include <pthread.h>
|
|
#else /* WITH_PTHREADS */
|
|
#endif /* WITH_PTHREADS */
|
|
|
|
int main(int argc, char **argv) {
|
|
static struct test_case_s vs[] = {
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--", "-c", "echo hello" },
|
|
.result = 0
|
|
},
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--is-uid=123" },
|
|
.result = 256
|
|
},
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--is-uid=123" },
|
|
.result = 0,
|
|
.uid = 123,
|
|
},
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--is-gid=123" },
|
|
.result = 0,
|
|
.gid = 123,
|
|
.ngroups = 1,
|
|
.groups = { 456 },
|
|
.iab = "",
|
|
},
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--dropped=cap_chown",
|
|
"--has-i=cap_chown" },
|
|
.result = 0,
|
|
.iab = "!%cap_chown"
|
|
},
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--dropped=cap_chown",
|
|
"--has-i=cap_chown", "--is-uid=234",
|
|
"--has-a=cap_chown", "--has-p=cap_chown" },
|
|
.uid = 234,
|
|
.result = 0,
|
|
.iab = "!^cap_chown"
|
|
},
|
|
{
|
|
.args = { "../progs/tcapsh-static", "--inmode=NOPRIV",
|
|
"--has-no-new-privs" },
|
|
.result = 0,
|
|
.mode = CAP_MODE_NOPRIV
|
|
},
|
|
{
|
|
.args = { "/noop" },
|
|
.result = 0,
|
|
.chroot = ".",
|
|
},
|
|
{
|
|
.pass_on = NO_MORE
|
|
},
|
|
};
|
|
|
|
cap_t orig = cap_get_proc();
|
|
|
|
int success = 1, i;
|
|
for (i=0; vs[i].pass_on != NO_MORE; i++) {
|
|
const struct test_case_s *v = &vs[i];
|
|
printf("[%d] test should %s\n", i,
|
|
v->result ? "generate error" : "work");
|
|
cap_launch_t attr = cap_new_launcher(v->args[0], v->args, v->envp);
|
|
if (v->chroot) {
|
|
cap_launcher_set_chroot(attr, v->chroot);
|
|
}
|
|
if (v->uid) {
|
|
cap_launcher_setuid(attr, v->uid);
|
|
}
|
|
if (v->gid) {
|
|
cap_launcher_setgroups(attr, v->gid, v->ngroups, v->groups);
|
|
}
|
|
if (v->iab) {
|
|
cap_iab_t iab = cap_iab_from_text(v->iab);
|
|
if (iab == NULL) {
|
|
fprintf(stderr, "[%d] failed to decode iab [%s]", i, v->iab);
|
|
perror(":");
|
|
success = 0;
|
|
continue;
|
|
}
|
|
cap_iab_t old = cap_launcher_set_iab(attr, iab);
|
|
if (cap_free(old)) {
|
|
fprintf(stderr, "[%d] failed to decode iab [%s]", i, v->iab);
|
|
perror(":");
|
|
success = 0;
|
|
continue;
|
|
}
|
|
}
|
|
if (v->mode) {
|
|
cap_launcher_set_mode(attr, v->mode);
|
|
}
|
|
|
|
pid_t child = cap_launch(attr, NULL);
|
|
|
|
if (child <= 0) {
|
|
fprintf(stderr, "[%d] failed to launch", i);
|
|
perror(":");
|
|
success = 0;
|
|
continue;
|
|
}
|
|
if (cap_free(attr)) {
|
|
fprintf(stderr, "[%d] failed to free launcher", i);
|
|
perror(":");
|
|
success = 0;
|
|
}
|
|
int result;
|
|
int ret = waitpid(child, &result, 0);
|
|
if (ret != child) {
|
|
fprintf(stderr, "[%d] failed to wait", i);
|
|
perror(":");
|
|
success = 0;
|
|
continue;
|
|
}
|
|
if (result != v->result) {
|
|
fprintf(stderr, "[%d] bad result: got=%d want=%d", i, result,
|
|
v->result);
|
|
perror(":");
|
|
success = 0;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
cap_t final = cap_get_proc();
|
|
if (cap_compare(orig, final)) {
|
|
char *was = cap_to_text(orig, NULL);
|
|
char *is = cap_to_text(final, NULL);
|
|
printf("cap_launch_test: orig:'%s' != final:'%s'\n", was, is);
|
|
cap_free(is);
|
|
cap_free(was);
|
|
success = 0;
|
|
}
|
|
cap_free(final);
|
|
cap_free(orig);
|
|
|
|
if (success) {
|
|
printf("cap_launch_test: PASSED\n");
|
|
} else {
|
|
printf("cap_launch_test: FAILED\n");
|
|
exit(1);
|
|
}
|
|
}
|