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.
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.
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]
26 #include <sys/types.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
35 #define EXECSHELL "/bin/sh"
36 #define UIDMAP "0 100000 65536"
39 child_main(int argc
, char *argv
[], int sync_pipe
)
42 char cmds
[BUFSIZ
] = { 0 };
46 if (unshare(CLONE_NEWUSER
| CLONE_NEWNS
) != 0) {
51 /* tell parent we entered the new namespace */
52 if (write(sync_pipe
, "1", 1) != 1) {
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");
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
);
81 if (execl(EXECSHELL
, "sh", "-c", cmds
, (char *)NULL
) != 0) {
82 perror("execl: " EXECSHELL
);
90 set_idmap(pid_t pid
, const char *file
)
96 (void) snprintf(path
, sizeof (path
), "/proc/%d/%s", (int)pid
, file
);
98 mapfd
= open(path
, O_WRONLY
);
104 if (write(mapfd
, UIDMAP
, sizeof (UIDMAP
)-1) != sizeof (UIDMAP
)-1) {
115 main(int argc
, char *argv
[])
122 if (argc
< 2 || strlen(argv
[1]) == 0) {
123 (void) printf("\tUsage: %s <commands> ...\n", argv
[0]);
127 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, syncfd
) != 0) {
128 perror("socketpair");
133 if (child
== (pid_t
)-1) {
140 return (child_main(argc
, argv
, syncfd
[1]));
146 /* wait for the child to have unshared its namespaces */
147 if (read(syncfd
[0], &sync_buf
, 1) != 1) {
149 kill(child
, SIGKILL
);
154 /* write uid mapping */
155 if (set_idmap(child
, "uid_map") != 0 ||
156 set_idmap(child
, "gid_map") != 0) {
158 kill(child
, SIGKILL
);
162 /* tell the child to proceed */
163 if (write(syncfd
[0], "1", 1) != 1) {
165 kill(child
, SIGKILL
);
172 while (waitpid(child
, &wstatus
, 0) != child
)
173 kill(child
, SIGKILL
);
175 result
= WEXITSTATUS(wstatus
);