The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/tests/zfs-tests/cmd/user_ns_exec.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 #include <stdio.h>
   23 #include <unistd.h>
   24 #include <string.h>
   25 #include <limits.h>
   26 #include <sys/types.h>
   27 #include <sys/types.h>
   28 #include <sys/socket.h>
   29 #include <sys/wait.h>
   30 #include <fcntl.h>
   31 #include <errno.h>
   32 #include <signal.h>
   33 #include <sched.h>
   34 
   35 #define EXECSHELL       "/bin/sh"
   36 #define UIDMAP          "0 100000 65536"
   37 
   38 static int
   39 child_main(int argc, char *argv[], int sync_pipe)
   40 {
   41         char sync_buf;
   42         char cmds[BUFSIZ] = { 0 };
   43         char sep[] = " ";
   44         int i, len;
   45 
   46         if (unshare(CLONE_NEWUSER | CLONE_NEWNS) != 0) {
   47                 perror("unshare");
   48                 return (1);
   49         }
   50 
   51         /* tell parent we entered the new namespace */
   52         if (write(sync_pipe, "1", 1) != 1) {
   53                 perror("write");
   54                 return (1);
   55         }
   56 
   57         /* wait for parent to setup the uid mapping */
   58         if (read(sync_pipe, &sync_buf, 1) != 1) {
   59                 (void) fprintf(stderr, "user namespace setup failed\n");
   60                 return (1);
   61         }
   62 
   63         close(sync_pipe);
   64 
   65         if (setuid(0) != 0) {
   66                 perror("setuid");
   67                 return (1);
   68         }
   69         if (setgid(0) != 0) {
   70                 perror("setgid");
   71                 return (1);
   72         }
   73 
   74         len = 0;
   75         for (i = 1; i < argc; i++) {
   76                 (void) snprintf(cmds+len, sizeof (cmds)-len,
   77                     "%s%s", argv[i], sep);
   78                 len += strlen(argv[i]) + strlen(sep);
   79         }
   80 
   81         if (execl(EXECSHELL, "sh",  "-c", cmds, (char *)NULL) != 0) {
   82                 perror("execl: " EXECSHELL);
   83                 return (1);
   84         }
   85 
   86         return (0);
   87 }
   88 
   89 static int
   90 set_idmap(pid_t pid, const char *file)
   91 {
   92         int result = 0;
   93         int mapfd;
   94         char path[PATH_MAX];
   95 
   96         (void) snprintf(path, sizeof (path), "/proc/%d/%s", (int)pid, file);
   97 
   98         mapfd = open(path, O_WRONLY);
   99         if (mapfd < 0) {
  100                 perror("open");
  101                 return (errno);
  102         }
  103 
  104         if (write(mapfd, UIDMAP, sizeof (UIDMAP)-1) != sizeof (UIDMAP)-1) {
  105                 perror("write");
  106                 result = (errno);
  107         }
  108 
  109         close(mapfd);
  110 
  111         return (result);
  112 }
  113 
  114 int
  115 main(int argc, char *argv[])
  116 {
  117         char sync_buf;
  118         int result, wstatus;
  119         int syncfd[2];
  120         pid_t child;
  121 
  122         if (argc < 2 || strlen(argv[1]) == 0) {
  123                 (void) printf("\tUsage: %s <commands> ...\n", argv[0]);
  124                 return (1);
  125         }
  126 
  127         if (socketpair(AF_UNIX, SOCK_STREAM, 0, syncfd) != 0) {
  128                 perror("socketpair");
  129                 return (1);
  130         }
  131 
  132         child = fork();
  133         if (child == (pid_t)-1) {
  134                 perror("fork");
  135                 return (1);
  136         }
  137 
  138         if (child == 0) {
  139                 close(syncfd[0]);
  140                 return (child_main(argc, argv, syncfd[1]));
  141         }
  142 
  143         close(syncfd[1]);
  144 
  145         result = 0;
  146         /* wait for the child to have unshared its namespaces */
  147         if (read(syncfd[0], &sync_buf, 1) != 1) {
  148                 perror("read");
  149                 kill(child, SIGKILL);
  150                 result = 1;
  151                 goto reap;
  152         }
  153 
  154         /* write uid mapping */
  155         if (set_idmap(child, "uid_map") != 0 ||
  156             set_idmap(child, "gid_map") != 0) {
  157                 result = 1;
  158                 kill(child, SIGKILL);
  159                 goto reap;
  160         }
  161 
  162         /* tell the child to proceed */
  163         if (write(syncfd[0], "1", 1) != 1) {
  164                 perror("write");
  165                 kill(child, SIGKILL);
  166                 result = 1;
  167                 goto reap;
  168         }
  169         close(syncfd[0]);
  170 
  171 reap:
  172         while (waitpid(child, &wstatus, 0) != child)
  173                 kill(child, SIGKILL);
  174         if (result == 0)
  175                 result = WEXITSTATUS(wstatus);
  176 
  177         return (result);
  178 }

Cache object: 0ab87ab2b33d294746640787b6ae8c9d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.