Compare commits
5 Commits
44b9a17bec
...
4cfdead5d0
Author | SHA1 | Date | |
---|---|---|---|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user