Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <err.h>
- #include <sched.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <string.h>
- #include <sys/prctl.h>
- #include <sys/mount.h>
- #include <grp.h>
- #include <sys/capability.h>
- static const char *proc_file(pid_t pid, const char *fname) {
- char buf[256] = {0};
- sprintf(buf, "/proc/%u/%s", pid, fname);
- fprintf(stderr, "proc_file: %s\n", buf);
- return strdup(buf);
- }
- static void write_uid_gid_map(pid_t pid, uid_t uid, gid_t gid) {
- FILE *fp = fopen(proc_file(pid, "uid_map"), "w");
- if (!fp)
- err(-1, "fopen('/proc/%d/uid_map')", pid);
- /* uid mapped to 0 */
- fprintf(fp, "%u %u 1", 0, uid);
- if (fclose(fp) < 0)
- err(-1, "fclose('uid_map')");
- fp = fopen(proc_file(pid, "gid_map"), "w");
- if (!fp)
- err(-1, "fopen('/proc/%d/gid_map')", pid);
- /* identity map */
- fprintf(fp, "%u %u 1", gid, gid);
- if (fclose(fp) < 0)
- err(-1, "fclose('gid_map')");
- }
- static void reset_caps() {
- struct __user_cap_header_struct cap_hdr;
- cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
- cap_hdr.pid = 0;
- struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3];
- bzero(cap_data, sizeof(cap_data));
- if (capset(&cap_hdr, &cap_data[0]) < 0) {
- err(-1, "capset()");
- }
- return;
- }
- int main(int argc, char **argv)
- {
- int ret;
- int pid = fork();
- if (pid < 0)
- err(-1, "fork()");
- if (pid == 0) {
- ret = unshare(CLONE_NEWUSER);
- if (ret < 0)
- err(-1, "unshare()");
- sleep(5);
- fprintf(stderr, "child resuming\n");
- //if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
- // err(-1, "prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)");
- ret = setresgid(99, 99, 99);
- if (ret < 0)
- err(-1, "setresgid()");
- ret = setresuid(0, 0, 0);
- if (ret < 0)
- err(-1, "setresuid()");
- /* provide any arg to reset capabilities */
- if (argc > 1) {
- fprintf(stderr, "resetting caps\n");
- reset_caps();
- }
- const char *args[] = { "/bin/sleep", "10000", NULL };
- // Interestingly, doing additional exec() seems to not reproduce
- // the issue. I.e., if we run following command, the ownership
- // if correct.
- // const char *args[] = { "/bin/bash", "-c", "/bin/sleep 10000", NULL };
- execve(args[0], (char *const *)args, environ);
- err(-1, "execve()");
- } else {
- fprintf(stderr, "child_pid: %u\n", pid);
- sleep(1);
- write_uid_gid_map(pid /* pid */, 99 /* uid */, 99 /*gid*/);
- }
- ret = waitpid(pid, NULL, 0);
- err(ret, "waitpid()");
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement