Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 82 additions & 10 deletions tools/testing/selftests/landlock/fs_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
* Copyright © 2020 ANSSI
* Copyright © 2020-2022 Microsoft Corporation
* Copyright © 2025 Tingmao Wang <m@maowtm.org>
*/

#define _GNU_SOURCE
Expand Down Expand Up @@ -215,14 +216,74 @@ static void mkdir_parents(struct __test_metadata *const _metadata,
free(walker);
}

static void
maybe_warn_about_permission_on_cwd(struct __test_metadata *const _metadata,
int err)
{
char abspath_buf[255];

if (err == EACCES) {
const char *realp = realpath(".", abspath_buf);

if (realp == NULL)
realp = ".";

TH_LOG("Hint: fs_tests requires permissions for uid %u on test directory %s "
"and files under it (even when running as root).",
getuid(), realp);
TH_LOG(" Try chmod a+rwX -R %s", realp);
}
}

static int try_teardown_layout(struct __test_metadata *const _metadata)
{
struct stat stat_buf;

if (stat(TMP_DIR, &stat_buf) < 0)
return -1;

TH_LOG("Attempting to cleanup layout and retry...");

if (umount(TMP_DIR)) {
if (errno != EINVAL && errno != ENOENT) {
TH_LOG("Failed to unmount directory \"%s\": %s",
TMP_DIR, strerror(errno));
return -1;
}
}
if (rmdir(TMP_DIR)) {
if (errno != ENOENT) {
TH_LOG("Failed to remove directory \"%s\": %s", TMP_DIR,
strerror(errno));
return -1;
}
}
return 0;
}

static void create_directory(struct __test_metadata *const _metadata,
const char *const path)
{
bool retried = false;

retry:
mkdir_parents(_metadata, path);
ASSERT_EQ(0, mkdir(path, 0700))
{
if (mkdir(path, 0700)) {
int err = errno;

TH_LOG("Failed to create directory \"%s\": %s", path,
strerror(errno));
strerror(err));

if (strcmp(path, TMP_DIR) == 0) {
maybe_warn_about_permission_on_cwd(_metadata, err);
if (!retried && errno == EEXIST &&
!try_teardown_layout(_metadata)) {
retried = true;
goto retry;
}
}

ASSERT_TRUE(false);
}
}

Expand Down Expand Up @@ -296,17 +357,18 @@ static void prepare_layout_opt(struct __test_metadata *const _metadata,
{
disable_caps(_metadata);
umask(0077);

/* create_directory may try umounting then rmdir if tmp already mounted */
set_cap(_metadata, CAP_SYS_ADMIN);
create_directory(_metadata, TMP_DIR);

/*
* Do not pollute the rest of the system: creates a private mount point
* for tests relying on pivot_root(2) and move_mount(2).
*/
set_cap(_metadata, CAP_SYS_ADMIN);
ASSERT_EQ(0, unshare(CLONE_NEWNS | CLONE_NEWCGROUP));
ASSERT_EQ(0, mount_opt(mnt, TMP_DIR))
ASSERT_EQ(0, unshare(CLONE_NEWNS | CLONE_NEWCGROUP))
{
TH_LOG("Failed to mount the %s filesystem: %s", mnt->type,
TH_LOG("Failed to create new mount namespace: %s",
strerror(errno));
/*
* FIXTURE_TEARDOWN() is not called when FIXTURE_SETUP()
Expand All @@ -316,6 +378,12 @@ static void prepare_layout_opt(struct __test_metadata *const _metadata,
*/
remove_path(TMP_DIR);
}
ASSERT_EQ(0, mount_opt(mnt, TMP_DIR))
{
TH_LOG("Failed to mount the %s filesystem: %s", mnt->type,
strerror(errno));
remove_path(TMP_DIR);
}
ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
clear_cap(_metadata, CAP_SYS_ADMIN);
}
Expand Down Expand Up @@ -1979,18 +2047,22 @@ TEST_F_FORK(layout1, relative_chroot_chdir)
static void copy_file(struct __test_metadata *const _metadata,
const char *const src_path, const char *const dst_path)
{
int dst_fd, src_fd;
int dst_fd, src_fd, err;
struct stat statbuf;

dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
ASSERT_LE(0, dst_fd)
{
TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
err = errno;
TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(err));
maybe_warn_about_permission_on_cwd(_metadata, err);
}
src_fd = open(src_path, O_RDONLY | O_CLOEXEC);
ASSERT_LE(0, src_fd)
{
TH_LOG("Failed to open \"%s\": %s", src_path, strerror(errno));
err = errno;
TH_LOG("Failed to open \"%s\": %s", src_path, strerror(err));
maybe_warn_about_permission_on_cwd(_metadata, err);
}
ASSERT_EQ(0, fstat(src_fd, &statbuf));
ASSERT_EQ(statbuf.st_size,
Expand Down