1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-22 06:50:18 +03:00

uid-range: add new uid_range_load_userns() for loading /proc/self/uid_map

This commit is contained in:
Lennart Poettering 2022-03-31 13:28:54 +02:00
parent 2e37ebdae9
commit 5674aa7a2c
3 changed files with 98 additions and 0 deletions

View File

@ -5,8 +5,13 @@
#include <string.h>
#include "alloc-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "macro.h"
#include "path-util.h"
#include "sort-util.h"
#include "stat-util.h"
#include "uid-range.h"
#include "user-util.h"
@ -178,3 +183,47 @@ bool uid_range_contains(const UidRange *p, size_t n, uid_t uid) {
return false;
}
int uid_range_load_userns(UidRange **p, size_t *n, const char *path) {
_cleanup_fclose_ FILE *f = NULL;
int r;
/* If 'path' is NULL loads the UID range of the userns namespace we run. Otherwise load the data from
* the specified file (which can be either uid_map or gid_map, in case caller needs to deal with GID
* maps).
*
* To simplify things this will modify the passed array in case of later failure. */
if (!path)
path = "/proc/self/uid_map";
f = fopen(path, "re");
if (!f) {
r = -errno;
if (r == -ENOENT && path_startswith(path, "/proc/") && proc_mounted() > 0)
return -EOPNOTSUPP;
return r;
}
for (;;) {
uid_t uid_base, uid_shift, uid_range;
int k;
errno = 0;
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range);
if (k == EOF) {
if (ferror(f))
return errno_or_else(EIO);
return 0;
}
if (k != 3)
return -EBADMSG;
r = uid_range_add(p, n, uid_base, uid_range);
if (r < 0)
return r;
}
}

View File

@ -13,3 +13,5 @@ int uid_range_add_str(UidRange **p, size_t *n, const char *s);
int uid_range_next_lower(const UidRange *p, size_t n, uid_t *uid);
bool uid_range_contains(const UidRange *p, size_t n, uid_t uid);
int uid_range_load_userns(UidRange **p, size_t *n, const char *path);

View File

@ -3,10 +3,16 @@
#include <stddef.h>
#include "alloc-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "uid-range.h"
#include "user-util.h"
#include "util.h"
#include "virt.h"
TEST(uid_range) {
_cleanup_free_ UidRange *p = NULL;
@ -72,4 +78,45 @@ TEST(uid_range) {
assert_se(p[0].nr == 1983);
}
TEST(load_userns) {
_cleanup_(unlink_and_freep) char *fn = NULL;
_cleanup_free_ UidRange *p = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t n = 0;
int r;
r = uid_range_load_userns(&p, &n, NULL);
if (ERRNO_IS_NOT_SUPPORTED(r))
return;
assert_se(r >= 0);
assert_se(uid_range_contains(p, n, getuid()));
r = running_in_userns();
if (r == 0) {
assert_se(n == 1);
assert_se(p[0].start == 0);
assert_se(p[0].nr == UINT32_MAX);
}
assert_se(fopen_temporary(NULL, &f, &fn) >= 0);
fputs("0 0 20\n"
"100 0 20\n", f);
assert_se(fflush_and_check(f) >= 0);
p = mfree(p);
n = 0;
assert_se(uid_range_load_userns(&p, &n, fn) >= 0);
assert_se(uid_range_contains(p, n, 0));
assert_se(uid_range_contains(p, n, 19));
assert_se(!uid_range_contains(p, n, 20));
assert_se(!uid_range_contains(p, n, 99));
assert_se(uid_range_contains(p, n, 100));
assert_se(uid_range_contains(p, n, 119));
assert_se(!uid_range_contains(p, n, 120));
}
DEFINE_TEST_MAIN(LOG_DEBUG);