Skip to content

Commit

Permalink
Add landlock01 test
Browse files Browse the repository at this point in the history
This test verifies that landlock_create_ruleset syscall fails with the
right error codes:

- EINVAL Unknown flags, or unknown access, or too small size
- E2BIG size is too big
- EFAULT attr was not a valid address
- ENOMSG Empty accesses (i.e., attr->handled_access_fs is 0)

Link: https://lore.kernel.org/ltp/20240711-landlock-v3-5-c7b0e9edf9b0@suse.com/
Reviewed-by: Li Wang <liwang@redhat.com>
Reviewed-by: Petr Vorel <pvorel@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
  • Loading branch information
acerv authored and pevik committed Jul 12, 2024
1 parent 7978423 commit 4e17e90
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 0 deletions.
2 changes: 2 additions & 0 deletions runtest/syscalls
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,8 @@ kill11 kill11
kill12 kill12
kill13 kill13

landlock01 landlock01

lchown01 lchown01
lchown01_16 lchown01_16
lchown02 lchown02
Expand Down
1 change: 1 addition & 0 deletions testcases/kernel/syscalls/landlock/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
landlock01
7 changes: 7 additions & 0 deletions testcases/kernel/syscalls/landlock/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>

top_srcdir ?= ../../../..

include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
92 changes: 92 additions & 0 deletions testcases/kernel/syscalls/landlock/landlock01.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/

/*\
* [Description]
*
* This test verifies that landlock_create_ruleset syscall fails with the right
* error codes:
*
* - EINVAL Unknown flags, or unknown access, or too small size
* - E2BIG size is too big
* - EFAULT attr was not a valid address
* - ENOMSG Empty accesses (i.e., attr->handled_access_fs is 0)
*/

#include "landlock_common.h"

static struct landlock_ruleset_attr *ruleset_attr;
static struct landlock_ruleset_attr *null_attr;
static size_t rule_size;
static size_t rule_small_size;
static size_t rule_big_size;

static struct tcase {
struct landlock_ruleset_attr **attr;
uint64_t access_fs;
size_t *size;
uint32_t flags;
int exp_errno;
char *msg;
} tcases[] = {
{&ruleset_attr, -1, &rule_size, 0, EINVAL, "Unknown access"},
{&ruleset_attr, 0, &rule_small_size, 0, EINVAL, "Size is too small"},
{&ruleset_attr, 0, &rule_size, -1, EINVAL, "Unknown flags"},
{&ruleset_attr, 0, &rule_big_size, 0, E2BIG, "Size is too big"},
{&null_attr, 0, &rule_size, 0, EFAULT, "Invalid attr address"},
{&ruleset_attr, 0, &rule_size, 0, ENOMSG, "Empty accesses"},
};

static void run(unsigned int n)
{
struct tcase *tc = &tcases[n];

if (*tc->attr)
(*tc->attr)->handled_access_fs = tc->access_fs;

TST_EXP_FAIL(tst_syscall(__NR_landlock_create_ruleset,
*tc->attr, *tc->size, tc->flags),
tc->exp_errno,
"%s",
tc->msg);

if (TST_RET >= 0)
SAFE_CLOSE(TST_RET);
}

static void setup(void)
{
verify_landlock_is_enabled();

rule_size = sizeof(struct landlock_ruleset_attr);

#ifdef HAVE_STRUCT_LANDLOCK_RULESET_ATTR_HANDLED_ACCESS_NET
rule_small_size = rule_size - sizeof(uint64_t) - 1;
#else
rule_small_size = rule_size - 1;
#endif

rule_big_size = SAFE_SYSCONF(_SC_PAGESIZE) + 1;
}

static struct tst_test test = {
.test = run,
.tcnt = ARRAY_SIZE(tcases),
.setup = setup,
.min_kver = "5.13",
.needs_root = 1,
.needs_kconfigs = (const char *[]) {
"CONFIG_SECURITY_LANDLOCK=y",
NULL
},
.bufs = (struct tst_buffers []) {
{&ruleset_attr, .size = sizeof(struct landlock_ruleset_attr)},
{},
},
.caps = (struct tst_cap []) {
TST_CAP(TST_CAP_REQ, CAP_SYS_ADMIN),
{}
},
};
74 changes: 74 additions & 0 deletions testcases/kernel/syscalls/landlock/landlock_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/

#ifndef LANDLOCK_COMMON_H

#include "tst_test.h"
#include "lapi/prctl.h"
#include "lapi/fcntl.h"
#include "lapi/landlock.h"

static inline void verify_landlock_is_enabled(void)
{
int abi;

abi = tst_syscall(__NR_landlock_create_ruleset,
NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);

if (abi < 0) {
if (errno == EOPNOTSUPP) {
tst_brk(TCONF, "Landlock is currently disabled. "
"Please enable it either via CONFIG_LSM or "
"'lsm' kernel parameter.");
}

tst_brk(TBROK | TERRNO, "landlock_create_ruleset error");
}

tst_res(TINFO, "Landlock ABI v%d", abi);
}

static inline void apply_landlock_rule(
struct landlock_path_beneath_attr *path_beneath_attr,
const int ruleset_fd,
const int access,
const char *path)
{
path_beneath_attr->allowed_access = access;
path_beneath_attr->parent_fd = SAFE_OPEN(path, O_PATH | O_CLOEXEC);

SAFE_LANDLOCK_ADD_RULE(
ruleset_fd,
LANDLOCK_RULE_PATH_BENEATH,
path_beneath_attr,
0);

SAFE_CLOSE(path_beneath_attr->parent_fd);
}

static inline void enforce_ruleset(const int ruleset_fd)
{
SAFE_PRCTL(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
SAFE_LANDLOCK_RESTRICT_SELF(ruleset_fd, 0);
}

static inline void apply_landlock_layer(
struct landlock_ruleset_attr *ruleset_attr,
struct landlock_path_beneath_attr *path_beneath_attr,
const char *path,
const int access)
{
int ruleset_fd;

ruleset_fd = SAFE_LANDLOCK_CREATE_RULESET(
ruleset_attr, sizeof(struct landlock_ruleset_attr), 0);

apply_landlock_rule(path_beneath_attr, ruleset_fd, access, path);
enforce_ruleset(ruleset_fd);

SAFE_CLOSE(ruleset_fd);
}

#endif

0 comments on commit 4e17e90

Please sign in to comment.