Landlock: userland documentation¶
Landlock programs¶
eBPF programs are used to create security programs. They are contained and can call only a whitelist of dedicated functions. Moreover, they can only loop under strict conditions, which protects from denial of service. More information on BPF can be found in Documentation/networking/filter.txt.
Writing a program¶
To enforce a security policy, a thread first needs to create a Landlock program. The easiest way to write an eBPF program depicting a security program is to write it in the C language. As described in samples/bpf/README.rst, LLVM can compile such programs. Files samples/bpf/landlock1_kern.c and those in tools/testing/selftests/landlock/ can be used as examples.
Once the eBPF program is created, the next step is to create the metadata describing the Landlock program. This metadata includes an expected attach type which contains the hook type to which the program is tied, and expected attach triggers which identify the actions for which the program should be run.
A hook is a policy decision point which exposes the same context type for each program evaluation.
A Landlock hook describes the kind of kernel object for which a program will be triggered to allow or deny an action. For example, the hook BPF_LANDLOCK_FS_PICK can be triggered every time a landlocked thread performs a set of action related to the filesystem (e.g. open, read, write, mount…). This actions are identified by the triggers bitfield.
The next step is to fill a struct bpf_load_program_attr
with BPF_PROG_TYPE_LANDLOCK_HOOK, the expected attach
type and other BPF program metadata. This bpf_attr must then be passed to the
bpf(2) syscall alongside the BPF_PROG_LOAD command. If everything
is deemed correct by the kernel, the thread gets a file descriptor referring to
this program.
In the following code, the insn variable is an array of BPF instructions which can be extracted from an ELF file as is done in bpf_load_file() from samples/bpf/bpf_load.c.
int prog_fd;
struct bpf_load_program_attr load_attr;
memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
load_attr.prog_type = BPF_PROG_TYPE_LANDLOCK_HOOK;
load_attr.expected_attach_type = BPF_LANDLOCK_FS_PICK;
load_attr.expected_attach_triggers = LANDLOCK_TRIGGER_FS_PICK_OPEN;
load_attr.insns = insns;
load_attr.insns_cnt = sizeof(insn) / sizeof(struct bpf_insn);
load_attr.license = "GPL";
prog_fd = bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
if (prog_fd == -1)
exit(1);
Enforcing a program¶
Once the Landlock program has been created or received (e.g. through a UNIX socket), the thread willing to sandbox itself (and its future children) should perform the following two steps.
The thread should first request to never be allowed to get new privileges with a call to prctl(2) and the PR_SET_NO_NEW_PRIVS option. More information can be found in Documentation/prctl/no_new_privs.txt.
if (prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0))
exit(1);
A thread can apply a program to itself by using the seccomp(2) syscall. The operation is SECCOMP_PREPEND_LANDLOCK_PROG, the flags must be empty and the args argument must point to a valid Landlock program file descriptor.
if (seccomp(SECCOMP_PREPEND_LANDLOCK_PROG, 0, &fd))
exit(1);
If the syscall succeeds, the program is now enforced on the calling thread and will be enforced on all its subsequently created children of the thread as well. Once a thread is landlocked, there is no way to remove this security policy, only stacking more restrictions is allowed. The program evaluation is performed from the newest to the oldest.
When a syscall ask for an action on a kernel object, if this action is denied, then an EACCES errno code is returned through the syscall.
Inherited programs¶
Every new thread resulting from a clone(2) inherits Landlock program restrictions from its parent. This is similar to the seccomp inheritance as described in Documentation/prctl/seccomp_filter.txt.
Ptrace restrictions¶
A landlocked process has less privileges than a non-landlocked process and must then be subject to additional restrictions when manipulating another process. To be allowed to use ptrace(2) and related syscalls on a target process, a landlocked process must have a subset of the target process programs.
Landlock structures and constants¶
Hook types¶
Contexts¶
-
struct
landlock_ctx_fs_pick
¶ context accessible to a fs_pick program
Definition
struct landlock_ctx_fs_pick {
__u64 inode;
};
Members
inode
- pointer to the current kernel object that can be used to compare inodes from an inode map.
-
struct
landlock_ctx_fs_walk
¶ context accessible to a fs_walk program
Definition
struct landlock_ctx_fs_walk {
__u64 inode;
};
Members
inode
- pointer to the current kernel object that can be used to compare inodes from an inode map.
Triggers for fs_pick¶
A landlock trigger is used as a bitmask in subtype.landlock_hook.triggers for a fs_pick program. It defines a set of actions for which the program should verify an access request.
LANDLOCK_TRIGGER_FS_PICK_APPEND
LANDLOCK_TRIGGER_FS_PICK_CHDIR
LANDLOCK_TRIGGER_FS_PICK_CHROOT
LANDLOCK_TRIGGER_FS_PICK_CREATE
LANDLOCK_TRIGGER_FS_PICK_EXECUTE
LANDLOCK_TRIGGER_FS_PICK_FCNTL
LANDLOCK_TRIGGER_FS_PICK_GETATTR
LANDLOCK_TRIGGER_FS_PICK_IOCTL
LANDLOCK_TRIGGER_FS_PICK_LINK
LANDLOCK_TRIGGER_FS_PICK_LINKTO
LANDLOCK_TRIGGER_FS_PICK_LOCK
LANDLOCK_TRIGGER_FS_PICK_MAP
LANDLOCK_TRIGGER_FS_PICK_MOUNTON
LANDLOCK_TRIGGER_FS_PICK_OPEN
LANDLOCK_TRIGGER_FS_PICK_READ
LANDLOCK_TRIGGER_FS_PICK_READDIR
LANDLOCK_TRIGGER_FS_PICK_RECEIVE
LANDLOCK_TRIGGER_FS_PICK_RENAME
LANDLOCK_TRIGGER_FS_PICK_RENAMETO
LANDLOCK_TRIGGER_FS_PICK_RMDIR
LANDLOCK_TRIGGER_FS_PICK_SETATTR
LANDLOCK_TRIGGER_FS_PICK_TRANSFER
LANDLOCK_TRIGGER_FS_PICK_UNLINK
LANDLOCK_TRIGGER_FS_PICK_WRITE