Compare commits
	
		
			6 커밋
		
	
	
		
			769f729dc5
			...
			44b9a17bec
		
	
	| 작성자 | SHA1 | 날짜 | |
|---|---|---|---|
| 44b9a17bec | |||
| f662398ac3 | |||
| 7b859d0aed | |||
| 5cd0a36ced | |||
| 618f223491 | |||
| 01c5cbf701 | 
							
								
								
									
										74
									
								
								exile.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								exile.c
									
									
									
									
									
								
							| @@ -625,6 +625,8 @@ struct exile_policy *exile_init_policy() | |||||||
| 	result->not_dumpable = 1; | 	result->not_dumpable = 1; | ||||||
| 	result->no_new_privs = 1; | 	result->no_new_privs = 1; | ||||||
| 	result->namespace_options = EXILE_UNSHARE_MOUNT | EXILE_UNSHARE_USER; | 	result->namespace_options = EXILE_UNSHARE_MOUNT | EXILE_UNSHARE_USER; | ||||||
|  | 	result->namespace_uid = 0; | ||||||
|  | 	result->namespace_gid = 0; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -938,10 +940,15 @@ void exile_free_policy(struct exile_policy *ctxt) | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Enters the specified namespaces */ | /* Enters the specified namespaces */ | ||||||
| static int enter_namespaces(int namespace_options) | static int enter_namespaces(int namespace_options, uid_t namespace_uid, gid_t namespace_gid) | ||||||
| { | { | ||||||
| 	if(namespace_options & EXILE_UNSHARE_USER) | 	if(namespace_options & EXILE_UNSHARE_USER) | ||||||
| 	{ | 	{ | ||||||
|  | 		uid_t current_uid = getuid(); | ||||||
|  | 		gid_t current_gid = getgid(); | ||||||
|  |  | ||||||
|  | 		char buf[1024] = {0}; | ||||||
|  |  | ||||||
| 		int ret = unshare(CLONE_NEWUSER); | 		int ret = unshare(CLONE_NEWUSER); | ||||||
| 		if(ret == -1) | 		if(ret == -1) | ||||||
| 		{ | 		{ | ||||||
| @@ -949,47 +956,51 @@ static int enter_namespaces(int namespace_options) | |||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		uid_t current_uid = getuid(); | 		int fd = open("/proc/self/setgroups", O_WRONLY); | ||||||
| 		gid_t current_gid = getgid(); | 		if(fd == -1) | ||||||
|  | 		{ | ||||||
|  | 			EXILE_LOG_ERROR("Failed to open /proc/self/setgroups for writing"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		int writesize = snprintf(buf, sizeof(buf), "deny"); | ||||||
|  | 		int writeret = write(fd, buf, writesize); | ||||||
|  | 		if(writeret < 0 || writeret < writesize) | ||||||
|  | 		{ | ||||||
|  | 			EXILE_LOG_ERROR("Failed to write to /proc/self/setgroups: %i (%s)\n", writeret, strerror(errno)); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		close(fd); | ||||||
|  |  | ||||||
| 		FILE *fp = fopen("/proc/self/setgroups", "w"); | 		fd = open("/proc/self/uid_map", O_WRONLY); | ||||||
| 		if(fp == NULL) | 		if(fd == -1) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("fopen failed while trying to deny setgroups\n"); | 			EXILE_LOG_ERROR("Failed to open /proc/self/uid_map for writing"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		if(fprintf(fp, "deny") < 0) | 		writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_uid, current_uid); | ||||||
|  | 		writeret = write(fd, buf, writesize); | ||||||
|  | 		if(writeret < 0 || writeret < writesize) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("fprintf failed while trying to write setgroups\n"); | 			EXILE_LOG_ERROR("Failed to write to /proc/self/uid_map: %i (%s)\n", writeret, strerror(errno)); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		fclose(fp); | 		close(fd); | ||||||
|  |  | ||||||
| 		fp = fopen("/proc/self/uid_map", "w"); |  | ||||||
| 		if(fp == NULL) |  | ||||||
| 		{ |  | ||||||
| 			EXILE_LOG_ERROR("fopen failed while trying to write uid_map\n"); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 		if(fprintf(fp, "0 %i", current_uid) < 0) |  | ||||||
| 		{ |  | ||||||
| 			EXILE_LOG_ERROR("fprintf failed while trying to write uid_map\n"); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 		fclose(fp); |  | ||||||
|  |  | ||||||
| 		fp = fopen("/proc/self/gid_map", "w"); | 		fd = open("/proc/self/gid_map", O_WRONLY); | ||||||
| 		if(fp == NULL) | 		if(fd == -1) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("fopen failed while trying to write gid_map\n"); | 			EXILE_LOG_ERROR("Failed to open /proc/self/gid_map for writing"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		if(fprintf(fp, "0 %i", current_gid) < 0) | 		writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_gid, current_gid); | ||||||
|  | 		writeret = write(fd, buf, writesize); | ||||||
|  | 		if(writeret < 0 || writeret < writesize) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("fprintf failed while trying to write gid_map\n"); | 			EXILE_LOG_ERROR("Failed to write to /proc/self/gid_map: %i (%s)\n", writeret, strerror(errno)); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		fclose(fp); | 		close(fd); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if(namespace_options & EXILE_UNSHARE_MOUNT) | 	if(namespace_options & EXILE_UNSHARE_MOUNT) | ||||||
| @@ -1532,7 +1543,7 @@ int exile_enable_policy(struct exile_policy *policy) | |||||||
| 		close_file_fds(); | 		close_file_fds(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if(enter_namespaces(policy->namespace_options) < 0) | 	if(enter_namespaces(policy->namespace_options, policy->namespace_uid, policy->namespace_gid) < 0) | ||||||
| 	{ | 	{ | ||||||
| 		EXILE_LOG_ERROR("Error while trying to enter namespaces\n"); | 		EXILE_LOG_ERROR("Error while trying to enter namespaces\n"); | ||||||
| 		return -1; | 		return -1; | ||||||
| @@ -1879,13 +1890,6 @@ char *exile_launch_get(struct exile_launch_params *launch_params, size_t *n) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	fclose(stream); | 	fclose(stream); | ||||||
| 	int seek = fseek(stream, 0, SEEK_SET); |  | ||||||
| 	if(seek == -1) |  | ||||||
| 	{ |  | ||||||
| 		EXILE_LOG_ERROR("fseek failed\n"); |  | ||||||
| 		close(launch_result.read_fd); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	close(launch_result.read_fd); | 	close(launch_result.read_fd); | ||||||
| 	*n = size; | 	*n = size; | ||||||
| 	return result; | 	return result; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								exile.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								exile.h
									
									
									
									
									
								
							| @@ -375,6 +375,9 @@ struct exile_policy | |||||||
|  |  | ||||||
| 	uint64_t vow_promises; | 	uint64_t vow_promises; | ||||||
|  |  | ||||||
|  | 	uid_t namespace_uid; | ||||||
|  | 	gid_t namespace_gid; | ||||||
|  |  | ||||||
| 	/* Do not manually add policies here, use exile_append_path_policies() */ | 	/* Do not manually add policies here, use exile_append_path_policies() */ | ||||||
| 	struct exile_path_policy *path_policies; | 	struct exile_path_policy *path_policies; | ||||||
| 	struct exile_path_policy **path_policies_tail; | 	struct exile_path_policy **path_policies_tail; | ||||||
|   | |||||||
							
								
								
									
										148
									
								
								test.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								test.c
									
									
									
									
									
								
							| @@ -618,9 +618,9 @@ int test_launch_get() | |||||||
| 	size_t n = 0; | 	size_t n = 0; | ||||||
| 	char *content = exile_launch_get(¶ms, &n); | 	char *content = exile_launch_get(¶ms, &n); | ||||||
| 	unsigned int len = strlen(LAUNCH_GET_TEST_STR); | 	unsigned int len = strlen(LAUNCH_GET_TEST_STR); | ||||||
| 	if(n != strlen(LAUNCH_GET_TEST_STR)) | 	if(n != len) | ||||||
| 	{ | 	{ | ||||||
| 		LOG("Lenght does does not match: %lu vs %u\n", n, len); | 		LOG("Lenght does not match: %lu vs %u\n", n, len); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| 	if(strcmp(content, LAUNCH_GET_TEST_STR) != 0) | 	if(strcmp(content, LAUNCH_GET_TEST_STR) != 0) | ||||||
| @@ -661,6 +661,146 @@ int test_clone3_nosys() | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int do_test_nsuidmap(const char *path,  const char *firstfield, const char *secondfield, const char *thirdfield) | ||||||
|  | { | ||||||
|  | 	char *line = NULL; | ||||||
|  | 	size_t n = 0; | ||||||
|  | 	FILE *fp = fopen(path, "r"); | ||||||
|  |  | ||||||
|  | 	int ret = getdelim(&line, &n, ' ', fp); | ||||||
|  | 	while(ret != -1 && strlen(line) == 1 && *line == ' ') | ||||||
|  | 		ret = getdelim(&line, &n, ' ', fp); | ||||||
|  | 	if(ret == -1) | ||||||
|  | 	{ | ||||||
|  | 		LOG("getdelim() failed to read a line from %s\n", path); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	line[ret-1] = '\0'; | ||||||
|  | 	if(strcmp(line, firstfield) != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("Invalid value for first entry in map: Expected: %s, was: %s\n", firstfield, line); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ret = getdelim(&line, &n, ' ', fp); | ||||||
|  | 	while(ret != -1 && strlen(line) == 1 && *line == ' ') | ||||||
|  | 		ret = getdelim(&line, &n, ' ', fp); | ||||||
|  | 	if(ret == -1) | ||||||
|  | 	{ | ||||||
|  | 		LOG("getdelim() failed to read a line from map\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	line[ret-1] = '\0'; | ||||||
|  |  | ||||||
|  | 	if(strcmp(line, secondfield) != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("Invalid value for second entry in map: Expected: %s, was: %s\n", secondfield, line); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	ret = getdelim(&line, &n, ' ', fp); | ||||||
|  | 	while(ret != -1 && strlen(line) == 1 && *line == ' ') | ||||||
|  | 		ret = getdelim(&line, &n, ' ', fp); | ||||||
|  | 	if(ret == -1) | ||||||
|  | 	{ | ||||||
|  | 		LOG("getdelim() failed to read a line from uid_map\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	line[ret-1] = '\0'; | ||||||
|  | 	if(strcmp(line, thirdfield) != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("Invalid value for second entry in map: Expected: %s, was: %s\n", thirdfield, line); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fclose(fp); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int test_unshare_user() | ||||||
|  | { | ||||||
|  | 	char uidstr[64]; | ||||||
|  | 	snprintf(uidstr, sizeof(uidstr), "%u", getuid()); | ||||||
|  |  | ||||||
|  | 	char gidstr[64]; | ||||||
|  | 	snprintf(gidstr, sizeof(gidstr), "%u", getgid()); | ||||||
|  |  | ||||||
|  | 	struct exile_policy *policy = exile_init_policy(); | ||||||
|  | 	policy->namespace_options = EXILE_UNSHARE_USER; | ||||||
|  | 	xexile_enable_policy(policy); | ||||||
|  |  | ||||||
|  | 	if(do_test_nsuidmap("/proc/self/uid_map", "0", uidstr, "1") != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("/proc/self/uid_map failed\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(do_test_nsuidmap("/proc/self/gid_map", "0", gidstr, "1") != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("/proc/self/gid_map failed\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	FILE *fp = fopen("/proc/self/setgroups", "r"); | ||||||
|  |  | ||||||
|  | 	char buffer[4096] = { 0 }; | ||||||
|  | 	fread(buffer, sizeof(buffer), 1, fp); | ||||||
|  | 	fclose(fp); | ||||||
|  |  | ||||||
|  | 	if(strcmp(buffer, "deny\n") != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("/proc/self/setgroups does not contain 'deny'\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int test_unshare_user_own_uid() | ||||||
|  | { | ||||||
|  | 	uid_t uid = getuid(); | ||||||
|  | 	gid_t gid = getgid(); | ||||||
|  |  | ||||||
|  | 	char uidstr[64]; | ||||||
|  | 	snprintf(uidstr, sizeof(uidstr), "%u", uid); | ||||||
|  |  | ||||||
|  | 	char gidstr[64]; | ||||||
|  | 	snprintf(gidstr, sizeof(gidstr), "%u", gid); | ||||||
|  |  | ||||||
|  | 	struct exile_policy *policy = exile_init_policy(); | ||||||
|  | 	policy->namespace_options = EXILE_UNSHARE_USER; | ||||||
|  | 	policy->namespace_gid = gid; | ||||||
|  | 	policy->namespace_uid = uid; | ||||||
|  | 	xexile_enable_policy(policy); | ||||||
|  |  | ||||||
|  | 	if(do_test_nsuidmap("/proc/self/uid_map", uidstr, uidstr, "1") != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("/proc/self/uid_map failed\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if(do_test_nsuidmap("/proc/self/gid_map", gidstr, gidstr, "1") != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("/proc/self/gid_map failed\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	FILE *fp = fopen("/proc/self/setgroups", "r"); | ||||||
|  |  | ||||||
|  | 	char buffer[4096] = { 0 }; | ||||||
|  | 	fread(buffer, sizeof(buffer), 1, fp); | ||||||
|  | 	fclose(fp); | ||||||
|  |  | ||||||
|  | 	if(strcmp(buffer, "deny\n") != 0) | ||||||
|  | 	{ | ||||||
|  | 		LOG("/proc/self/setgroups does not contain 'deny'\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| struct dispatcher | struct dispatcher | ||||||
| { | { | ||||||
| 	char *name; | 	char *name; | ||||||
| @@ -689,6 +829,10 @@ struct dispatcher dispatchers[] = { | |||||||
| 	{ "launch-get", &test_launch_get}, | 	{ "launch-get", &test_launch_get}, | ||||||
| 	{ "vow_from_str", &test_vows_from_str}, | 	{ "vow_from_str", &test_vows_from_str}, | ||||||
| 	{ "clone3_nosys", &test_clone3_nosys}, | 	{ "clone3_nosys", &test_clone3_nosys}, | ||||||
|  | 	{ "unshare-user", &test_unshare_user}, | ||||||
|  | 	{ "unshare-user-own-uid", &test_unshare_user_own_uid}, | ||||||
|  |  | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								test.sh
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								test.sh
									
									
									
									
									
								
							| @@ -8,41 +8,41 @@ COUNT_SUCCEEDED=0 | |||||||
| COUNT_FAILED=0 | COUNT_FAILED=0 | ||||||
| COUNT_SKIPPED=0 | COUNT_SKIPPED=0 | ||||||
|  |  | ||||||
| function print_fail() | print_fail() | ||||||
| { | { | ||||||
| 	echo -e "${RED}$@${NC}" 1>&2 | 	printf "${RED}$@${NC}\n" 1>&2 | ||||||
| } | } | ||||||
|  |  | ||||||
| function print_success() | print_success() | ||||||
| { | { | ||||||
| 	echo -e "${GREEN}$@${NC}" | 	printf "${GREEN}$@${NC}\n" | ||||||
| } | } | ||||||
|  |  | ||||||
| function print_skipped() | print_skipped() | ||||||
| { | { | ||||||
| 	echo -e "${YELLOW}$@${NC}" | 	printf "${YELLOW}$@${NC}\n" | ||||||
| } | } | ||||||
|  |  | ||||||
| function runtest_fail() | runtest_fail() | ||||||
| { | { | ||||||
| 	print_fail "failed" | 	print_fail "failed" | ||||||
| 	COUNT_FAILED=$(($COUNT_FAILED+1)) | 	COUNT_FAILED=$(($COUNT_FAILED+1)) | ||||||
| } | } | ||||||
|  |  | ||||||
| function runtest_success() | runtest_success() | ||||||
| { | { | ||||||
| 	print_success "ok" | 	print_success "ok" | ||||||
| 	COUNT_SUCCEEDED=$((COUNT_SUCCEEDED+1)) | 	COUNT_SUCCEEDED=$((COUNT_SUCCEEDED+1)) | ||||||
| } | } | ||||||
|  |  | ||||||
| function runtest_skipped() | runtest_skipped() | ||||||
| { | { | ||||||
| 	print_skipped "skipped" | 	print_skipped "skipped" | ||||||
| 	COUNT_SKIPPED=$((COUNT_SKIPPED+1)) | 	COUNT_SKIPPED=$((COUNT_SKIPPED+1)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| function runtest() | runtest() | ||||||
| { | { | ||||||
| 	testbin="$1" | 	testbin="$1" | ||||||
| 	testname="$2" | 	testname="$2" | ||||||
| @@ -52,7 +52,8 @@ function runtest() | |||||||
|  |  | ||||||
| 	echo -n "Running $testname... " | 	echo -n "Running $testname... " | ||||||
| 	#exit $? to suppress shell message like "./test.sh: line 18: pid Bad system call" | 	#exit $? to suppress shell message like "./test.sh: line 18: pid Bad system call" | ||||||
| 	(./$testbin "$testname" || exit $?) &>> "${test_log_file}" | 	(./$testbin "$testname" || exit $?) >> "${test_log_file}" 2>&1 | ||||||
|  |  | ||||||
| 	ret=$? | 	ret=$? | ||||||
| 	SUCCESS="no" | 	SUCCESS="no" | ||||||
| 	if [ $ret -eq 0 ] ; then | 	if [ $ret -eq 0 ] ; then | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user