basic/uid-range: add uid_map_read_one helper

This commit is contained in:
Mike Yuan
2023-12-15 21:22:51 +08:00
parent 121b705426
commit 7312c422f0
4 changed files with 54 additions and 50 deletions
+28 -10
View File
@@ -180,6 +180,30 @@ bool uid_range_covers(const UidRange *range, uid_t start, uid_t nr) {
return false;
}
int uid_map_read_one(FILE *f, uid_t *ret_base, uid_t *ret_shift, uid_t *ret_range) {
uid_t uid_base, uid_shift, uid_range;
int r;
assert(f);
assert(ret_base);
assert(ret_shift);
assert(ret_range);
errno = 0;
r = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range);
if (r == EOF)
return errno_or_else(ENOMSG);
assert(r >= 0);
if (r != 3)
return -EBADMSG;
*ret_base = uid_base;
*ret_shift = uid_shift;
*ret_range = uid_range;
return 0;
}
int uid_range_load_userns(UidRange **ret, const char *path) {
_cleanup_(uid_range_freep) UidRange *range = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -212,18 +236,12 @@ int uid_range_load_userns(UidRange **ret, const char *path) {
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);
r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
if (r == -ENOMSG)
break;
}
if (k != 3)
return -EBADMSG;
if (r < 0)
return r;
r = uid_range_add_internal(&range, uid_base, uid_range, /* coalesce = */ false);
if (r < 0)
+2
View File
@@ -31,4 +31,6 @@ static inline bool uid_range_contains(const UidRange *range, uid_t uid) {
return uid_range_covers(range, uid, 1);
}
int uid_map_read_one(FILE *f, uid_t *ret_base, uid_t *ret_shift, uid_t *ret_range);
int uid_range_load_userns(UidRange **ret, const char *path);
+9 -12
View File
@@ -21,6 +21,7 @@
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "uid-range.h"
#include "virt.h"
enum {
@@ -814,7 +815,7 @@ Virtualization detect_virtualization(void) {
static int userns_has_mapping(const char *name) {
_cleanup_fclose_ FILE *f = NULL;
uid_t a, b, c;
uid_t base, shift, range;
int r;
f = fopen(name, "re");
@@ -823,26 +824,22 @@ static int userns_has_mapping(const char *name) {
return errno == ENOENT ? false : -errno;
}
errno = 0;
r = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &a, &b, &c);
if (r == EOF) {
if (ferror(f))
return log_debug_errno(errno_or_else(EIO), "Failed to read %s: %m", name);
log_debug("%s is empty, we're in an uninitialized user namespace", name);
r = uid_map_read_one(f, &base, &shift, &range);
if (r == -ENOMSG) {
log_debug("%s is empty, we're in an uninitialized user namespace.", name);
return true;
}
if (r != 3)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse %s: %m", name);
if (r < 0)
return log_debug_errno(r, "Failed to read %s: %m", name);
if (a == 0 && b == 0 && c == UINT32_MAX) {
if (base == 0 && shift == 0 && range == UINT32_MAX) {
/* The kernel calls mappings_overlap() and does not allow overlaps */
log_debug("%s has a full 1:1 mapping", name);
return false;
}
/* Anything else implies that we are in a user namespace */
log_debug("Mapping found in %s, we're in a user namespace", name);
log_debug("Mapping found in %s, we're in a user namespace.", name);
return true;
}