diff options
author | Eugene Syromyatnikov <evgsyr@gmail.com> | 2021-07-03 00:55:02 +0200 |
---|---|---|
committer | Dmitry V. Levin <ldv@strace.io> | 2021-07-16 18:57:21 +0000 |
commit | 7592a0eeab2588162c1741077053f8a052c8418f (patch) | |
tree | 630269c633e97514ecc09e0f5f87f7ed5fd9ff5c | |
parent | f001287e0c4b30adf2cfaaecab43908d5dee2b68 (diff) | |
download | strace-7592a0eeab2588162c1741077053f8a052c8418f.tar.gz |
Implement landlock_{add_rule,create_ruleset,restrict_self} syscall decoding
Introduced by Linux commit v5.13-rc1~71^2~4.
* bundled/linux/include/uapi/linux/landlock.h: New file, copied from
headers_install'ed Linux kernel v5.13.
* bundled/Makefile.am (EXTRA_DIST): Add it.
* src/Makefile.am (libstrace_a_SOURCES): Add landlock.c.
* src/landlock.c: New file.
* src/linux/generic/syscallent-common.h([BASE_NR + 444], [BASE_NR + 445],
[BASE_NR + 446]): New entries, for landlock_create_ruleset, landlock_add_rule,
and landlock_restrict_self, respectively.
* src/pathtrace.c (pathtrace_match_set): Handle SEN_landlock_add_rule,
SEN_landlock_create_ruleset, and SEN_landlock_restrict_self.
* src/xlat/landlock_create_ruleset_flags.in: New xlat.
* src/xlat/landlock_rule_types.in: Likewise.
* src/xlat/landlock_ruleset_access_fs.in: Likewise.
* tests/Makefile.am (check_PROGRAMS): Add
landlock_create_ruleset-success and landlock_create_ruleset-success-y.
(DECODER_TESTS): Add landlock_create_ruleset-success.test.
* tests/gen_tests.in (landlock_add_rule, landlock_add_rule-y,
landlock_create_ruleset, landlock_create_ruleset-success-y,
landlock_create_ruleset-y, landlock_restrict_self,
landlock_restrict_self-y): New tests.
* tests/landlock_add_rule.c: New file.
* tests/landlock_add_rule-y.c: Likewise.
* tests/landlock_create_ruleset-success.c: Likewise.
* tests/landlock_create_ruleset-success-y.c: Likewise.
* tests/landlock_create_ruleset.c: Likewise.
* tests/landlock_create_ruleset-y.c: Likewise.
* tests/landlock_restrict_self.c: Likewise.
* tests/landlock_restrict_self-y.c: Likewise.
* tests/landlock_create_ruleset-success.test: New test.
* tests/pure_executables.list: Add landlock_add_rule,
landlock_add_rule-y, landlock_create_ruleset, landlock_create_ruleset-y,
landlock_restrict_self, and landlock_restrict_self-y.
* tests/.gitignore: Add landlock_add_rule, landlock_add_rule-y,
landlock_create_ruleset, landlock_create_ruleset-success,
landlock_create_ruleset-success-y, landlock_create_ruleset-y,
landlock_restrict_self, and landlock_restrict_self-y.
* NEWS: Mention it.
Co-authored-by: Dmitry V. Levin <ldv@strace.io>
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | bundled/Makefile.am | 1 | ||||
-rw-r--r-- | bundled/linux/include/uapi/linux/landlock.h | 137 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/landlock.c | 124 | ||||
-rw-r--r-- | src/linux/generic/syscallent-common.h | 4 | ||||
-rw-r--r-- | src/pathtrace.c | 3 | ||||
-rw-r--r-- | src/xlat/landlock_create_ruleset_flags.in | 2 | ||||
-rw-r--r-- | src/xlat/landlock_rule_types.in | 3 | ||||
-rw-r--r-- | src/xlat/landlock_ruleset_access_fs.in | 14 | ||||
-rw-r--r-- | tests/.gitignore | 8 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/gen_tests.in | 7 | ||||
-rw-r--r-- | tests/landlock_add_rule-y.c | 7 | ||||
-rw-r--r-- | tests/landlock_add_rule.c | 132 | ||||
-rw-r--r-- | tests/landlock_create_ruleset-success-y.c | 4 | ||||
-rw-r--r-- | tests/landlock_create_ruleset-success.c | 2 | ||||
-rwxr-xr-x | tests/landlock_create_ruleset-success.test | 13 | ||||
-rw-r--r-- | tests/landlock_create_ruleset-y.c | 4 | ||||
-rw-r--r-- | tests/landlock_create_ruleset.c | 140 | ||||
-rw-r--r-- | tests/landlock_restrict_self-y.c | 4 | ||||
-rw-r--r-- | tests/landlock_restrict_self.c | 83 | ||||
-rwxr-xr-x | tests/pure_executables.list | 6 |
23 files changed, 704 insertions, 0 deletions
@@ -9,6 +9,8 @@ Noteworthy changes in release ?.?? (????-??-??) PTRACE_SETREGS, PTRACE_SETREGS64, PTRACE_GETFPREGS, and PTRACE_SETFPREGS requests. * Implemented powerpc System Call Vectored ABI support. + * Implemented decoding of landlock_add_rule, landlock_create_ruleset, + and landlock_restrict_self syscalls introduced in Linux 5.13. * Enhanced decoding of perf_event_open syscall. * Updated lists of BPF_*, IORING_*, KEXEC_*, KEY_*, KVM_*, NT_*, PR_*, PTRACE_*, RTM_*, RTPROT_*, TRAP_*, UFFD_*, UFFDIO_*, and V4L2_* constants. diff --git a/bundled/Makefile.am b/bundled/Makefile.am index f0fd8711b..fcb712081 100644 --- a/bundled/Makefile.am +++ b/bundled/Makefile.am @@ -54,6 +54,7 @@ EXTRA_DIST = \ linux/include/uapi/linux/kcmp.h \ linux/include/uapi/linux/kexec.h \ linux/include/uapi/linux/keyctl.h \ + linux/include/uapi/linux/landlock.h \ linux/include/uapi/linux/libc-compat.h \ linux/include/uapi/linux/loop.h \ linux/include/uapi/linux/memfd.h \ diff --git a/bundled/linux/include/uapi/linux/landlock.h b/bundled/linux/include/uapi/linux/landlock.h new file mode 100644 index 000000000..bebb42928 --- /dev/null +++ b/bundled/linux/include/uapi/linux/landlock.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Landlock - User space API + * + * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net> + * Copyright © 2018-2020 ANSSI + */ + +#ifndef _LINUX_LANDLOCK_H +#define _LINUX_LANDLOCK_H + +#include <linux/types.h> + +/** + * struct landlock_ruleset_attr - Ruleset definition + * + * Argument of sys_landlock_create_ruleset(). This structure can grow in + * future versions. + */ +struct landlock_ruleset_attr { + /** + * @handled_access_fs: Bitmask of actions (cf. `Filesystem flags`_) + * that is handled by this ruleset and should then be forbidden if no + * rule explicitly allow them. This is needed for backward + * compatibility reasons. + */ + __u64 handled_access_fs; +}; + +/* + * sys_landlock_create_ruleset() flags: + * + * - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI + * version. + */ +#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0) + +/** + * enum landlock_rule_type - Landlock rule type + * + * Argument of sys_landlock_add_rule(). + */ +enum landlock_rule_type { + /** + * @LANDLOCK_RULE_PATH_BENEATH: Type of a &struct + * landlock_path_beneath_attr . + */ + LANDLOCK_RULE_PATH_BENEATH = 1, +}; + +/** + * struct landlock_path_beneath_attr - Path hierarchy definition + * + * Argument of sys_landlock_add_rule(). + */ +struct landlock_path_beneath_attr { + /** + * @allowed_access: Bitmask of allowed actions for this file hierarchy + * (cf. `Filesystem flags`_). + */ + __u64 allowed_access; + /** + * @parent_fd: File descriptor, open with ``O_PATH``, which identifies + * the parent directory of a file hierarchy, or just a file. + */ + __s32 parent_fd; + /* + * This struct is packed to avoid trailing reserved members. + * Cf. security/landlock/syscalls.c:build_check_abi() + */ +} __attribute__((packed)); + +/** + * DOC: fs_access + * + * A set of actions on kernel objects may be defined by an attribute (e.g. + * &struct landlock_path_beneath_attr) including a bitmask of access. + * + * Filesystem flags + * ~~~~~~~~~~~~~~~~ + * + * These flags enable to restrict a sandboxed process to a set of actions on + * files and directories. Files or directories opened before the sandboxing + * are not subject to these restrictions. + * + * A file can only receive these access rights: + * + * - %LANDLOCK_ACCESS_FS_EXECUTE: Execute a file. + * - %LANDLOCK_ACCESS_FS_WRITE_FILE: Open a file with write access. + * - %LANDLOCK_ACCESS_FS_READ_FILE: Open a file with read access. + * + * A directory can receive access rights related to files or directories. The + * following access right is applied to the directory itself, and the + * directories beneath it: + * + * - %LANDLOCK_ACCESS_FS_READ_DIR: Open a directory or list its content. + * + * However, the following access rights only apply to the content of a + * directory, not the directory itself: + * + * - %LANDLOCK_ACCESS_FS_REMOVE_DIR: Remove an empty directory or rename one. + * - %LANDLOCK_ACCESS_FS_REMOVE_FILE: Unlink (or rename) a file. + * - %LANDLOCK_ACCESS_FS_MAKE_CHAR: Create (or rename or link) a character + * device. + * - %LANDLOCK_ACCESS_FS_MAKE_DIR: Create (or rename) a directory. + * - %LANDLOCK_ACCESS_FS_MAKE_REG: Create (or rename or link) a regular file. + * - %LANDLOCK_ACCESS_FS_MAKE_SOCK: Create (or rename or link) a UNIX domain + * socket. + * - %LANDLOCK_ACCESS_FS_MAKE_FIFO: Create (or rename or link) a named pipe. + * - %LANDLOCK_ACCESS_FS_MAKE_BLOCK: Create (or rename or link) a block device. + * - %LANDLOCK_ACCESS_FS_MAKE_SYM: Create (or rename or link) a symbolic link. + * + * .. warning:: + * + * It is currently not possible to restrict some file-related actions + * accessible through these syscall families: :manpage:`chdir(2)`, + * :manpage:`truncate(2)`, :manpage:`stat(2)`, :manpage:`flock(2)`, + * :manpage:`chmod(2)`, :manpage:`chown(2)`, :manpage:`setxattr(2)`, + * :manpage:`utime(2)`, :manpage:`ioctl(2)`, :manpage:`fcntl(2)`, + * :manpage:`access(2)`. + * Future Landlock evolutions will enable to restrict them. + */ +#define LANDLOCK_ACCESS_FS_EXECUTE (1ULL << 0) +#define LANDLOCK_ACCESS_FS_WRITE_FILE (1ULL << 1) +#define LANDLOCK_ACCESS_FS_READ_FILE (1ULL << 2) +#define LANDLOCK_ACCESS_FS_READ_DIR (1ULL << 3) +#define LANDLOCK_ACCESS_FS_REMOVE_DIR (1ULL << 4) +#define LANDLOCK_ACCESS_FS_REMOVE_FILE (1ULL << 5) +#define LANDLOCK_ACCESS_FS_MAKE_CHAR (1ULL << 6) +#define LANDLOCK_ACCESS_FS_MAKE_DIR (1ULL << 7) +#define LANDLOCK_ACCESS_FS_MAKE_REG (1ULL << 8) +#define LANDLOCK_ACCESS_FS_MAKE_SOCK (1ULL << 9) +#define LANDLOCK_ACCESS_FS_MAKE_FIFO (1ULL << 10) +#define LANDLOCK_ACCESS_FS_MAKE_BLOCK (1ULL << 11) +#define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12) + +#endif /* _LINUX_LANDLOCK_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 02fa00a6d..4699aae5f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -168,6 +168,7 @@ libstrace_a_SOURCES = \ keyctl_kdf_params.h \ kill_save_errno.h \ kvm.c \ + landlock.c \ largefile_wrappers.h \ ldt.c \ link.c \ diff --git a/src/landlock.c b/src/landlock.c new file mode 100644 index 000000000..561b603fb --- /dev/null +++ b/src/landlock.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include <linux/landlock.h> + +#include "xlat/landlock_create_ruleset_flags.h" +#include "xlat/landlock_rule_types.h" +#include "xlat/landlock_ruleset_access_fs.h" + +static void +print_landlock_ruleset_attr(struct tcb *tcp, const kernel_ulong_t addr, + const kernel_ulong_t size) +{ + struct { + uint64_t handled_access_fs; + } attr; + + if (size < offsetofend(typeof(attr), handled_access_fs)) { + printaddr(addr); + return; + } + + if (umoven_or_printaddr(tcp, addr, MIN(size, sizeof(attr)), &attr)) + return; + + tprint_struct_begin(); + PRINT_FIELD_FLAGS(attr, handled_access_fs, landlock_ruleset_access_fs, + "LANDLOCK_ACCESS_FS_???"); + + if (size > offsetofend(typeof(attr), handled_access_fs)) { + tprint_arg_next(); + tprint_more_data_follows(); + } + + tprint_struct_end(); +} + +SYS_FUNC(landlock_create_ruleset) +{ + kernel_ulong_t attr = tcp->u_arg[0]; + kernel_ulong_t size = tcp->u_arg[1]; + unsigned int flags = tcp->u_arg[2]; + int fd_flag = flags & LANDLOCK_CREATE_RULESET_VERSION ? 0 : RVAL_FD; + + /* attr */ + print_landlock_ruleset_attr(tcp, attr, size); + tprint_arg_next(); + + /* size */ + PRINT_VAL_U(size); + tprint_arg_next(); + + /* flags */ + printflags(landlock_create_ruleset_flags, flags, + "LANDLOCK_CREATE_RULESET_???"); + + return RVAL_DECODED | fd_flag; +} + +static void +print_landlock_path_beneath_attr(struct tcb *tcp, const kernel_ulong_t addr) +{ + struct { + uint64_t allowed_access; + int32_t parent_fd; + } ATTRIBUTE_PACKED attr; + + if (umove_or_printaddr(tcp, addr, &attr)) + return; + + tprint_struct_begin(); + PRINT_FIELD_FLAGS(attr, allowed_access, landlock_ruleset_access_fs, + "LANDLOCK_ACCESS_FS_???"); + tprint_struct_next(); + PRINT_FIELD_FD(attr, parent_fd, tcp); + tprint_struct_end(); +} + +SYS_FUNC(landlock_add_rule) +{ + unsigned int rule_type = tcp->u_arg[1]; + + /* ruleset_fd */ + printfd(tcp, tcp->u_arg[0]); + tprint_arg_next(); + + /* rule_type */ + printxval(landlock_rule_types, rule_type, "LANDLOCK_RULE_???"); + tprint_arg_next(); + + /* rule_attr */ + switch (rule_type) { + case LANDLOCK_RULE_PATH_BENEATH: + print_landlock_path_beneath_attr(tcp, tcp->u_arg[2]); + break; + + default: + printaddr(tcp->u_arg[2]); + } + tprint_arg_next(); + + /* flags */ + PRINT_VAL_X((unsigned int) tcp->u_arg[3]); + + return RVAL_DECODED; +} + +SYS_FUNC(landlock_restrict_self) +{ + /* ruleset_fd */ + printfd(tcp, tcp->u_arg[0]); + tprint_arg_next(); + + /* flags */ + PRINT_VAL_X((unsigned int) tcp->u_arg[1]); + + return RVAL_DECODED; +} diff --git a/src/linux/generic/syscallent-common.h b/src/linux/generic/syscallent-common.h index 0cc3cf973..b46d418cb 100644 --- a/src/linux/generic/syscallent-common.h +++ b/src/linux/generic/syscallent-common.h @@ -27,3 +27,7 @@ [BASE_NR + 440] = { 5, TD, SEN(process_madvise), "process_madvise" }, [BASE_NR + 441] = { 6, TD, SEN(epoll_pwait2), "epoll_pwait2" }, [BASE_NR + 442] = { 5, TD|TF, SEN(mount_setattr), "mount_setattr" }, +/* 443 is reserved for quotactl_fd */ +[BASE_NR + 444] = { 3, TD, SEN(landlock_create_ruleset), "landlock_create_ruleset" }, +[BASE_NR + 445] = { 4, TD, SEN(landlock_add_rule), "landlock_add_rule" }, +[BASE_NR + 446] = { 2, TD, SEN(landlock_restrict_self), "landlock_restrict_self" }, diff --git a/src/pathtrace.c b/src/pathtrace.c index 2c24ced8b..7f98dcbdb 100644 --- a/src/pathtrace.c +++ b/src/pathtrace.c @@ -372,6 +372,9 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) case SEN_io_uring_enter: case SEN_io_uring_register: case SEN_io_uring_setup: + case SEN_landlock_add_rule: + case SEN_landlock_create_ruleset: + case SEN_landlock_restrict_self: case SEN_memfd_create: case SEN_mq_getsetattr: case SEN_mq_notify: diff --git a/src/xlat/landlock_create_ruleset_flags.in b/src/xlat/landlock_create_ruleset_flags.in new file mode 100644 index 000000000..2e7053c9a --- /dev/null +++ b/src/xlat/landlock_create_ruleset_flags.in @@ -0,0 +1,2 @@ +#unconditional +LANDLOCK_CREATE_RULESET_VERSION diff --git a/src/xlat/landlock_rule_types.in b/src/xlat/landlock_rule_types.in new file mode 100644 index 000000000..eaccb6de3 --- /dev/null +++ b/src/xlat/landlock_rule_types.in @@ -0,0 +1,3 @@ +#unconditional +#value_indexed +LANDLOCK_RULE_PATH_BENEATH diff --git a/src/xlat/landlock_ruleset_access_fs.in b/src/xlat/landlock_ruleset_access_fs.in new file mode 100644 index 000000000..c0251f416 --- /dev/null +++ b/src/xlat/landlock_ruleset_access_fs.in @@ -0,0 +1,14 @@ +#unconditional +LANDLOCK_ACCESS_FS_EXECUTE +LANDLOCK_ACCESS_FS_WRITE_FILE +LANDLOCK_ACCESS_FS_READ_FILE +LANDLOCK_ACCESS_FS_READ_DIR +LANDLOCK_ACCESS_FS_REMOVE_DIR +LANDLOCK_ACCESS_FS_REMOVE_FILE +LANDLOCK_ACCESS_FS_MAKE_CHAR +LANDLOCK_ACCESS_FS_MAKE_DIR +LANDLOCK_ACCESS_FS_MAKE_REG +LANDLOCK_ACCESS_FS_MAKE_SOCK +LANDLOCK_ACCESS_FS_MAKE_FIFO +LANDLOCK_ACCESS_FS_MAKE_BLOCK +LANDLOCK_ACCESS_FS_MAKE_SYM diff --git a/tests/.gitignore b/tests/.gitignore index 8f2472b64..047b2d930 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -383,6 +383,14 @@ kill--pidns-translation kill_child ksysent ksysent.h +landlock_add_rule +landlock_add_rule-y +landlock_create_ruleset +landlock_create_ruleset-success +landlock_create_ruleset-success-y +landlock_create_ruleset-y +landlock_restrict_self +landlock_restrict_self-y lchown lchown32 libtests.a diff --git a/tests/Makefile.am b/tests/Makefile.am index 126e84361..5493f6223 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -205,6 +205,8 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ kill--pidns-translation \ kill_child \ ksysent \ + landlock_create_ruleset-success \ + landlock_create_ruleset-success-y \ list_sigaction_signum \ localtime \ looping_threads \ @@ -401,6 +403,7 @@ DECODER_TESTS = \ ioctl_evdev-success.test \ ipc_msgbuf.test \ kern_features-fault.test \ + landlock_create_ruleset-success.test \ llseek.test \ lseek.test \ mmap.test \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 747383368..017d33c70 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -370,6 +370,13 @@ keyctl-Xverbose -a41 -s10 -e trace=keyctl -Xverbose kill -a12 -esignal=none kill--pidns-translation test_pidns -a12 -e trace=kill -esignal=none ksysent ../$NAME +landlock_add_rule -a57 +landlock_add_rule-y -a57 -y -e trace=landlock_add_rule </dev/null 7>/dev/zero 8>/dev/full +landlock_create_ruleset -a36 +landlock_create_ruleset-success-y +landlock_create_ruleset-success.test -y +landlock_create_ruleset-y -a36 -y -e trace=landlock_create_ruleset +landlock_restrict_self -a29 +landlock_restrict_self-y -a29 -y -e trace=landlock_restrict_self 7>/dev/full lchown -a30 lchown32 -a32 link diff --git a/tests/landlock_add_rule-y.c b/tests/landlock_add_rule-y.c new file mode 100644 index 000000000..3f4f671f6 --- /dev/null +++ b/tests/landlock_add_rule-y.c @@ -0,0 +1,7 @@ +#define FD0_STR "</dev/null>" +#define RULESET_FD 7 +#define RULESET_FD_STR "7</dev/zero>" +#define PARENT_FD 8 +#define PARENT_FD_STR "8</dev/full>" + +#include "landlock_add_rule.c" diff --git a/tests/landlock_add_rule.c b/tests/landlock_add_rule.c new file mode 100644 index 000000000..d788929d8 --- /dev/null +++ b/tests/landlock_add_rule.c @@ -0,0 +1,132 @@ +/* + * Check decoding of landlock_add_rule syscall. + * + * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" + +#include <inttypes.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> + +#include <linux/landlock.h> + +#ifndef SKIP_IF_PROC_IS_UNAVAILABLE +# define SKIP_IF_PROC_IS_UNAVAILABLE +#endif + +#ifndef FD0_STR +# define FD0_STR "" +#endif +#ifndef RULESET_FD +# define RULESET_FD -1 +#endif +#ifndef RULESET_FD_STR +# define RULESET_FD_STR "-1" +#endif +#ifndef PARENT_FD +# define PARENT_FD -1 +#endif +#ifndef PARENT_FD_STR +# define PARENT_FD_STR "-1" +#endif + +static const char *errstr; + +static long +sys_landlock_add_rule(int ruleset_fd, unsigned int rule_type, void *rule_attr, + unsigned int flags) +{ + static const kernel_ulong_t fill = + (kernel_ulong_t) 0xd1efaced00000000ULL; + kernel_ulong_t arg1 = fill | (unsigned int) ruleset_fd; + kernel_ulong_t arg2 = fill | rule_type; + kernel_ulong_t arg3 = (uintptr_t) rule_attr; + kernel_ulong_t arg4 = fill | flags; + kernel_ulong_t arg5 = fill | 0xdecaffed; + kernel_ulong_t arg6 = fill | 0xdeefaced; + + long rc = syscall(__NR_landlock_add_rule, + arg1, arg2, arg3, arg4, arg5, arg6); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + SKIP_IF_PROC_IS_UNAVAILABLE; + + TAIL_ALLOC_OBJECT_VAR_PTR(struct landlock_path_beneath_attr, attr); + + /* All zeroes */ + sys_landlock_add_rule(0, 0, NULL, 0); + printf("landlock_add_rule(0" FD0_STR ", 0 /* LANDLOCK_RULE_??? */" + ", NULL, 0) = %s\n", errstr); + + /* Bogus values */ + sys_landlock_add_rule(0xdeadc0de, 0xfacebeef, attr + 1, 1); + printf("landlock_add_rule(-559038242" + ", 0xfacebeef /* LANDLOCK_RULE_??? */, %p, 0x1) = %s\n", + attr + 1, errstr); + + sys_landlock_add_rule(1729, 2, attr + 1, 0xffffffff); + printf("landlock_add_rule(1729, 0x2 /* LANDLOCK_RULE_??? */, %p" + ", 0xffffffff) = %s\n", + attr + 1, errstr); + + /* Invalid pointer */ + sys_landlock_add_rule(RULESET_FD, LANDLOCK_RULE_PATH_BENEATH, + attr + 1, 0); + printf("landlock_add_rule(" RULESET_FD_STR + ", LANDLOCK_RULE_PATH_BENEATH, %p, 0) = %s\n", + attr + 1, errstr); + + /* Short read */ + sys_landlock_add_rule(RULESET_FD, LANDLOCK_RULE_PATH_BENEATH, + (char *) attr + 4, 0); + printf("landlock_add_rule(" RULESET_FD_STR + ", LANDLOCK_RULE_PATH_BENEATH, %p, 0) = %s\n", + (char *) attr + 4, errstr); + + /* Valid attr ptr */ + static const struct { + uint64_t val; + const char *str; + } attr_vals[] = { + { ARG_STR(LANDLOCK_ACCESS_FS_EXECUTE) }, + { ARG_ULL_STR(LANDLOCK_ACCESS_FS_EXECUTE|LANDLOCK_ACCESS_FS_READ_FILE|LANDLOCK_ACCESS_FS_READ_DIR|LANDLOCK_ACCESS_FS_REMOVE_FILE|LANDLOCK_ACCESS_FS_MAKE_CHAR|LANDLOCK_ACCESS_FS_MAKE_DIR|LANDLOCK_ACCESS_FS_MAKE_SOCK|LANDLOCK_ACCESS_FS_MAKE_FIFO|LANDLOCK_ACCESS_FS_MAKE_BLOCK|LANDLOCK_ACCESS_FS_MAKE_SYM|0xdebeefeddecae000) }, + { ARG_ULL_STR(0xdebeefeddecae000) + " /* LANDLOCK_ACCESS_FS_??? */" }, + }; + static const struct { + int val; + const char *str; + } parent_fd_vals[] = { + { ARG_STR(-1) }, + { ARG_STR(11630) }, + { PARENT_FD, PARENT_FD_STR }, + }; + for (size_t i = 0; i < ARRAY_SIZE(attr_vals); i++) { + for (size_t j = 0; j < ARRAY_SIZE(parent_fd_vals); j++) { + attr->allowed_access = attr_vals[i].val; + attr->parent_fd = parent_fd_vals[j].val; + sys_landlock_add_rule(RULESET_FD, + LANDLOCK_RULE_PATH_BENEATH, + attr, 0); + printf("landlock_add_rule(" RULESET_FD_STR + ", LANDLOCK_RULE_PATH_BENEATH" + ", {allowed_access=%s, parent_fd=%s}, 0) = %s\n", + attr_vals[i].str, parent_fd_vals[j].str, errstr); + } + } + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/landlock_create_ruleset-success-y.c b/tests/landlock_create_ruleset-success-y.c new file mode 100644 index 000000000..839155603 --- /dev/null +++ b/tests/landlock_create_ruleset-success-y.c @@ -0,0 +1,4 @@ +#define FD_PATH "</dev/null>" +#define SKIP_IF_PROC_IS_UNAVAILABLE skip_if_unavailable("/proc/self/fd/") + +#include "landlock_create_ruleset-success.c" diff --git a/tests/landlock_create_ruleset-success.c b/tests/landlock_create_ruleset-success.c new file mode 100644 index 000000000..d9c471ba8 --- /dev/null +++ b/tests/landlock_create_ruleset-success.c @@ -0,0 +1,2 @@ +#define RETVAL_INJECTED 1 +#include "landlock_create_ruleset.c" diff --git a/tests/landlock_create_ruleset-success.test b/tests/landlock_create_ruleset-success.test new file mode 100755 index 000000000..a2e541212 --- /dev/null +++ b/tests/landlock_create_ruleset-success.test @@ -0,0 +1,13 @@ +#!/bin/sh -efu +# +# Copyright (c) 2019-2021 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/scno_tampering.sh" + +run_strace -a10 "$@" -e trace=landlock_create_ruleset \ + -e inject=landlock_create_ruleset:retval=7 \ + "../$NAME" > "$EXP" 7> /dev/null +match_diff "$LOG" "$EXP" diff --git a/tests/landlock_create_ruleset-y.c b/tests/landlock_create_ruleset-y.c new file mode 100644 index 000000000..a30966b09 --- /dev/null +++ b/tests/landlock_create_ruleset-y.c @@ -0,0 +1,4 @@ +#define FD_PATH "<anon_inode:landlock-ruleset>" +#define SKIP_IF_PROC_IS_UNAVAILABLE skip_if_unavailable("/proc/self/fd/") + +#include "landlock_create_ruleset.c" diff --git a/tests/landlock_create_ruleset.c b/tests/landlock_create_ruleset.c new file mode 100644 index 000000000..bc1bcc2cf --- /dev/null +++ b/tests/landlock_create_ruleset.c @@ -0,0 +1,140 @@ +/* + * Check decoding of landlock_create_ruleset syscall. + * + * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" + +#include <inttypes.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> + +#include <linux/landlock.h> + +#ifndef RETVAL_INJECTED +# define RETVAL_INJECTED 0 +#endif + +#ifndef SKIP_IF_PROC_IS_UNAVAILABLE +# define SKIP_IF_PROC_IS_UNAVAILABLE +#endif +#ifndef FD_PATH +# define FD_PATH "" +#endif + +#if RETVAL_INJECTED +# define INJ_STR " (INJECTED)\n" +# define INJ_FD_STR FD_PATH " (INJECTED)\n" +#else /* !RETVAL_INJECTED */ +# define INJ_STR "\n" +# define INJ_FD_STR "\n" +#endif /* RETVAL_INJECTED */ + +static const char *errstr; + +static long +sys_landlock_create_ruleset(struct landlock_ruleset_attr *attr, + kernel_ulong_t size, unsigned int flags) + +{ + static const kernel_ulong_t fill = + (kernel_ulong_t) 0xd1efaced00000000ULL; + kernel_ulong_t arg1 = (uintptr_t) attr; + kernel_ulong_t arg2 = size; + kernel_ulong_t arg3 = fill | flags; + kernel_ulong_t arg4 = fill | 0xbadbeefd; + kernel_ulong_t arg5 = fill | 0xdecaffed; + kernel_ulong_t arg6 = fill | 0xdeefaced; + + long rc = syscall(__NR_landlock_create_ruleset, + arg1, arg2, arg3, arg4, arg5, arg6); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + static const kernel_ulong_t bogus_size = + (kernel_ulong_t) 0xbadfaceddecaffee; + + SKIP_IF_PROC_IS_UNAVAILABLE; + + TAIL_ALLOC_OBJECT_VAR_PTR(struct landlock_ruleset_attr, attr); + long rc; + + /* All zeroes */ + rc = sys_landlock_create_ruleset(NULL, 0, 0); + printf("landlock_create_ruleset(NULL, 0, 0) = %s" INJ_FD_STR, + errstr); + + /* Get ABI version */ + rc = sys_landlock_create_ruleset(NULL, 0, 1); + printf("landlock_create_ruleset(NULL, 0" + ", LANDLOCK_CREATE_RULESET_VERSION) = %s" INJ_STR, errstr); + + /* ilp32 check */ + rc = syscall(__NR_landlock_create_ruleset, + (kernel_ulong_t) 0xffFFffFF00000000, + (kernel_ulong_t) 0xdefeededdeadface, + (kernel_ulong_t) 0xbadc0dedbadfaced); + printf("landlock_create_ruleset(" +#if SIZEOF_KERNEL_LONG_T > 4 + "%#llx" +#else + "NULL" +#endif + ", %llu, LANDLOCK_CREATE_RULESET_VERSION|%#x) = %s" INJ_STR, +#if SIZEOF_KERNEL_LONG_T > 4 + (unsigned long long) (kernel_ulong_t) 0xffFFffFF00000000, +#endif + (unsigned long long) (kernel_ulong_t) 0xdefeededdeadface, + 0xbadfacec, sprintrc(rc)); + + /* Bogus addr, size, flags */ + rc = sys_landlock_create_ruleset(attr + 1, bogus_size, 0xbadcaffe); + printf("landlock_create_ruleset(%p, %llu" + ", 0xbadcaffe /* LANDLOCK_CREATE_RULESET_??? */) = %s" + INJ_FD_STR, + attr + 1, (unsigned long long) bogus_size, errstr); + + /* Size is too small */ + for (size_t i = 0; i < 8; i++) { + rc = sys_landlock_create_ruleset(attr, i, 0); + printf("landlock_create_ruleset(%p, %zu, 0) = %s" INJ_FD_STR, + attr, i, errstr); + } + + /* Perform syscalls with valid attr ptr */ + static const struct { + uint64_t val; + const char *str; + } attr_vals[] = { + { ARG_STR(LANDLOCK_ACCESS_FS_EXECUTE) }, + { ARG_ULL_STR(LANDLOCK_ACCESS_FS_EXECUTE|LANDLOCK_ACCESS_FS_READ_FILE|LANDLOCK_ACCESS_FS_READ_DIR|LANDLOCK_ACCESS_FS_REMOVE_FILE|LANDLOCK_ACCESS_FS_MAKE_CHAR|LANDLOCK_ACCESS_FS_MAKE_DIR|LANDLOCK_ACCESS_FS_MAKE_SOCK|LANDLOCK_ACCESS_FS_MAKE_FIFO|LANDLOCK_ACCESS_FS_MAKE_BLOCK|LANDLOCK_ACCESS_FS_MAKE_SYM|0xdebeefeddecae000) }, + { ARG_ULL_STR(0xdebeefeddecae000) + " /* LANDLOCK_ACCESS_FS_??? */" }, + }; + static const kernel_ulong_t sizes[] = { 8, 12, 16 }; + for (size_t i = 0; i < ARRAY_SIZE(attr_vals); i++) { + for (size_t j = 0; j < ARRAY_SIZE(sizes); j++) { + attr->handled_access_fs = attr_vals[i].val; + rc = sys_landlock_create_ruleset(attr, sizes[j], 0); + printf("landlock_create_ruleset({handled_access_fs=%s" + "%s}, %llu, 0) = %s%s" INJ_STR, + attr_vals[i].str, + sizes[j] > sizeof(*attr) ? ", ..." : "", + (unsigned long long) sizes[j], + errstr, rc > 0 ? FD_PATH : ""); + } + } + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/landlock_restrict_self-y.c b/tests/landlock_restrict_self-y.c new file mode 100644 index 000000000..f28dd18b1 --- /dev/null +++ b/tests/landlock_restrict_self-y.c @@ -0,0 +1,4 @@ +#define RULESET_FD 7 +#define RULESET_FD_STR "7</dev/full>" + +#include "landlock_restrict_self.c" diff --git a/tests/landlock_restrict_self.c b/tests/landlock_restrict_self.c new file mode 100644 index 000000000..b4378eee5 --- /dev/null +++ b/tests/landlock_restrict_self.c @@ -0,0 +1,83 @@ +/* + * Check decoding of landlock_restrict_self syscall. + * + * Copyright (c) 2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "scno.h" + +#include <inttypes.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> + +#ifndef SKIP_IF_PROC_IS_UNAVAILABLE +# define SKIP_IF_PROC_IS_UNAVAILABLE +#endif + +#ifndef RULESET_FD +# define RULESET_FD 7 +#endif +#ifndef RULESET_FD_STR +# define RULESET_FD_STR "7" +#endif + +static const char *errstr; + +static long +sys_landlock_restrict_self(int ruleset_fd, unsigned int flags) +{ + static const kernel_ulong_t fill = + (kernel_ulong_t) 0xd1efaced00000000ULL; + kernel_ulong_t arg1 = fill | (unsigned int) ruleset_fd; + kernel_ulong_t arg2 = fill | flags; + kernel_ulong_t arg3 = fill | 0xcaffeedc; + kernel_ulong_t arg4 = fill | 0xbadceded; + kernel_ulong_t arg5 = fill | 0xdecaffed; + kernel_ulong_t arg6 = fill | 0xdeefaced; + + long rc = syscall(__NR_landlock_restrict_self, + arg1, arg2, arg3, arg4, arg5, arg6); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + SKIP_IF_PROC_IS_UNAVAILABLE; + + /* Valid attr ptr */ + static const struct { + uint64_t val; + const char *str; + } ruleset_fd_vals[] = { + { ARG_STR(-1) }, + { ARG_STR(9409) }, + { RULESET_FD, RULESET_FD_STR }, + }; + static const struct { + int val; + const char *str; + } flags_vals[] = { + { ARG_STR(0) }, + { ARG_STR(0x1) }, + { ARG_STR(0xffffffff) }, + }; + for (size_t i = 0; i < ARRAY_SIZE(ruleset_fd_vals); i++) { + for (size_t j = 0; j < ARRAY_SIZE(flags_vals); j++) { + sys_landlock_restrict_self(ruleset_fd_vals[i].val, + flags_vals[j].val); + printf("landlock_restrict_self(%s, %s) = %s\n", + ruleset_fd_vals[i].str, flags_vals[j].str, + errstr); + } + } + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index c59e11783..9a8248567 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -267,6 +267,12 @@ keyctl-Xabbrev keyctl-Xraw keyctl-Xverbose kill +landlock_add_rule +landlock_add_rule-y +landlock_create_ruleset +landlock_create_ruleset-y +landlock_restrict_self +landlock_restrict_self-y lchown lchown32 link |