static int give_capabilities (pid_t pid) { cap_t caps = cap_init(); const unsigned caps_size = 4; cap_value_t cap_list[] = { CAP_SETPCAP, CAP_SYS_NICE, CAP_SYS_RESOURCE, CAP_IPC_LOCK} ; if (caps == NULL) { fprintf (stderr, "jackstart: could not allocate capability working storage\n"); return -1; } cap_clear(caps); if (capgetp (pid, caps)) { fprintf (stderr, "jackstart: could not get capabilities for process %d\n", pid); cap_clear(caps); } cap_set_flag(caps, CAP_EFFECTIVE, caps_size, cap_list , CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, caps_size, cap_list , CAP_SET); cap_set_flag(caps, CAP_PERMITTED, caps_size, cap_list , CAP_SET); if (capsetp (pid, caps)) { fprintf (stderr, "jackstart: could not give capabilities: %s\n", strerror (errno)); cap_free (caps); return -1; } cap_free (caps); return 0; }
static PyObject * strcaps_set_process(PyObject *self, PyObject *args) { // (str) caps, (int) pid or None char *strcaps; int pid = 0; if (!PyArg_ParseTuple(args, "et|i", Py_FileSystemDefaultEncoding, &strcaps, &pid)) return NULL; cap_t caps; if ((caps = cap_from_text(strcaps)) == NULL) { PyErr_SetString(PyExc_ValueError, "Invalid capability specification"); PyMem_Free(strcaps); return NULL; } PyMem_Free(strcaps); int err; if (!pid) err = cap_set_proc(caps); else err = capsetp(pid, caps); if (err) { PyErr_SetFromErrno(PyExc_OSError); cap_free(caps); return NULL; } cap_free(caps); Py_RETURN_NONE; };
/** * Drop all capabilities. */ void setup_drop_caps() { cap_t empty; empty = cap_init(); if (!empty) { SYSERROR("cap_init() failed"); throw -1; } if ( capsetp(0, empty) ) { SYSERROR("capsetp() failed"); throw -1; } if ( cap_free(empty) ) { SYSERROR("cap_free() failed"); throw -1; } DEBUG("capabilities has been dropped"); }
int main(int argc, char **argv) { cap_t old_caps; uid_t uid; pid_t pid, parent_pid; gid_t gid; int pipe_fds[2]; /* this program should not be made setuid-0 */ if (getuid() && !geteuid()) { usage(); } /* check that we have at least 3 arguments */ if (argc < 4) { usage(); } /* Convert username to uid */ { struct passwd *pw = getpwnam(argv[1]); if (!pw) { fprintf(stderr, "sucap: No such user: %s\n", argv[1]); exit(1); } uid = pw->pw_uid; } /* Convert groupname to gid */ { struct group *gr = getgrnam(argv[2]); if (!gr) { fprintf(stderr, "sucap: No such group: %s\n", argv[2]); exit(1); } gid = gr->gr_gid; } /* set process group to current pid */ if (setpgid(0, getpid())) { perror("sucap: Failed to set process group"); exit(1); } if (pipe(pipe_fds)) { perror("sucap: pipe() failed"); exit(1); } parent_pid = getpid(); old_caps = cap_init(); if (capgetp(0, old_caps)) { perror("sucap: capgetp"); exit(1); } { ssize_t x; printf("Caps: %s\n", cap_to_text(old_caps, &x)); } /* fork off a child to do the hard work */ fflush(NULL); pid = fork(); if (pid == -1) { perror("sucap: fork failed"); exit(1); } /* 1. mother process sets gid and uid * 2. child process sets capabilities of mother process * 3. mother process execs whatever is to be executed */ if (pid) { /* Mother process. */ close(pipe_fds[0]); /* Get rid of any supplemental groups */ if (!getuid() && setgroups(0, 0)) { perror("sucap: setgroups failed"); exit(1); } /* Set gid and uid (this probably clears capabilities) */ setregid(gid, gid); setreuid(uid, uid); { ssize_t x; cap_t cap = cap_init(); capgetp(0, cap); printf("Caps: %s\n", cap_to_text(cap, &x)); } printf("[debug] uid:%d, real uid:%d\n", geteuid(), getuid()); /* Signal child that we want our privileges updated */ close(pipe_fds[1]); /* Child hangs in blocking read */ /* Wait for child process to set our privileges */ { int status = 0; if (wait(&status) == -1) { perror("sucap: wait failed"); } if (!WIFEXITED(status) || WEXITSTATUS(status)) { fprintf(stderr, "sucap: child did not exit cleanly.\n"); exit(1); } } { ssize_t x; cap_t cap = cap_init(); capgetp(0, cap); printf("Caps: %s\n", cap_to_text(cap, &x)); } /* printf("[debug] uid:%d, real uid:%d\n", geteuid(), getuid()); */ /* exec the program indicated by args 2 ... */ execvp(argv[3], argv+3); /* if we fall through to here, our exec failed -- announce the fact */ fprintf(stderr, "Unable to execute command: %s\n", strerror(errno)); usage(); } else { /* Child process */ close(pipe_fds[1]); /* Wait for mother process to setuid */ wait_on_fd(pipe_fds[0]); /* Set privileges on mother process */ if (capsetp(parent_pid, old_caps)) { perror("sucaps: capsetp"); _exit(1); } /* exit to signal mother process that we are ready */ _exit(0); } return 0; }