Allow specifying uid/gid to map in user namespace

This commit is contained in:
Albert S. 2022-12-27 13:25:12 +01:00
parent f662398ac3
commit 44b9a17bec
3 changed files with 53 additions and 4 deletions

10
exile.c
View File

@ -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,7 +940,7 @@ 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)
{ {
@ -975,7 +977,7 @@ static int enter_namespaces(int namespace_options)
EXILE_LOG_ERROR("Failed to open /proc/self/uid_map for writing"); EXILE_LOG_ERROR("Failed to open /proc/self/uid_map for writing");
return -1; return -1;
} }
writesize = snprintf(buf, sizeof(buf), "0 %u 1\n", current_uid); writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_uid, current_uid);
writeret = write(fd, buf, writesize); writeret = write(fd, buf, writesize);
if(writeret < 0 || writeret < writesize) if(writeret < 0 || writeret < writesize)
{ {
@ -991,7 +993,7 @@ static int enter_namespaces(int namespace_options)
EXILE_LOG_ERROR("Failed to open /proc/self/gid_map for writing"); EXILE_LOG_ERROR("Failed to open /proc/self/gid_map for writing");
return -1; return -1;
} }
writesize = snprintf(buf, sizeof(buf), "0 %u 1\n", current_gid); writesize = snprintf(buf, sizeof(buf), "%u %u 1\n", namespace_gid, current_gid);
writeret = write(fd, buf, writesize); writeret = write(fd, buf, writesize);
if(writeret < 0 || writeret < writesize) if(writeret < 0 || writeret < writesize)
{ {
@ -1541,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;

View File

@ -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;

44
test.c
View File

@ -755,8 +755,50 @@ int test_unshare_user()
} }
return 0; 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
@ -788,6 +830,8 @@ struct dispatcher dispatchers[] = {
{ "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", &test_unshare_user},
{ "unshare-user-own-uid", &test_unshare_user_own_uid},
}; };