132 lines
3.2 KiB
C
132 lines
3.2 KiB
C
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
#define _GNU_SOURCE
|
|
#include <unistd.h>
|
|
#include <sched.h>
|
|
#include <sys/stat.h>
|
|
#include <pthread.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "../test.h"
|
|
|
|
FN_TEST(invalid_flags)
|
|
{
|
|
TEST_ERRNO(unshare(CLONE_CHILD_CLEARTID), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_CHILD_SETTID), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_DETACHED), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_IO), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_PARENT), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_PARENT_SETTID), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_PIDFD), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_PTRACE), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_SETTLS), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_UNTRACED), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_VFORK), EINVAL);
|
|
}
|
|
END_TEST()
|
|
|
|
void *sleep_1s_thread(void *arg)
|
|
{
|
|
sleep(1);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
FN_TEST(single_thread_flags)
|
|
{
|
|
TEST_SUCC(unshare(CLONE_VM | CLONE_SIGHAND | CLONE_THREAD));
|
|
|
|
pthread_t thread_id;
|
|
TEST_SUCC(pthread_create(&thread_id, NULL, sleep_1s_thread, NULL));
|
|
|
|
TEST_ERRNO(unshare(CLONE_VM), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_SIGHAND), EINVAL);
|
|
TEST_ERRNO(unshare(CLONE_THREAD), EINVAL);
|
|
|
|
TEST_SUCC(pthread_join(thread_id, NULL));
|
|
|
|
TEST_SUCC(unshare(CLONE_VM));
|
|
TEST_SUCC(unshare(CLONE_SIGHAND));
|
|
TEST_SUCC(unshare(CLONE_THREAD));
|
|
}
|
|
END_TEST()
|
|
|
|
void *unshare_files_thread(void *arg)
|
|
{
|
|
int test_fd = (int)(intptr_t)arg;
|
|
|
|
CHECK(unshare(CLONE_FILES));
|
|
CHECK(close(test_fd));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
FN_TEST(unshare_files)
|
|
{
|
|
struct stat old_stdin_stat, old_stdout_stat, old_stderr_stat;
|
|
struct stat new_stdin_stat, new_stdout_stat, new_stderr_stat;
|
|
|
|
TEST_SUCC(fstat(STDIN_FILENO, &old_stdin_stat));
|
|
TEST_SUCC(fstat(STDOUT_FILENO, &old_stdout_stat));
|
|
TEST_SUCC(fstat(STDERR_FILENO, &old_stderr_stat));
|
|
|
|
TEST_SUCC(unshare(CLONE_FILES));
|
|
|
|
TEST_RES(fstat(STDIN_FILENO, &new_stdin_stat),
|
|
old_stdin_stat.st_ino == new_stdin_stat.st_ino);
|
|
TEST_RES(fstat(STDOUT_FILENO, &new_stdout_stat),
|
|
old_stdout_stat.st_ino == new_stdout_stat.st_ino);
|
|
TEST_RES(fstat(STDERR_FILENO, &new_stderr_stat),
|
|
old_stderr_stat.st_ino == new_stderr_stat.st_ino);
|
|
|
|
const char *TEST_FILENAME = "/tmp/unshare_files_test.txt";
|
|
pthread_t thread_id;
|
|
struct stat stat1, stat2;
|
|
int test_fd;
|
|
|
|
test_fd = TEST_SUCC(
|
|
open(TEST_FILENAME, O_CREAT | O_RDWR | O_TRUNC, 0644));
|
|
TEST_SUCC(fstat(test_fd, &stat1));
|
|
|
|
TEST_SUCC(pthread_create(&thread_id, NULL, unshare_files_thread,
|
|
(void *)(intptr_t)test_fd));
|
|
TEST_SUCC(pthread_join(thread_id, NULL));
|
|
|
|
TEST_RES(fstat(test_fd, &stat2), stat1.st_ino == stat2.st_ino);
|
|
TEST_SUCC(close(test_fd));
|
|
TEST_SUCC(unlink(TEST_FILENAME));
|
|
}
|
|
END_TEST()
|
|
|
|
#define CWD_BUF_SIZE 1024
|
|
#define THREAD_CWD "/tmp"
|
|
|
|
void *unshare_fs_thread(void *arg)
|
|
{
|
|
CHECK(unshare(CLONE_FS));
|
|
|
|
CHECK(chdir(THREAD_CWD));
|
|
CHECK(getcwd((char *)arg, CWD_BUF_SIZE));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
FN_TEST(unshare_fs)
|
|
{
|
|
char cwd_buf1[CWD_BUF_SIZE], cwd_buf2[CWD_BUF_SIZE];
|
|
pthread_t thread_id;
|
|
|
|
TEST_RES(getcwd(cwd_buf1, CWD_BUF_SIZE),
|
|
strcmp(cwd_buf1, THREAD_CWD) != 0);
|
|
|
|
TEST_SUCC(pthread_create(&thread_id, NULL, unshare_fs_thread,
|
|
(void *)cwd_buf2));
|
|
|
|
TEST_RES(pthread_join(thread_id, NULL),
|
|
strcmp(cwd_buf2, THREAD_CWD) == 0);
|
|
|
|
TEST_RES(getcwd(cwd_buf2, CWD_BUF_SIZE),
|
|
strcmp(cwd_buf1, cwd_buf2) == 0);
|
|
}
|
|
END_TEST()
|