uid-range: tie up number and array of uid range entries
This renames UidRange -> UidRangeEntry, and reintroduces UidRange which contains the array of UidRangeEntry and its size. No fucntional changes, just refactoring.
This commit is contained in:
+69
-46
@@ -15,14 +15,22 @@
|
||||
#include "uid-range.h"
|
||||
#include "user-util.h"
|
||||
|
||||
static bool uid_range_intersect(const UidRange *a, const UidRange *b) {
|
||||
UidRange *uid_range_free(UidRange *range) {
|
||||
if (!range)
|
||||
return NULL;
|
||||
|
||||
free(range->entries);
|
||||
return mfree(range);
|
||||
}
|
||||
|
||||
static bool uid_range_entry_intersect(const UidRangeEntry *a, const UidRangeEntry *b) {
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
return a->start <= b->start + b->nr && a->start + a->nr >= b->start;
|
||||
}
|
||||
|
||||
static int uid_range_compare(const UidRange *a, const UidRange *b) {
|
||||
static int uid_range_entry_compare(const UidRangeEntry *a, const UidRangeEntry *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
@@ -35,23 +43,22 @@ static int uid_range_compare(const UidRange *a, const UidRange *b) {
|
||||
return CMP(a->nr, b->nr);
|
||||
}
|
||||
|
||||
static void uid_range_coalesce(UidRange **p, size_t *n) {
|
||||
assert(p);
|
||||
assert(n);
|
||||
static void uid_range_coalesce(UidRange *range) {
|
||||
assert(range);
|
||||
|
||||
if (*n <= 1)
|
||||
if (range->n_entries <= 0)
|
||||
return;
|
||||
|
||||
typesafe_qsort(*p, *n, uid_range_compare);
|
||||
typesafe_qsort(range->entries, range->n_entries, uid_range_entry_compare);
|
||||
|
||||
for (size_t i = 0; i < *n; i++) {
|
||||
UidRange *x = (*p) + i;
|
||||
for (size_t i = 0; i < range->n_entries; i++) {
|
||||
UidRangeEntry *x = range->entries + i;
|
||||
|
||||
for (size_t j = i + 1; j < *n; j++) {
|
||||
UidRange *y = (*p)+j;
|
||||
for (size_t j = i + 1; j < range->n_entries; j++) {
|
||||
UidRangeEntry *y = range->entries + j;
|
||||
uid_t begin, end;
|
||||
|
||||
if (!uid_range_intersect(x, y))
|
||||
if (!uid_range_entry_intersect(x, y))
|
||||
break;
|
||||
|
||||
begin = MIN(x->start, y->start);
|
||||
@@ -60,18 +67,20 @@ static void uid_range_coalesce(UidRange **p, size_t *n) {
|
||||
x->start = begin;
|
||||
x->nr = end - begin;
|
||||
|
||||
if (*n > j+1)
|
||||
memmove(y, y+1, sizeof(UidRange) * (*n - j -1));
|
||||
if (range->n_entries > j + 1)
|
||||
memmove(y, y + 1, sizeof(UidRangeEntry) * (range->n_entries - j - 1));
|
||||
|
||||
(*n)--;
|
||||
range->n_entries--;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uid_range_add_internal(UidRange **p, size_t *n, uid_t start, uid_t nr, bool coalesce) {
|
||||
assert(p);
|
||||
assert(n);
|
||||
int uid_range_add_internal(UidRange **range, uid_t start, uid_t nr, bool coalesce) {
|
||||
_cleanup_(uid_range_freep) UidRange *range_new = NULL;
|
||||
UidRange *p;
|
||||
|
||||
assert(range);
|
||||
|
||||
if (nr <= 0)
|
||||
return 0;
|
||||
@@ -79,39 +88,51 @@ int uid_range_add_internal(UidRange **p, size_t *n, uid_t start, uid_t nr, bool
|
||||
if (start > UINT32_MAX - nr) /* overflow check */
|
||||
return -ERANGE;
|
||||
|
||||
if (!GREEDY_REALLOC(*p, *n + 1))
|
||||
if (*range)
|
||||
p = *range;
|
||||
else {
|
||||
range_new = new0(UidRange, 1);
|
||||
if (!range_new)
|
||||
return -ENOMEM;
|
||||
|
||||
p = range_new;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(p->entries, p->n_entries + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
(*p)[(*n)++] = (UidRange) {
|
||||
p->entries[p->n_entries++] = (UidRangeEntry) {
|
||||
.start = start,
|
||||
.nr = nr,
|
||||
};
|
||||
|
||||
if (coalesce)
|
||||
uid_range_coalesce(p, n);
|
||||
uid_range_coalesce(p);
|
||||
|
||||
return *n;
|
||||
TAKE_PTR(range_new);
|
||||
*range = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uid_range_add_str(UidRange **p, size_t *n, const char *s) {
|
||||
int uid_range_add_str(UidRange **range, const char *s) {
|
||||
uid_t start, end;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
assert(n);
|
||||
assert(range);
|
||||
assert(s);
|
||||
|
||||
r = parse_uid_range(s, &start, &end);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return uid_range_add(p, n, start, end - start + 1);
|
||||
return uid_range_add_internal(range, start, end - start + 1, /* coalesce = */ true);
|
||||
}
|
||||
|
||||
int uid_range_next_lower(const UidRange *p, size_t n, uid_t *uid) {
|
||||
int uid_range_next_lower(const UidRange *range, uid_t *uid) {
|
||||
uid_t closest = UID_INVALID, candidate;
|
||||
|
||||
assert(p);
|
||||
assert(range);
|
||||
assert(uid);
|
||||
|
||||
if (*uid == 0)
|
||||
@@ -119,11 +140,11 @@ int uid_range_next_lower(const UidRange *p, size_t n, uid_t *uid) {
|
||||
|
||||
candidate = *uid - 1;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
for (size_t i = 0; i < range->n_entries; i++) {
|
||||
uid_t begin, end;
|
||||
|
||||
begin = p[i].start;
|
||||
end = p[i].start + p[i].nr - 1;
|
||||
begin = range->entries[i].start;
|
||||
end = range->entries[i].start + range->entries[i].nr - 1;
|
||||
|
||||
if (candidate >= begin && candidate <= end) {
|
||||
*uid = candidate;
|
||||
@@ -141,26 +162,27 @@ int uid_range_next_lower(const UidRange *p, size_t n, uid_t *uid) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool uid_range_covers(const UidRange *p, size_t n, uid_t start, uid_t nr) {
|
||||
assert(p || n == 0);
|
||||
|
||||
bool uid_range_covers(const UidRange *range, uid_t start, uid_t nr) {
|
||||
if (nr == 0) /* empty range? always covered... */
|
||||
return true;
|
||||
|
||||
if (start > UINT32_MAX - nr) /* range overflows? definitely not covered... */
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < n; i++)
|
||||
if (start >= p[i].start && start + nr <= p[i].start + p[i].nr)
|
||||
if (!range)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < range->n_entries; i++)
|
||||
if (start >= range->entries[i].start &&
|
||||
start + nr <= range->entries[i].start + range->entries[i].nr)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int uid_range_load_userns(UidRange **p, size_t *n, const char *path) {
|
||||
_cleanup_free_ UidRange *q = NULL;
|
||||
int uid_range_load_userns(UidRange **ret, const char *path) {
|
||||
_cleanup_(uid_range_freep) UidRange *range = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
size_t m = 0;
|
||||
int r;
|
||||
|
||||
/* If 'path' is NULL loads the UID range of the userns namespace we run. Otherwise load the data from
|
||||
@@ -169,8 +191,7 @@ int uid_range_load_userns(UidRange **p, size_t *n, const char *path) {
|
||||
*
|
||||
* To simplify things this will modify the passed array in case of later failure. */
|
||||
|
||||
assert(p);
|
||||
assert(n);
|
||||
assert(ret);
|
||||
|
||||
if (!path)
|
||||
path = "/proc/self/uid_map";
|
||||
@@ -185,6 +206,10 @@ int uid_range_load_userns(UidRange **p, size_t *n, const char *path) {
|
||||
return r;
|
||||
}
|
||||
|
||||
range = new0(UidRange, 1);
|
||||
if (!range)
|
||||
return -ENOMEM;
|
||||
|
||||
for (;;) {
|
||||
uid_t uid_base, uid_shift, uid_range;
|
||||
int k;
|
||||
@@ -200,15 +225,13 @@ int uid_range_load_userns(UidRange **p, size_t *n, const char *path) {
|
||||
if (k != 3)
|
||||
return -EBADMSG;
|
||||
|
||||
r = uid_range_add_internal(&q, &m, uid_base, uid_range, /* coalesce = */ false);
|
||||
r = uid_range_add_internal(&range, uid_base, uid_range, /* coalesce = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
uid_range_coalesce(&q, &m);
|
||||
|
||||
*p = TAKE_PTR(q);
|
||||
*n = m;
|
||||
uid_range_coalesce(range);
|
||||
|
||||
*ret = TAKE_PTR(range);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+20
-10
@@ -4,21 +4,31 @@
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct UidRange {
|
||||
#include "macro.h"
|
||||
|
||||
typedef struct UidRangeEntry {
|
||||
uid_t start, nr;
|
||||
} UidRangeEntry;
|
||||
|
||||
typedef struct UidRange {
|
||||
UidRangeEntry *entries;
|
||||
size_t n_entries;
|
||||
} UidRange;
|
||||
|
||||
int uid_range_add_internal(UidRange **p, size_t *n, uid_t start, uid_t nr, bool coalesce);
|
||||
static inline int uid_range_add(UidRange **p, size_t *n, uid_t start, uid_t nr) {
|
||||
return uid_range_add_internal(p, n, start, nr, true);
|
||||
UidRange *uid_range_free(UidRange *range);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(UidRange*, uid_range_free);
|
||||
|
||||
int uid_range_add_internal(UidRange **range, uid_t start, uid_t nr, bool coalesce);
|
||||
static inline int uid_range_add(UidRange **range, uid_t start, uid_t nr) {
|
||||
return uid_range_add_internal(range, start, nr, true);
|
||||
}
|
||||
int uid_range_add_str(UidRange **p, size_t *n, const char *s);
|
||||
int uid_range_add_str(UidRange **range, const char *s);
|
||||
|
||||
int uid_range_next_lower(const UidRange *p, size_t n, uid_t *uid);
|
||||
bool uid_range_covers(const UidRange *p, size_t n, uid_t start, uid_t nr);
|
||||
int uid_range_next_lower(const UidRange *range, uid_t *uid);
|
||||
|
||||
static inline bool uid_range_contains(const UidRange *p, size_t n, uid_t uid) {
|
||||
return uid_range_covers(p, n, uid, 1);
|
||||
bool uid_range_covers(const UidRange *range, uid_t start, uid_t nr);
|
||||
static inline bool uid_range_contains(const UidRange *range, uid_t uid) {
|
||||
return uid_range_covers(range, uid, 1);
|
||||
}
|
||||
|
||||
int uid_range_load_userns(UidRange **p, size_t *n, const char *path);
|
||||
int uid_range_load_userns(UidRange **ret, const char *path);
|
||||
|
||||
Reference in New Issue
Block a user