• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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