Advertisement
Guest User

userns_uid0

a guest
Sep 30th, 2014
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.48 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <err.h>
  5. #include <sched.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <sys/types.h>
  9. #include <sys/wait.h>
  10. #include <string.h>
  11. #include <sys/prctl.h>
  12. #include <sys/mount.h>
  13. #include <grp.h>
  14. #include <sys/capability.h>
  15.  
  16. static const char *proc_file(pid_t pid, const char *fname) {
  17.     char buf[256] = {0};
  18.     sprintf(buf, "/proc/%u/%s", pid, fname);
  19.     fprintf(stderr, "proc_file: %s\n", buf);
  20.     return strdup(buf);
  21. }
  22.  
  23. static void write_uid_gid_map(pid_t pid, uid_t uid, gid_t gid) {
  24.     FILE *fp = fopen(proc_file(pid, "uid_map"), "w");
  25.     if (!fp)
  26.         err(-1, "fopen('/proc/%d/uid_map')", pid);
  27.     /* uid mapped to 0 */
  28.     fprintf(fp, "%u %u 1", 0, uid);
  29.     if (fclose(fp) < 0)
  30.         err(-1, "fclose('uid_map')");
  31.  
  32.     fp = fopen(proc_file(pid, "gid_map"), "w");
  33.     if (!fp)
  34.         err(-1, "fopen('/proc/%d/gid_map')", pid);
  35.     /* identity map */
  36.     fprintf(fp, "%u %u 1", gid, gid);
  37.     if (fclose(fp) < 0)
  38.         err(-1, "fclose('gid_map')");
  39. }
  40.  
  41. static void reset_caps() {
  42.     struct __user_cap_header_struct cap_hdr;
  43.     cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
  44.     cap_hdr.pid = 0;
  45.     struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3];
  46.     bzero(cap_data, sizeof(cap_data));
  47.     if (capset(&cap_hdr, &cap_data[0]) < 0) {
  48.         err(-1, "capset()");
  49.     }
  50.     return;
  51. }
  52.  
  53. int main(int argc, char **argv)
  54. {
  55.     int ret;
  56.  
  57.     int pid = fork();
  58.     if (pid < 0)
  59.         err(-1, "fork()");
  60.  
  61.     if (pid == 0) {
  62.         ret = unshare(CLONE_NEWUSER);
  63.         if (ret < 0)
  64.             err(-1, "unshare()");
  65.  
  66.         sleep(5);
  67.         fprintf(stderr, "child resuming\n");
  68.  
  69.         //if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
  70.         //  err(-1, "prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)");
  71.         ret = setresgid(99, 99, 99);
  72.         if (ret < 0)
  73.             err(-1, "setresgid()");
  74.         ret = setresuid(0, 0, 0);
  75.         if (ret < 0)
  76.             err(-1, "setresuid()");
  77.  
  78.         /* provide any arg to reset capabilities */
  79.         if (argc > 1) {
  80.             fprintf(stderr, "resetting caps\n");
  81.             reset_caps();
  82.         }
  83.  
  84.         const char *args[] = { "/bin/sleep", "10000", NULL };
  85.         // Interestingly, doing additional exec() seems to not reproduce
  86.         // the issue. I.e., if we run following command, the ownership
  87.         // if correct.
  88.         // const char *args[] = { "/bin/bash", "-c", "/bin/sleep 10000", NULL };
  89.         execve(args[0], (char *const *)args, environ);
  90.         err(-1, "execve()");
  91.     } else {
  92.         fprintf(stderr, "child_pid: %u\n", pid);
  93.         sleep(1);
  94.         write_uid_gid_map(pid /* pid */, 99 /* uid */, 99 /*gid*/);
  95.     }
  96.     ret = waitpid(pid, NULL, 0);
  97.     err(ret, "waitpid()");
  98.     return ret;
  99. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement