Merge tag 'landlock-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux

Pull Landlock updates from Mickaël Salaün:

 - improve the path_rename LSM hook implementations for RENAME_EXCHANGE;

 - fix a too-restrictive filesystem control for a rare corner case;

 - set the nested sandbox limitation to 16 layers;

 - add a new LANDLOCK_ACCESS_FS_REFER access right to properly handle
   file reparenting (i.e. full rename and link support);

 - add new tests and documentation;

 - format code with clang-format to make it easier to maintain and
   contribute.

* tag 'landlock-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: (30 commits)
  landlock: Explain how to support Landlock
  landlock: Add design choices documentation for filesystem access rights
  landlock: Document good practices about filesystem policies
  landlock: Document LANDLOCK_ACCESS_FS_REFER and ABI versioning
  samples/landlock: Add support for file reparenting
  selftests/landlock: Add 11 new test suites dedicated to file reparenting
  landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER
  LSM: Remove double path_rename hook calls for RENAME_EXCHANGE
  landlock: Move filesystem helpers and add a new one
  landlock: Fix same-layer rule unions
  landlock: Create find_rule() from unmask_layers()
  landlock: Reduce the maximum number of layers to 16
  landlock: Define access_mask_t to enforce a consistent access mask size
  selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
  landlock: Change landlock_restrict_self(2) check ordering
  landlock: Change landlock_add_rule(2) argument check ordering
  selftests/landlock: Add tests for O_PATH
  selftests/landlock: Fully test file rename with "remove" access
  selftests/landlock: Extend access right tests to directories
  selftests/landlock: Add tests for unknown access rights
  ...
This commit is contained in:
Linus Torvalds
2022-05-24 13:09:13 -07:00
24 changed files with 2597 additions and 711 deletions

View File

@@ -18,10 +18,11 @@
#include "common.h"
#ifndef O_PATH
#define O_PATH 010000000
#define O_PATH 010000000
#endif
TEST(inconsistent_attr) {
TEST(inconsistent_attr)
{
const long page_size = sysconf(_SC_PAGESIZE);
char *const buf = malloc(page_size + 1);
struct landlock_ruleset_attr *const ruleset_attr = (void *)buf;
@@ -34,20 +35,26 @@ TEST(inconsistent_attr) {
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 1, 0));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 7, 0));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 1, 0));
/* The size if less than sizeof(struct landlock_attr_enforce). */
ASSERT_EQ(EFAULT, errno);
ASSERT_EQ(-1, landlock_create_ruleset(NULL,
sizeof(struct landlock_ruleset_attr), 0));
ASSERT_EQ(-1, landlock_create_ruleset(
NULL, sizeof(struct landlock_ruleset_attr), 0));
ASSERT_EQ(EFAULT, errno);
ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size + 1, 0));
ASSERT_EQ(E2BIG, errno);
ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr,
sizeof(struct landlock_ruleset_attr), 0));
/* Checks minimal valid attribute size. */
ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 8, 0));
ASSERT_EQ(ENOMSG, errno);
ASSERT_EQ(-1, landlock_create_ruleset(
ruleset_attr,
sizeof(struct landlock_ruleset_attr), 0));
ASSERT_EQ(ENOMSG, errno);
ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size, 0));
ASSERT_EQ(ENOMSG, errno);
@@ -63,38 +70,44 @@ TEST(inconsistent_attr) {
free(buf);
}
TEST(abi_version) {
TEST(abi_version)
{
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
};
ASSERT_EQ(1, landlock_create_ruleset(NULL, 0,
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(2, landlock_create_ruleset(NULL, 0,
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
LANDLOCK_CREATE_RULESET_VERSION));
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
LANDLOCK_CREATE_RULESET_VERSION));
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr),
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(-1,
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
LANDLOCK_CREATE_RULESET_VERSION));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
LANDLOCK_CREATE_RULESET_VERSION | 1 << 31));
LANDLOCK_CREATE_RULESET_VERSION |
1 << 31));
ASSERT_EQ(EINVAL, errno);
}
TEST(inval_create_ruleset_flags) {
/* Tests ordering of syscall argument checks. */
TEST(create_ruleset_checks_ordering)
{
const int last_flag = LANDLOCK_CREATE_RULESET_VERSION;
const int invalid_flag = last_flag << 1;
int ruleset_fd;
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
};
/* Checks priority for invalid flags. */
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0, invalid_flag));
ASSERT_EQ(EINVAL, errno);
@@ -102,44 +115,121 @@ TEST(inval_create_ruleset_flags) {
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
invalid_flag));
invalid_flag));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr), invalid_flag));
ASSERT_EQ(-1,
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
invalid_flag));
ASSERT_EQ(EINVAL, errno);
}
TEST(empty_path_beneath_attr) {
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
};
const int ruleset_fd = landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr), 0);
/* Checks too big ruleset_attr size. */
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, -1, 0));
ASSERT_EQ(E2BIG, errno);
/* Checks too small ruleset_attr size. */
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, 0));
ASSERT_EQ(EINVAL, errno);
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 1, 0));
ASSERT_EQ(EINVAL, errno);
/* Checks valid call. */
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
/* Similar to struct landlock_path_beneath_attr.parent_fd = 0 */
ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
NULL, 0));
ASSERT_EQ(EFAULT, errno);
ASSERT_EQ(0, close(ruleset_fd));
}
TEST(inval_fd_enforce) {
ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
/* Tests ordering of syscall argument checks. */
TEST(add_rule_checks_ordering)
{
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
};
struct landlock_path_beneath_attr path_beneath_attr = {
.allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
.parent_fd = -1,
};
const int ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
ASSERT_LE(0, ruleset_fd);
/* Checks invalid flags. */
ASSERT_EQ(-1, landlock_add_rule(-1, 0, NULL, 1));
ASSERT_EQ(EINVAL, errno);
/* Checks invalid ruleset FD. */
ASSERT_EQ(-1, landlock_add_rule(-1, 0, NULL, 0));
ASSERT_EQ(EBADF, errno);
/* Checks invalid rule type. */
ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, 0, NULL, 0));
ASSERT_EQ(EINVAL, errno);
/* Checks invalid rule attr. */
ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
NULL, 0));
ASSERT_EQ(EFAULT, errno);
/* Checks invalid path_beneath.parent_fd. */
ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath_attr, 0));
ASSERT_EQ(EBADF, errno);
/* Checks valid call. */
path_beneath_attr.parent_fd =
open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
ASSERT_LE(0, path_beneath_attr.parent_fd);
ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath_attr, 0));
ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
ASSERT_EQ(0, close(ruleset_fd));
}
TEST(unpriv_enforce_without_no_new_privs) {
int err;
/* Tests ordering of syscall argument and permission checks. */
TEST(restrict_self_checks_ordering)
{
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
};
struct landlock_path_beneath_attr path_beneath_attr = {
.allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
.parent_fd = -1,
};
const int ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
path_beneath_attr.parent_fd =
open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
ASSERT_LE(0, path_beneath_attr.parent_fd);
ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath_attr, 0));
ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
/* Checks unprivileged enforcement without no_new_privs. */
drop_caps(_metadata);
err = landlock_restrict_self(-1, 0);
ASSERT_EQ(-1, landlock_restrict_self(-1, -1));
ASSERT_EQ(EPERM, errno);
ASSERT_EQ(err, -1);
ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
ASSERT_EQ(EPERM, errno);
ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
ASSERT_EQ(EPERM, errno);
ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
/* Checks invalid flags. */
ASSERT_EQ(-1, landlock_restrict_self(-1, -1));
ASSERT_EQ(EINVAL, errno);
/* Checks invalid ruleset FD. */
ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
ASSERT_EQ(EBADF, errno);
/* Checks valid call. */
ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
ASSERT_EQ(0, close(ruleset_fd));
}
TEST(ruleset_fd_io)
@@ -151,8 +241,8 @@ TEST(ruleset_fd_io)
char buf;
drop_caps(_metadata);
ruleset_fd = landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr), 0);
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
ASSERT_EQ(-1, write(ruleset_fd, ".", 1));
@@ -197,14 +287,15 @@ TEST(ruleset_fd_transfer)
drop_caps(_metadata);
/* Creates a test ruleset with a simple rule. */
ruleset_fd_tx = landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr), 0);
ruleset_fd_tx =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd_tx);
path_beneath_attr.parent_fd = open("/tmp", O_PATH | O_NOFOLLOW |
O_DIRECTORY | O_CLOEXEC);
path_beneath_attr.parent_fd =
open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
ASSERT_LE(0, path_beneath_attr.parent_fd);
ASSERT_EQ(0, landlock_add_rule(ruleset_fd_tx, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath_attr, 0));
ASSERT_EQ(0,
landlock_add_rule(ruleset_fd_tx, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath_attr, 0));
ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
cmsg = CMSG_FIRSTHDR(&msg);
@@ -215,7 +306,8 @@ TEST(ruleset_fd_transfer)
memcpy(CMSG_DATA(cmsg), &ruleset_fd_tx, sizeof(ruleset_fd_tx));
/* Sends the ruleset FD over a socketpair and then close it. */
ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, socket_fds));
ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
socket_fds));
ASSERT_EQ(sizeof(data_tx), sendmsg(socket_fds[0], &msg, 0));
ASSERT_EQ(0, close(socket_fds[0]));
ASSERT_EQ(0, close(ruleset_fd_tx));
@@ -226,7 +318,8 @@ TEST(ruleset_fd_transfer)
int ruleset_fd_rx;
*(char *)msg.msg_iov->iov_base = '\0';
ASSERT_EQ(sizeof(data_tx), recvmsg(socket_fds[1], &msg, MSG_CMSG_CLOEXEC));
ASSERT_EQ(sizeof(data_tx),
recvmsg(socket_fds[1], &msg, MSG_CMSG_CLOEXEC));
ASSERT_EQ('.', *(char *)msg.msg_iov->iov_base);
ASSERT_EQ(0, close(socket_fds[1]));
cmsg = CMSG_FIRSTHDR(&msg);

View File

@@ -25,6 +25,7 @@
* this to be possible, we must not call abort() but instead exit smoothly
* (hence the step print).
*/
/* clang-format off */
#define TEST_F_FORK(fixture_name, test_name) \
static void fixture_name##_##test_name##_child( \
struct __test_metadata *_metadata, \
@@ -71,11 +72,12 @@
FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
const FIXTURE_VARIANT(fixture_name) \
__attribute__((unused)) *variant)
/* clang-format on */
#ifndef landlock_create_ruleset
static inline int landlock_create_ruleset(
const struct landlock_ruleset_attr *const attr,
const size_t size, const __u32 flags)
static inline int
landlock_create_ruleset(const struct landlock_ruleset_attr *const attr,
const size_t size, const __u32 flags)
{
return syscall(__NR_landlock_create_ruleset, attr, size, flags);
}
@@ -83,17 +85,18 @@ static inline int landlock_create_ruleset(
#ifndef landlock_add_rule
static inline int landlock_add_rule(const int ruleset_fd,
const enum landlock_rule_type rule_type,
const void *const rule_attr, const __u32 flags)
const enum landlock_rule_type rule_type,
const void *const rule_attr,
const __u32 flags)
{
return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type,
rule_attr, flags);
return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, rule_attr,
flags);
}
#endif
#ifndef landlock_restrict_self
static inline int landlock_restrict_self(const int ruleset_fd,
const __u32 flags)
const __u32 flags)
{
return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
}
@@ -111,69 +114,76 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
};
cap_p = cap_get_proc();
EXPECT_NE(NULL, cap_p) {
EXPECT_NE(NULL, cap_p)
{
TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_clear(cap_p)) {
EXPECT_NE(-1, cap_clear(cap_p))
{
TH_LOG("Failed to cap_clear: %s", strerror(errno));
}
if (!drop_all) {
EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED,
ARRAY_SIZE(caps), caps, CAP_SET)) {
ARRAY_SIZE(caps), caps, CAP_SET))
{
TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
}
}
EXPECT_NE(-1, cap_set_proc(cap_p)) {
EXPECT_NE(-1, cap_set_proc(cap_p))
{
TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_free(cap_p)) {
EXPECT_NE(-1, cap_free(cap_p))
{
TH_LOG("Failed to cap_free: %s", strerror(errno));
}
}
/* We cannot put such helpers in a library because of kselftest_harness.h . */
__attribute__((__unused__))
static void disable_caps(struct __test_metadata *const _metadata)
__attribute__((__unused__)) static void
disable_caps(struct __test_metadata *const _metadata)
{
_init_caps(_metadata, false);
}
__attribute__((__unused__))
static void drop_caps(struct __test_metadata *const _metadata)
__attribute__((__unused__)) static void
drop_caps(struct __test_metadata *const _metadata)
{
_init_caps(_metadata, true);
}
static void _effective_cap(struct __test_metadata *const _metadata,
const cap_value_t caps, const cap_flag_value_t value)
const cap_value_t caps, const cap_flag_value_t value)
{
cap_t cap_p;
cap_p = cap_get_proc();
EXPECT_NE(NULL, cap_p) {
EXPECT_NE(NULL, cap_p)
{
TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value)) {
EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value))
{
TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
}
EXPECT_NE(-1, cap_set_proc(cap_p)) {
EXPECT_NE(-1, cap_set_proc(cap_p))
{
TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_free(cap_p)) {
EXPECT_NE(-1, cap_free(cap_p))
{
TH_LOG("Failed to cap_free: %s", strerror(errno));
}
}
__attribute__((__unused__))
static void set_cap(struct __test_metadata *const _metadata,
const cap_value_t caps)
__attribute__((__unused__)) static void
set_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
{
_effective_cap(_metadata, caps, CAP_SET);
}
__attribute__((__unused__))
static void clear_cap(struct __test_metadata *const _metadata,
const cap_value_t caps)
__attribute__((__unused__)) static void
clear_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
{
_effective_cap(_metadata, caps, CAP_CLEAR);
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,9 +26,10 @@ static void create_domain(struct __test_metadata *const _metadata)
.handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_BLOCK,
};
ruleset_fd = landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr), 0);
EXPECT_LE(0, ruleset_fd) {
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
EXPECT_LE(0, ruleset_fd)
{
TH_LOG("Failed to create a ruleset: %s", strerror(errno));
}
EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
@@ -43,7 +44,7 @@ static int test_ptrace_read(const pid_t pid)
int procenv_path_size, fd;
procenv_path_size = snprintf(procenv_path, sizeof(procenv_path),
path_template, pid);
path_template, pid);
if (procenv_path_size >= sizeof(procenv_path))
return E2BIG;
@@ -59,9 +60,12 @@ static int test_ptrace_read(const pid_t pid)
return 0;
}
FIXTURE(hierarchy) { };
/* clang-format off */
FIXTURE(hierarchy) {};
/* clang-format on */
FIXTURE_VARIANT(hierarchy) {
FIXTURE_VARIANT(hierarchy)
{
const bool domain_both;
const bool domain_parent;
const bool domain_child;
@@ -83,7 +87,9 @@ FIXTURE_VARIANT(hierarchy) {
* \ P2 -> P1 : allow
* 'P2
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, allow_without_domain) {
/* clang-format on */
.domain_both = false,
.domain_parent = false,
.domain_child = false,
@@ -98,7 +104,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_without_domain) {
* | P2 |
* '------'
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, allow_with_one_domain) {
/* clang-format on */
.domain_both = false,
.domain_parent = false,
.domain_child = true,
@@ -112,7 +120,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_with_one_domain) {
* '
* P2
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, deny_with_parent_domain) {
/* clang-format on */
.domain_both = false,
.domain_parent = true,
.domain_child = false,
@@ -127,7 +137,9 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with_parent_domain) {
* | P2 |
* '------'
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, deny_with_sibling_domain) {
/* clang-format on */
.domain_both = false,
.domain_parent = true,
.domain_child = true,
@@ -142,7 +154,9 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with_sibling_domain) {
* | P2 |
* '-------------'
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, allow_sibling_domain) {
/* clang-format on */
.domain_both = true,
.domain_parent = false,
.domain_child = false,
@@ -158,7 +172,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_sibling_domain) {
* | '------' |
* '-----------------'
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, allow_with_nested_domain) {
/* clang-format on */
.domain_both = true,
.domain_parent = false,
.domain_child = true,
@@ -174,7 +190,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_with_nested_domain) {
* | P2 |
* '-----------------'
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, deny_with_nested_and_parent_domain) {
/* clang-format on */
.domain_both = true,
.domain_parent = true,
.domain_child = false,
@@ -192,17 +210,21 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with_nested_and_parent_domain) {
* | '------' |
* '-----------------'
*/
/* clang-format off */
FIXTURE_VARIANT_ADD(hierarchy, deny_with_forked_domain) {
/* clang-format on */
.domain_both = true,
.domain_parent = true,
.domain_child = true,
};
FIXTURE_SETUP(hierarchy)
{ }
{
}
FIXTURE_TEARDOWN(hierarchy)
{ }
{
}
/* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */
TEST_F(hierarchy, trace)
@@ -330,7 +352,7 @@ TEST_F(hierarchy, trace)
ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
ASSERT_EQ(child, waitpid(child, &status, 0));
if (WIFSIGNALED(status) || !WIFEXITED(status) ||
WEXITSTATUS(status) != EXIT_SUCCESS)
WEXITSTATUS(status) != EXIT_SUCCESS)
_metadata->passed = 0;
}