Comparar commits
	
		
			5 Commits
		
	
	
		
			44b9a17bec
			...
			4cfdead5d0
		
	
	| Autor | SHA1 | Data | |
|---|---|---|---|
| 4cfdead5d0 | |||
| bbc8193ea9 | |||
| c9fdeb4a1d | |||
| 3732524bfa | |||
| 4059c1a093 | 
							
								
								
									
										125
									
								
								exile.c
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								exile.c
									
									
									
									
									
								
							| @@ -621,10 +621,10 @@ struct exile_policy *exile_init_policy() | |||||||
| 	{ | 	{ | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 	result->drop_caps = 1; | 	result->drop_caps = 0; | ||||||
| 	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_AUTOMATIC; | ||||||
| 	result->namespace_uid = 0; | 	result->namespace_uid = 0; | ||||||
| 	result->namespace_gid = 0; | 	result->namespace_gid = 0; | ||||||
| 	return result; | 	return result; | ||||||
| @@ -959,7 +959,7 @@ static int enter_namespaces(int namespace_options, uid_t namespace_uid, gid_t na | |||||||
| 		int fd = open("/proc/self/setgroups", O_WRONLY); | 		int fd = open("/proc/self/setgroups", O_WRONLY); | ||||||
| 		if(fd == -1) | 		if(fd == -1) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("Failed to open /proc/self/setgroups for writing"); | 			EXILE_LOG_ERROR("Failed to open /proc/self/setgroups for writing\n"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		int writesize = snprintf(buf, sizeof(buf), "deny"); | 		int writesize = snprintf(buf, sizeof(buf), "deny"); | ||||||
| @@ -974,7 +974,7 @@ static int enter_namespaces(int namespace_options, uid_t namespace_uid, gid_t na | |||||||
| 		fd = open("/proc/self/uid_map", O_WRONLY); | 		fd = open("/proc/self/uid_map", O_WRONLY); | ||||||
| 		if(fd == -1) | 		if(fd == -1) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("Failed to open /proc/self/uid_map for writing"); | 			EXILE_LOG_ERROR("Failed to open /proc/self/uid_map for writing\n"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_uid, current_uid); | 		writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_uid, current_uid); | ||||||
| @@ -990,7 +990,7 @@ static int enter_namespaces(int namespace_options, uid_t namespace_uid, gid_t na | |||||||
| 		fd = open("/proc/self/gid_map", O_WRONLY); | 		fd = open("/proc/self/gid_map", O_WRONLY); | ||||||
| 		if(fd == -1) | 		if(fd == -1) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("Failed to open /proc/self/gid_map for writing"); | 			EXILE_LOG_ERROR("Failed to open /proc/self/gid_map for writing\n"); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
| 		writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_gid, current_gid); | 		writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_gid, current_gid); | ||||||
| @@ -1229,6 +1229,9 @@ static unsigned int exile_flags_to_landlock(unsigned int flags, int statmode) | |||||||
| 	if(flags & EXILE_FS_ALLOW_ALL_WRITE) | 	if(flags & EXILE_FS_ALLOW_ALL_WRITE) | ||||||
| 	{ | 	{ | ||||||
| 		result |= LANDLOCK_ACCESS_FS_WRITE_FILE; | 		result |= LANDLOCK_ACCESS_FS_WRITE_FILE; | ||||||
|  | #ifdef LANDLOCK_ACCESS_FS_TRUNCATE | ||||||
|  | 		result |= LANDLOCK_ACCESS_FS_TRUNCATE; | ||||||
|  | #endif | ||||||
| 		if(S_ISDIR(statmode)) | 		if(S_ISDIR(statmode)) | ||||||
| 		{ | 		{ | ||||||
| 			result |= LANDLOCK_ACCESS_FS_REMOVE_DIR; | 			result |= LANDLOCK_ACCESS_FS_REMOVE_DIR; | ||||||
| @@ -1238,6 +1241,9 @@ static unsigned int exile_flags_to_landlock(unsigned int flags, int statmode) | |||||||
| 			result |= LANDLOCK_ACCESS_FS_MAKE_REG; | 			result |= LANDLOCK_ACCESS_FS_MAKE_REG; | ||||||
| 			result |= LANDLOCK_ACCESS_FS_MAKE_SOCK; | 			result |= LANDLOCK_ACCESS_FS_MAKE_SOCK; | ||||||
| 			result |= LANDLOCK_ACCESS_FS_MAKE_SYM; | 			result |= LANDLOCK_ACCESS_FS_MAKE_SYM; | ||||||
|  | #ifdef LANDLOCK_ACCESS_FS_REFER | ||||||
|  | 			result |= LANDLOCK_ACCESS_FS_REFER; | ||||||
|  | #endif | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if(flags & EXILE_FS_ALLOW_EXEC) | 	if(flags & EXILE_FS_ALLOW_EXEC) | ||||||
| @@ -1304,15 +1310,42 @@ static unsigned int exile_flags_to_landlock(unsigned int flags, int statmode) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Sets maximum values for the handled access fs... */ | ||||||
|  | static int landlock_set_max_handled_access(struct landlock_ruleset_attr *ruleset) | ||||||
|  | { | ||||||
|  | 	int abi = landlock_create_ruleset(NULL, 0, | ||||||
|  |                                   LANDLOCK_CREATE_RULESET_VERSION); | ||||||
|  | 	if(abi < 0) | ||||||
|  | 	{ | ||||||
|  | 		EXILE_LOG_ERROR("Can't determine landlock ABI version\n"); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	ruleset->handled_access_net = 0; | ||||||
|  | 	if(abi == 1) | ||||||
|  | 	{ | ||||||
|  | 		ruleset->handled_access_fs = ((LANDLOCK_ACCESS_FS_MAKE_SYM << 1) - 1); | ||||||
|  | 	} | ||||||
|  | 	if(abi == 2) | ||||||
|  | 	{ | ||||||
|  | 		ruleset->handled_access_fs = ((LANDLOCK_ACCESS_FS_REFER << 1) - 1); | ||||||
|  | 	} | ||||||
|  | 	if(abi >= 3) | ||||||
|  | 	{ | ||||||
|  | 		ruleset->handled_access_fs = ((LANDLOCK_ACCESS_FS_TRUNCATE << 1) - 1); | ||||||
|  | 		/* TODO: think about net */ | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| static int landlock_prepare_ruleset(struct exile_path_policy *policies) | static int landlock_prepare_ruleset(struct exile_path_policy *policies) | ||||||
| { | { | ||||||
| 	int ruleset_fd = -1; | 	int ruleset_fd = -1; | ||||||
| 	struct landlock_ruleset_attr ruleset_attr; | 	struct landlock_ruleset_attr ruleset_attr = {0}; | ||||||
| 	/* We here want the maximum possible ruleset, so set the var to the max possible bitmask. | 	if(landlock_set_max_handled_access(&ruleset_attr) != 0) | ||||||
| 	   Stolen/Adapted from: [linux src]/security/landlock/limits.h | 	{ | ||||||
| 	*/ | 		return -1; | ||||||
| 	ruleset_attr.handled_access_fs = ((LANDLOCK_ACCESS_FS_MAKE_SYM << 1) - 1); | 	} | ||||||
|  |  | ||||||
| 	ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); | 	ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); | ||||||
| 	if (ruleset_fd < 0) | 	if (ruleset_fd < 0) | ||||||
| 	{ | 	{ | ||||||
| @@ -1322,7 +1355,7 @@ static int landlock_prepare_ruleset(struct exile_path_policy *policies) | |||||||
| 	struct exile_path_policy *policy = policies; | 	struct exile_path_policy *policy = policies; | ||||||
| 	while(policy != NULL) | 	while(policy != NULL) | ||||||
| 	{ | 	{ | ||||||
| 		struct landlock_path_beneath_attr path_beneath; | 		struct landlock_path_beneath_attr path_beneath = {0}; | ||||||
| 		path_beneath.parent_fd = open(policy->path, O_PATH | O_CLOEXEC); | 		path_beneath.parent_fd = open(policy->path, O_PATH | O_CLOEXEC); | ||||||
| 		if(path_beneath.parent_fd < 0) | 		if(path_beneath.parent_fd < 0) | ||||||
| 		{ | 		{ | ||||||
| @@ -1339,6 +1372,13 @@ static int landlock_prepare_ruleset(struct exile_path_policy *policies) | |||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 		path_beneath.allowed_access = exile_flags_to_landlock(policy->policy, sb.st_mode); | 		path_beneath.allowed_access = exile_flags_to_landlock(policy->policy, sb.st_mode); | ||||||
|  |  | ||||||
|  | 		/* Required, so the .allowed_access fits .handled_access_fs of the ruleset. | ||||||
|  | 		 * Needed for backwards compatibility, e. g. new binary compiled with new headers, | ||||||
|  | 		 executed on a kernel with an older ABI version which does not have some constant defined... | ||||||
|  | 		 */ | ||||||
|  | 		path_beneath.allowed_access &= ruleset_attr.handled_access_fs; | ||||||
|  |  | ||||||
| 		ret = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0); | 		ret = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, &path_beneath, 0); | ||||||
| 		if(ret) | 		if(ret) | ||||||
| 		{ | 		{ | ||||||
| @@ -1492,6 +1532,30 @@ static int enable_no_fs(struct exile_policy *policy) | |||||||
| { | { | ||||||
| 		close_file_fds(); | 		close_file_fds(); | ||||||
|  |  | ||||||
|  | 		if(exile_landlock_is_available()) | ||||||
|  | 		{ | ||||||
|  | 			struct landlock_ruleset_attr ruleset_attr = {0}; | ||||||
|  | 			if(landlock_set_max_handled_access(&ruleset_attr) != 0) | ||||||
|  | 			{ | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  | 			int ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); | ||||||
|  | 			if (ruleset_fd < 0) | ||||||
|  | 			{ | ||||||
|  | 				EXILE_LOG_ERROR("Failed to create landlock ruleset\n"); | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  | 			int ret = landlock_restrict_self(ruleset_fd, 0); | ||||||
|  | 			if(ret != 0) | ||||||
|  | 			{ | ||||||
|  | 				EXILE_LOG_ERROR("Failed to enable no_fs with landlock: %s\n", strerror(errno)); | ||||||
|  | 				close(ruleset_fd); | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  | 			close(ret); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if(chdir("/proc/self/fdinfo") != 0) | 		if(chdir("/proc/self/fdinfo") != 0) | ||||||
| 		{ | 		{ | ||||||
| 			EXILE_LOG_ERROR("Failed to change to safe directory: %s\n", strerror(errno)); | 			EXILE_LOG_ERROR("Failed to change to safe directory: %s\n", strerror(errno)); | ||||||
| @@ -1626,14 +1690,6 @@ int exile_enable_policy(struct exile_policy *policy) | |||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	if(policy->no_fs) |  | ||||||
| 	{ |  | ||||||
| 		if(enable_no_fs(policy) != 0) |  | ||||||
| 		{ |  | ||||||
| 			EXILE_LOG_ERROR("Failed to take away filesystem access of process\n"); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if(policy->no_new_fds) | 	if(policy->no_new_fds) | ||||||
| 	{ | 	{ | ||||||
| @@ -1645,15 +1701,6 @@ int exile_enable_policy(struct exile_policy *policy) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if(policy->drop_caps) |  | ||||||
| 	{ |  | ||||||
| 		if(drop_caps() < 0) |  | ||||||
| 		{ |  | ||||||
| 			EXILE_LOG_ERROR("failed to drop capabilities\n"); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if(policy->not_dumpable) | 	if(policy->not_dumpable) | ||||||
| 	{ | 	{ | ||||||
| 		if(prctl(PR_SET_DUMPABLE, 0) == -1) | 		if(prctl(PR_SET_DUMPABLE, 0) == -1) | ||||||
| @@ -1672,6 +1719,15 @@ int exile_enable_policy(struct exile_policy *policy) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if(policy->no_fs) | ||||||
|  | 	{ | ||||||
|  | 		if(enable_no_fs(policy) != 0) | ||||||
|  | 		{ | ||||||
|  | 			EXILE_LOG_ERROR("Failed to take away filesystem access of process\n"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| #if HAVE_LANDLOCK == 1 | #if HAVE_LANDLOCK == 1 | ||||||
| 	if (can_use_landlock && policy->path_policies != NULL && landlock_restrict_self(landlock_ruleset_fd, 0) != 0) | 	if (can_use_landlock && policy->path_policies != NULL && landlock_restrict_self(landlock_ruleset_fd, 0) != 0) | ||||||
| 	{ | 	{ | ||||||
| @@ -1692,12 +1748,19 @@ int exile_enable_policy(struct exile_policy *policy) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if(policy->drop_caps) | ||||||
|  | 	{ | ||||||
|  | 		if(drop_caps() < 0) | ||||||
|  | 		{ | ||||||
|  | 			EXILE_LOG_ERROR("failed to drop capabilities\n"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if(policy->syscall_policies != NULL) | 	if(policy->syscall_policies != NULL) | ||||||
| 	{ | 	{ | ||||||
| 		return exile_enable_syscall_policy(policy); | 		return exile_enable_syscall_policy(policy); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Referência em uma nova issue
	
	Block a user