Various fixes related to mountfsd (#40564)
This commit is contained in:
@@ -618,7 +618,7 @@ int userns_enter_and_pin(int userns_fd, PidRef *ret) {
|
||||
"(sd-pinuserns)",
|
||||
/* stdio_fds= */ NULL,
|
||||
(int[]) { pfd[1], userns_fd }, 2,
|
||||
FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
|
||||
FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_DEATHSIG_SIGKILL,
|
||||
&pidref);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
@@ -878,6 +880,99 @@ static DirectoryOwnership validate_directory_fd(
|
||||
return DIRECTORY_IS_OTHERWISE_OWNED;
|
||||
}
|
||||
|
||||
static int open_tree_try_drop_idmap_harder(sd_varlink *link, int directory_fd, const char *directory_path) {
|
||||
int r;
|
||||
|
||||
_cleanup_close_ int mount_fd = open_tree_try_drop_idmap(
|
||||
directory_fd,
|
||||
"",
|
||||
OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC|AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH);
|
||||
if (mount_fd >= 0)
|
||||
return TAKE_FD(mount_fd);
|
||||
if (mount_fd != -EINVAL)
|
||||
return log_debug_errno(mount_fd, "Failed to issue open_tree() of provided directory '%s': %m", strna(directory_path));
|
||||
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
r = varlink_get_peer_pidref(link, &pidref);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_close_ int mntns_fd = pidref_namespace_open_by_type(&pidref, NAMESPACE_MOUNT);
|
||||
if (mntns_fd < 0)
|
||||
return log_debug_errno(mntns_fd, "Failed to open mount namespace of peer: %m");
|
||||
|
||||
r = is_our_namespace(mntns_fd, NAMESPACE_MOUNT);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to check if peer is in same mount namespace: %m");
|
||||
if (r > 0)
|
||||
return log_debug_errno(mount_fd, "Failed to issue open_tree() of provided directory '%s': %m", strna(directory_path));
|
||||
|
||||
/* The peer is in a different mount namespace. open_tree() will fail with EINVAL on directory fds
|
||||
* from a different mount namespace, so we need to fork off a child process that joins the peer's
|
||||
* mount namespace and calls open_tree() there. */
|
||||
|
||||
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR, mount_fd_socket[2] = EBADF_PAIR;
|
||||
|
||||
if (pipe2(errno_pipe_fd, O_CLOEXEC) < 0)
|
||||
return log_debug_errno(errno, "Failed to create pipe: %m");
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, mount_fd_socket) < 0)
|
||||
return log_debug_errno(errno, "Failed to create socket pair: %m");
|
||||
|
||||
_cleanup_(pidref_done) PidRef child = PIDREF_NULL;
|
||||
r = namespace_fork(
|
||||
"(sd-opentreens)",
|
||||
"(sd-opentree)",
|
||||
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
|
||||
/* pidns_fd= */ -EBADF,
|
||||
mntns_fd,
|
||||
/* netns_fd= */ -EBADF,
|
||||
/* userns_fd= */ -EBADF,
|
||||
/* root_fd= */ -EBADF,
|
||||
&child);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to fork into peer's mount namespace: %m");
|
||||
if (r == 0) {
|
||||
/* Child */
|
||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||
mount_fd_socket[0] = safe_close(mount_fd_socket[0]);
|
||||
|
||||
mount_fd = open_tree_try_drop_idmap(
|
||||
directory_fd,
|
||||
"",
|
||||
OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC|AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH);
|
||||
if (mount_fd < 0) {
|
||||
log_debug_errno(mount_fd, "Failed to issue open_tree() of provided directory '%s': %m", strna(directory_path));
|
||||
report_errno_and_exit(errno_pipe_fd[1], mount_fd);
|
||||
}
|
||||
|
||||
r = send_one_fd(mount_fd_socket[1], mount_fd, /* flags= */ 0);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to send mount fd: %m");
|
||||
report_errno_and_exit(errno_pipe_fd[1], r);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
|
||||
mount_fd_socket[1] = safe_close(mount_fd_socket[1]);
|
||||
|
||||
r = pidref_wait_for_terminate_and_check("(sd-opentreens)", &child, /* flags= */ 0);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to wait for child: %m");
|
||||
|
||||
r = read_errno(errno_pipe_fd[0]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
mount_fd = receive_one_fd(mount_fd_socket[0], MSG_DONTWAIT);
|
||||
if (mount_fd < 0)
|
||||
return log_debug_errno(mount_fd, "Failed to receive mount fd from child: %m");
|
||||
|
||||
return TAKE_FD(mount_fd);
|
||||
}
|
||||
|
||||
static int vl_method_mount_directory(
|
||||
sd_varlink *link,
|
||||
sd_json_variant *parameters,
|
||||
@@ -992,12 +1087,9 @@ static int vl_method_mount_directory(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_close_ int mount_fd = open_tree_try_drop_idmap(
|
||||
directory_fd,
|
||||
"",
|
||||
OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC|AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH);
|
||||
_cleanup_close_ int mount_fd = open_tree_try_drop_idmap_harder(link, directory_fd, directory_path);
|
||||
if (mount_fd < 0)
|
||||
return log_debug_errno(errno, "Failed to issue open_tree() of provided directory '%s': %m", strna(directory_path));
|
||||
return mount_fd;
|
||||
|
||||
/* MOUNT_ATTR_IDMAP has possibly been cleared. Let's verify that the underlying data matches our expectations. */
|
||||
struct stat unmapped_st;
|
||||
|
||||
@@ -31,7 +31,7 @@ void* bpf_rdonly_cast(const void *, __u32) __ksym;
|
||||
* by their inode number in nsfs) that restricts creation of inodes (which would inherit the callers UID/GID)
|
||||
* or changing of ownership (similar).
|
||||
*
|
||||
* This hooks into the various path-based LSM entrypoints that control inode creation as well as chmod(), and
|
||||
* This hooks into the various path-based LSM entrypoints that control inode creation as well as chown(), and
|
||||
* then looks up the calling process' user namespace in a global map of namespaces, which points us to
|
||||
* another map that is simply a list of allowed mnt_ids. */
|
||||
|
||||
@@ -140,6 +140,8 @@ int BPF_PROG(userns_restrict_path_mkdir, struct path *dir, struct dentry *dentry
|
||||
return validate_path(dir, ret);
|
||||
}
|
||||
|
||||
/* The mknod hook covers all file creations, including regular files, in case the reader is looking for a
|
||||
* missing hook for open(). */
|
||||
SEC("lsm/path_mknod")
|
||||
int BPF_PROG(userns_restrict_path_mknod, const struct path *dir, struct dentry *dentry, umode_t mode, unsigned dev, int ret) {
|
||||
return validate_path(dir, ret);
|
||||
|
||||
+118
-118
@@ -15,104 +15,104 @@ TEST(uid_range) {
|
||||
_cleanup_(uid_range_freep) UIDRange *p = NULL;
|
||||
uid_t search;
|
||||
|
||||
assert_se(uid_range_covers(p, 0, 0));
|
||||
assert_se(!uid_range_covers(p, 0, 1));
|
||||
assert_se(!uid_range_covers(p, 100, UINT32_MAX));
|
||||
assert_se(!uid_range_covers(p, UINT32_MAX, 1));
|
||||
assert_se(!uid_range_covers(p, UINT32_MAX - 10, 11));
|
||||
ASSERT_TRUE(uid_range_covers(p, 0, 0));
|
||||
ASSERT_FALSE(uid_range_covers(p, 0, 1));
|
||||
ASSERT_FALSE(uid_range_covers(p, 100, UINT32_MAX));
|
||||
ASSERT_FALSE(uid_range_covers(p, UINT32_MAX, 1));
|
||||
ASSERT_FALSE(uid_range_covers(p, UINT32_MAX - 10, 11));
|
||||
|
||||
assert_se(uid_range_entries(p) == 0);
|
||||
assert_se(uid_range_size(p) == 0);
|
||||
assert_se(uid_range_is_empty(p));
|
||||
ASSERT_EQ(uid_range_entries(p), 0U);
|
||||
ASSERT_EQ(uid_range_size(p), 0U);
|
||||
ASSERT_TRUE(uid_range_is_empty(p));
|
||||
|
||||
assert_se(uid_range_add_str(&p, "500-999") >= 0);
|
||||
assert_se(p);
|
||||
assert_se(uid_range_entries(p) == 1);
|
||||
assert_se(uid_range_size(p) == 500);
|
||||
assert_se(!uid_range_is_empty(p));
|
||||
assert_se(p->entries[0].start == 500);
|
||||
assert_se(p->entries[0].nr == 500);
|
||||
ASSERT_OK(uid_range_add_str(&p, "500-999"));
|
||||
ASSERT_NOT_NULL(p);
|
||||
ASSERT_EQ(uid_range_entries(p), 1U);
|
||||
ASSERT_EQ(uid_range_size(p), 500U);
|
||||
ASSERT_FALSE(uid_range_is_empty(p));
|
||||
ASSERT_EQ(p->entries[0].start, 500U);
|
||||
ASSERT_EQ(p->entries[0].nr, 500U);
|
||||
|
||||
assert_se(!uid_range_contains(p, 499));
|
||||
assert_se(uid_range_contains(p, 500));
|
||||
assert_se(uid_range_contains(p, 999));
|
||||
assert_se(!uid_range_contains(p, 1000));
|
||||
ASSERT_FALSE(uid_range_contains(p, 499));
|
||||
ASSERT_TRUE(uid_range_contains(p, 500));
|
||||
ASSERT_TRUE(uid_range_contains(p, 999));
|
||||
ASSERT_FALSE(uid_range_contains(p, 1000));
|
||||
|
||||
assert_se(!uid_range_covers(p, 100, 150));
|
||||
assert_se(!uid_range_covers(p, 400, 200));
|
||||
assert_se(!uid_range_covers(p, 499, 1));
|
||||
assert_se(uid_range_covers(p, 500, 1));
|
||||
assert_se(uid_range_covers(p, 501, 10));
|
||||
assert_se(uid_range_covers(p, 999, 1));
|
||||
assert_se(!uid_range_covers(p, 999, 2));
|
||||
assert_se(!uid_range_covers(p, 1000, 1));
|
||||
assert_se(!uid_range_covers(p, 1000, 100));
|
||||
assert_se(!uid_range_covers(p, 1001, 100));
|
||||
ASSERT_FALSE(uid_range_covers(p, 100, 150));
|
||||
ASSERT_FALSE(uid_range_covers(p, 400, 200));
|
||||
ASSERT_FALSE(uid_range_covers(p, 499, 1));
|
||||
ASSERT_TRUE(uid_range_covers(p, 500, 1));
|
||||
ASSERT_TRUE(uid_range_covers(p, 501, 10));
|
||||
ASSERT_TRUE(uid_range_covers(p, 999, 1));
|
||||
ASSERT_FALSE(uid_range_covers(p, 999, 2));
|
||||
ASSERT_FALSE(uid_range_covers(p, 1000, 1));
|
||||
ASSERT_FALSE(uid_range_covers(p, 1000, 100));
|
||||
ASSERT_FALSE(uid_range_covers(p, 1001, 100));
|
||||
|
||||
search = UID_INVALID;
|
||||
assert_se(uid_range_next_lower(p, &search));
|
||||
assert_se(search == 999);
|
||||
assert_se(uid_range_next_lower(p, &search));
|
||||
assert_se(search == 998);
|
||||
ASSERT_OK_POSITIVE(uid_range_next_lower(p, &search));
|
||||
ASSERT_EQ(search, 999U);
|
||||
ASSERT_OK_POSITIVE(uid_range_next_lower(p, &search));
|
||||
ASSERT_EQ(search, 998U);
|
||||
search = 501;
|
||||
assert_se(uid_range_next_lower(p, &search));
|
||||
assert_se(search == 500);
|
||||
assert_se(uid_range_next_lower(p, &search) == -EBUSY);
|
||||
ASSERT_OK_POSITIVE(uid_range_next_lower(p, &search));
|
||||
ASSERT_EQ(search, 500U);
|
||||
ASSERT_ERROR(uid_range_next_lower(p, &search), EBUSY);
|
||||
|
||||
assert_se(uid_range_add_str(&p, "1000") >= 0);
|
||||
assert_se(uid_range_entries(p) == 1);
|
||||
assert_se(p->entries[0].start == 500);
|
||||
assert_se(p->entries[0].nr == 501);
|
||||
ASSERT_OK(uid_range_add_str(&p, "1000"));
|
||||
ASSERT_EQ(uid_range_entries(p), 1U);
|
||||
ASSERT_EQ(p->entries[0].start, 500U);
|
||||
ASSERT_EQ(p->entries[0].nr, 501U);
|
||||
|
||||
assert_se(uid_range_add_str(&p, "30-40") >= 0);
|
||||
assert_se(uid_range_entries(p) == 2);
|
||||
assert_se(uid_range_size(p) == 500 + 1 + 11);
|
||||
assert_se(!uid_range_is_empty(p));
|
||||
assert_se(p->entries[0].start == 30);
|
||||
assert_se(p->entries[0].nr == 11);
|
||||
assert_se(p->entries[1].start == 500);
|
||||
assert_se(p->entries[1].nr == 501);
|
||||
ASSERT_OK(uid_range_add_str(&p, "30-40"));
|
||||
ASSERT_EQ(uid_range_entries(p), 2U);
|
||||
ASSERT_EQ(uid_range_size(p), 500U + 1U + 11U);
|
||||
ASSERT_FALSE(uid_range_is_empty(p));
|
||||
ASSERT_EQ(p->entries[0].start, 30U);
|
||||
ASSERT_EQ(p->entries[0].nr, 11U);
|
||||
ASSERT_EQ(p->entries[1].start , 500U);
|
||||
ASSERT_EQ(p->entries[1].nr , 501U);
|
||||
|
||||
assert_se(uid_range_add_str(&p, "60-70") >= 0);
|
||||
assert_se(uid_range_entries(p) == 3);
|
||||
assert_se(uid_range_size(p) == 500 + 1 + 11 + 11);
|
||||
assert_se(!uid_range_is_empty(p));
|
||||
assert_se(p->entries[0].start == 30);
|
||||
assert_se(p->entries[0].nr == 11);
|
||||
assert_se(p->entries[1].start == 60);
|
||||
assert_se(p->entries[1].nr == 11);
|
||||
assert_se(p->entries[2].start == 500);
|
||||
assert_se(p->entries[2].nr == 501);
|
||||
ASSERT_OK(uid_range_add_str(&p, "60-70"));
|
||||
ASSERT_EQ(uid_range_entries(p), 3U);
|
||||
ASSERT_EQ(uid_range_size(p), 500U + 1U + 11U + 11U);
|
||||
ASSERT_FALSE(uid_range_is_empty(p));
|
||||
ASSERT_EQ(p->entries[0].start, 30U);
|
||||
ASSERT_EQ(p->entries[0].nr, 11U);
|
||||
ASSERT_EQ(p->entries[1].start, 60U);
|
||||
ASSERT_EQ(p->entries[1].nr, 11U);
|
||||
ASSERT_EQ(p->entries[2].start, 500U);
|
||||
ASSERT_EQ(p->entries[2].nr, 501U);
|
||||
|
||||
assert_se(uid_range_add_str(&p, "20-2000") >= 0);
|
||||
assert_se(uid_range_entries(p) == 1);
|
||||
assert_se(uid_range_size(p) == 1981);
|
||||
assert_se(p->entries[0].start == 20);
|
||||
assert_se(p->entries[0].nr == 1981);
|
||||
ASSERT_OK(uid_range_add_str(&p, "20-2000"));
|
||||
ASSERT_EQ(uid_range_entries(p), 1U);
|
||||
ASSERT_EQ(uid_range_size(p), 1981U);
|
||||
ASSERT_EQ(p->entries[0].start, 20U);
|
||||
ASSERT_EQ(p->entries[0].nr, 1981U);
|
||||
|
||||
assert_se(uid_range_add_str(&p, "2002") >= 0);
|
||||
assert_se(uid_range_entries(p) == 2);
|
||||
assert_se(uid_range_size(p) == 1982);
|
||||
assert_se(p->entries[0].start == 20);
|
||||
assert_se(p->entries[0].nr == 1981);
|
||||
assert_se(p->entries[1].start == 2002);
|
||||
assert_se(p->entries[1].nr == 1);
|
||||
ASSERT_OK(uid_range_add_str(&p, "2002"));
|
||||
ASSERT_EQ(uid_range_entries(p), 2U);
|
||||
ASSERT_EQ(uid_range_size(p), 1982U);
|
||||
ASSERT_EQ(p->entries[0].start, 20U);
|
||||
ASSERT_EQ(p->entries[0].nr, 1981U);
|
||||
ASSERT_EQ(p->entries[1].start, 2002U);
|
||||
ASSERT_EQ(p->entries[1].nr, 1U);
|
||||
|
||||
_cleanup_(uid_range_freep) UIDRange *q = NULL;
|
||||
assert_se(!uid_range_equal(p, q));
|
||||
assert_se(uid_range_add_str(&q, "20-2000") >= 0);
|
||||
assert_se(!uid_range_equal(p, q));
|
||||
assert_se(uid_range_add_str(&q, "2002") >= 0);
|
||||
assert_se(uid_range_equal(p, q));
|
||||
ASSERT_FALSE(uid_range_equal(p, q));
|
||||
ASSERT_OK(uid_range_add_str(&q, "20-2000"));
|
||||
ASSERT_FALSE(uid_range_equal(p, q));
|
||||
ASSERT_OK(uid_range_add_str(&q, "2002"));
|
||||
ASSERT_TRUE(uid_range_equal(p, q));
|
||||
|
||||
assert_se(uid_range_add_str(&p, "2001") >= 0);
|
||||
assert_se(uid_range_entries(p) == 1);
|
||||
assert_se(uid_range_size(p) == 1983);
|
||||
assert_se(p->entries[0].start == 20);
|
||||
assert_se(p->entries[0].nr == 1983);
|
||||
ASSERT_OK(uid_range_add_str(&p, "2001"));
|
||||
ASSERT_EQ(uid_range_entries(p), 1U);
|
||||
ASSERT_EQ(uid_range_size(p), 1983U);
|
||||
ASSERT_EQ(p->entries[0].start, 20U);
|
||||
ASSERT_EQ(p->entries[0].nr, 1983U);
|
||||
|
||||
assert_se(uid_range_add_str(&q, "2001") >= 0);
|
||||
assert_se(uid_range_equal(p, q));
|
||||
ASSERT_OK(uid_range_add_str(&q, "2001"));
|
||||
ASSERT_TRUE(uid_range_equal(p, q));
|
||||
}
|
||||
|
||||
TEST(load_userns) {
|
||||
@@ -125,74 +125,74 @@ TEST(load_userns) {
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return;
|
||||
|
||||
assert_se(r >= 0);
|
||||
assert_se(uid_range_contains(p, getuid()));
|
||||
ASSERT_OK(r);
|
||||
ASSERT_TRUE(uid_range_contains(p, getuid()));
|
||||
|
||||
r = running_in_userns();
|
||||
if (r == 0) {
|
||||
assert_se(p->n_entries == 1);
|
||||
assert_se(p->entries[0].start == 0);
|
||||
assert_se(p->entries[0].nr == UINT32_MAX);
|
||||
ASSERT_EQ(p->n_entries, 1U);
|
||||
ASSERT_EQ(p->entries[0].start, 0U);
|
||||
ASSERT_EQ(p->entries[0].nr, UINT32_MAX);
|
||||
|
||||
assert_se(uid_range_covers(p, 0, UINT32_MAX));
|
||||
ASSERT_TRUE(uid_range_covers(p, 0, UINT32_MAX));
|
||||
}
|
||||
|
||||
assert_se(fopen_temporary_child(NULL, &f, &fn) >= 0);
|
||||
ASSERT_OK(fopen_temporary_child(NULL, &f, &fn));
|
||||
fputs("0 0 20\n"
|
||||
"100 0 20\n", f);
|
||||
assert_se(fflush_and_check(f) >= 0);
|
||||
ASSERT_OK(fflush_and_check(f));
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
assert_se(uid_range_load_userns(fn, UID_RANGE_USERNS_INSIDE, &p) >= 0);
|
||||
ASSERT_OK(uid_range_load_userns(fn, UID_RANGE_USERNS_INSIDE, &p));
|
||||
|
||||
assert_se(uid_range_contains(p, 0));
|
||||
assert_se(uid_range_contains(p, 19));
|
||||
assert_se(!uid_range_contains(p, 20));
|
||||
ASSERT_TRUE(uid_range_contains(p, 0));
|
||||
ASSERT_TRUE(uid_range_contains(p, 19));
|
||||
ASSERT_FALSE(uid_range_contains(p, 20));
|
||||
|
||||
assert_se(!uid_range_contains(p, 99));
|
||||
assert_se(uid_range_contains(p, 100));
|
||||
assert_se(uid_range_contains(p, 119));
|
||||
assert_se(!uid_range_contains(p, 120));
|
||||
ASSERT_FALSE(uid_range_contains(p, 99));
|
||||
ASSERT_TRUE(uid_range_contains(p, 100));
|
||||
ASSERT_TRUE(uid_range_contains(p, 119));
|
||||
ASSERT_FALSE(uid_range_contains(p, 120));
|
||||
}
|
||||
|
||||
TEST(uid_range_coalesce) {
|
||||
_cleanup_(uid_range_freep) UIDRange *p = NULL;
|
||||
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
assert_se(uid_range_add_internal(&p, i * 10, 10, /* coalesce= */ false) >= 0);
|
||||
assert_se(uid_range_add_internal(&p, i * 10 + 5, 10, /* coalesce= */ false) >= 0);
|
||||
ASSERT_OK(uid_range_add_internal(&p, i * 10, 10, /* coalesce= */ false));
|
||||
ASSERT_OK(uid_range_add_internal(&p, i * 10 + 5, 10, /* coalesce= */ false));
|
||||
}
|
||||
|
||||
assert_se(uid_range_add_internal(&p, 100, 1, /* coalesce= */ true) >= 0);
|
||||
assert_se(p->n_entries == 1);
|
||||
assert_se(p->entries[0].start == 0);
|
||||
assert_se(p->entries[0].nr == 105);
|
||||
ASSERT_OK(uid_range_add_internal(&p, 100, 1, /* coalesce= */ true));
|
||||
ASSERT_EQ(p->n_entries, 1U);
|
||||
ASSERT_EQ(p->entries[0].start, 0U);
|
||||
ASSERT_EQ(p->entries[0].nr, 105U);
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
assert_se(uid_range_add_internal(&p, (10 - i) * 10, 10, /* coalesce= */ false) >= 0);
|
||||
assert_se(uid_range_add_internal(&p, (10 - i) * 10 + 5, 10, /* coalesce= */ false) >= 0);
|
||||
ASSERT_OK(uid_range_add_internal(&p, (10 - i) * 10, 10, /* coalesce= */ false));
|
||||
ASSERT_OK(uid_range_add_internal(&p, (10 - i) * 10 + 5, 10, /* coalesce= */ false));
|
||||
}
|
||||
|
||||
assert_se(uid_range_add_internal(&p, 100, 1, /* coalesce= */ true) >= 0);
|
||||
assert_se(p->n_entries == 1);
|
||||
assert_se(p->entries[0].start == 10);
|
||||
assert_se(p->entries[0].nr == 105);
|
||||
ASSERT_OK(uid_range_add_internal(&p, 100, 1, /* coalesce= */ true));
|
||||
ASSERT_EQ(p->n_entries, 1U);
|
||||
ASSERT_EQ(p->entries[0].start, 10U);
|
||||
ASSERT_EQ(p->entries[0].nr, 105U);
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
assert_se(uid_range_add_internal(&p, i * 10, 10, /* coalesce= */ false) >= 0);
|
||||
assert_se(uid_range_add_internal(&p, i * 10 + 5, 10, /* coalesce= */ false) >= 0);
|
||||
assert_se(uid_range_add_internal(&p, (10 - i) * 10, 10, /* coalesce= */ false) >= 0);
|
||||
assert_se(uid_range_add_internal(&p, (10 - i) * 10 + 5, 10, /* coalesce= */ false) >= 0);
|
||||
ASSERT_OK(uid_range_add_internal(&p, i * 10, 10, /* coalesce= */ false));
|
||||
ASSERT_OK(uid_range_add_internal(&p, i * 10 + 5, 10, /* coalesce= */ false));
|
||||
ASSERT_OK(uid_range_add_internal(&p, (10 - i) * 10, 10, /* coalesce= */ false));
|
||||
ASSERT_OK(uid_range_add_internal(&p, (10 - i) * 10 + 5, 10, /* coalesce= */ false));
|
||||
}
|
||||
assert_se(uid_range_add_internal(&p, 100, 1, /* coalesce= */ true) >= 0);
|
||||
assert_se(p->n_entries == 1);
|
||||
assert_se(p->entries[0].start == 0);
|
||||
assert_se(p->entries[0].nr == 115);
|
||||
ASSERT_OK(uid_range_add_internal(&p, 100, 1, /* coalesce= */ true));
|
||||
ASSERT_EQ(p->n_entries, 1U);
|
||||
ASSERT_EQ(p->entries[0].start, 0U);
|
||||
ASSERT_EQ(p->entries[0].nr, 115U);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
Reference in New Issue
Block a user