1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd., 2015
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11 * the GNU General Public License for more details.
12 */
13
14 /*
15 * Verify that:
16 * The user ID and group ID, which are inside a container, can be modified
17 * by its parent process.
18 */
19
20 #define _GNU_SOURCE
21 #include <sys/wait.h>
22 #include <assert.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <errno.h>
28 #include "userns_helper.h"
29 #include "test.h"
30
31 char *TCID = "user_namespace2";
32 int TST_TOTAL = 1;
33
cleanup(void)34 static void cleanup(void)
35 {
36 tst_rmdir();
37 }
38
39 /*
40 * child_fn1() - Inside a new user namespace
41 */
child_fn1(void)42 static int child_fn1(void)
43 {
44 int exit_val;
45 int uid, gid;
46
47 TST_SAFE_CHECKPOINT_WAIT(NULL, 0);
48 uid = geteuid();
49 gid = getegid();
50
51 if (uid == 100 && gid == 100) {
52 printf("Got expected uid and gid.\n");
53 exit_val = 0;
54 } else {
55 printf("Got unexpected result of uid=%d gid=%d\n", uid, gid);
56 exit_val = 1;
57 }
58
59 return exit_val;
60 }
61
setup(void)62 static void setup(void)
63 {
64 check_newuser();
65 tst_tmpdir();
66 TST_CHECKPOINT_INIT(NULL);
67 }
68
main(int argc,char * argv[])69 int main(int argc, char *argv[])
70 {
71 int lc;
72 int childpid;
73 int parentuid;
74 int parentgid;
75 char path[BUFSIZ];
76 char content[BUFSIZ];
77 int fd;
78
79 tst_parse_opts(argc, argv, NULL, NULL);
80 setup();
81
82 for (lc = 0; TEST_LOOPING(lc); lc++) {
83 tst_count = 0;
84 childpid = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD,
85 (void *)child_fn1, NULL);
86
87 if (childpid < 0)
88 tst_brkm(TFAIL | TERRNO, cleanup, "clone failed");
89
90 parentuid = geteuid();
91 parentgid = getegid();
92 sprintf(path, "/proc/%d/uid_map", childpid);
93 sprintf(content, "100 %d 1", parentuid);
94 fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
95 SAFE_WRITE(cleanup, 1, fd, content, strlen(content));
96 SAFE_CLOSE(cleanup, fd);
97
98 if (access("/proc/self/setgroups", F_OK) == 0) {
99 sprintf(path, "/proc/%d/setgroups", childpid);
100 fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
101 SAFE_WRITE(cleanup, 1, fd, "deny", 4);
102 SAFE_CLOSE(cleanup, fd);
103 }
104
105 sprintf(path, "/proc/%d/gid_map", childpid);
106 sprintf(content, "100 %d 1", parentgid);
107 fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
108 SAFE_WRITE(cleanup, 1, fd, content, strlen(content));
109 SAFE_CLOSE(cleanup, fd);
110
111 TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
112
113 tst_record_childstatus(cleanup, childpid);
114 }
115 cleanup();
116 tst_exit();
117 }
118