[RFC v2 10/10] samples/landlock: Add sandbox example
Add a basic sandbox tool to create a process isolated from some part of the system. This can depend of the current cgroup. Example: $ mkdir /sys/fs/cgroup/sandboxed $ ls /home user1 $ LANDLOCK_CGROUPS='/sys/fs/cgroup/sandboxed' \ LANDLOCK_ALLOWED='/bin:/lib:/usr:/tmp:/proc/self/fd/0' \ ./sandbox /bin/sh -i $ ls /home user1 $ echo $$ > /sys/fs/cgroup/sandboxed/cgroup.procs $ ls /home ls: cannot open directory '/home': Permission denied Signed-off-by: Mickaël SalaünCc: Kees Cook Cc: Alexei Starovoitov Cc: James Morris Cc: Serge E. Hallyn Cc: David S. Miller Cc: Daniel Borkmann --- samples/Makefile| 2 +- samples/landlock/.gitignore | 1 + samples/landlock/Makefile | 16 +++ samples/landlock/sandbox.c | 295 4 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 samples/landlock/.gitignore create mode 100644 samples/landlock/Makefile create mode 100644 samples/landlock/sandbox.c diff --git a/samples/Makefile b/samples/Makefile index 2e3b523d7097..42e6a613f728 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ - configfs/ connector/ v4l/ + configfs/ connector/ v4l/ landlock/ diff --git a/samples/landlock/.gitignore b/samples/landlock/.gitignore new file mode 100644 index ..f6c6da930a30 --- /dev/null +++ b/samples/landlock/.gitignore @@ -0,0 +1 @@ +/sandbox diff --git a/samples/landlock/Makefile b/samples/landlock/Makefile new file mode 100644 index ..d1044b2afd27 --- /dev/null +++ b/samples/landlock/Makefile @@ -0,0 +1,16 @@ +# kbuild trick to avoid linker error. Can be omitted if a module is built. +obj- := dummy.o + +hostprogs-$(CONFIG_SECURITY_LANDLOCK) := sandbox +sandbox-objs := sandbox.o + +always := $(hostprogs-y) + +HOSTCFLAGS += -I$(objtree)/usr/include + +# Trick to allow make to be run from this directory +all: + $(MAKE) -C ../../ $$PWD/ + +clean: + $(MAKE) -C ../../ M=$$PWD clean diff --git a/samples/landlock/sandbox.c b/samples/landlock/sandbox.c new file mode 100644 index ..86604963c30c --- /dev/null +++ b/samples/landlock/sandbox.c @@ -0,0 +1,295 @@ +/* + * Landlock LSM - Sandbox Example + * + * Copyright (C) 2016 Mickaël Salaün + * + * The code may be used by anyone for any purpose, and can serve as a starting + * point for developing a sandbox. + */ + +#define _GNU_SOURCE +#include +#include /* open() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../tools/include/linux/filter.h" + +#include "../bpf/libbpf.c" + +#ifndef seccomp +static int seccomp(unsigned int op, unsigned int flags, void *args) +{ + errno = 0; + return syscall(__NR_seccomp, op, flags, args); +} +#endif + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +static int apply_sandbox(const char **allowed_paths, int path_nb, const char **cgroup_paths, int cgroup_nb) +{ + __u32 key; + int i, ret = 0, map_fs = -1, map_cg = -1, offset; + + /* set up the test sandbox */ + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(no_new_priv)"); + return 1; + } + + /* register a new syscall filter */ + struct sock_filter filter0[] = { + /* pass a cookie containing 5 to the LSM hook filter */ + BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LANDLOCK | 5), + }; + struct sock_fprog prog0 = { + .len = (unsigned short)ARRAY_SIZE(filter0), + .filter = filter0, + }; + if (seccomp(SECCOMP_SET_MODE_FILTER, 0, )) { + perror("seccomp(set_filter)"); + return 1; + } + + if (path_nb) { + map_fs = bpf_create_map(BPF_MAP_TYPE_LANDLOCK_ARRAY, sizeof(key), sizeof(struct landlock_handle), 10, 0); + if (map_fs < 0) { + fprintf(stderr, "bpf_create_map(fs"); + perror(")"); + return 1; + } + for (key = 0; key < path_nb; key++) { + int fd = open(allowed_paths[key], O_RDONLY | O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "open(fs: \"%s\"", allowed_paths[key]); + perror(")"); + return 1; + } + struct landlock_handle handle = { + .type = BPF_MAP_HANDLE_TYPE_LANDLOCK_FS_FD, +
[RFC v2 10/10] samples/landlock: Add sandbox example
Add a basic sandbox tool to create a process isolated from some part of the system. This can depend of the current cgroup. Example: $ mkdir /sys/fs/cgroup/sandboxed $ ls /home user1 $ LANDLOCK_CGROUPS='/sys/fs/cgroup/sandboxed' \ LANDLOCK_ALLOWED='/bin:/lib:/usr:/tmp:/proc/self/fd/0' \ ./sandbox /bin/sh -i $ ls /home user1 $ echo $$ > /sys/fs/cgroup/sandboxed/cgroup.procs $ ls /home ls: cannot open directory '/home': Permission denied Signed-off-by: Mickaël Salaün Cc: Kees Cook Cc: Alexei Starovoitov Cc: James Morris Cc: Serge E. Hallyn Cc: David S. Miller Cc: Daniel Borkmann --- samples/Makefile| 2 +- samples/landlock/.gitignore | 1 + samples/landlock/Makefile | 16 +++ samples/landlock/sandbox.c | 295 4 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 samples/landlock/.gitignore create mode 100644 samples/landlock/Makefile create mode 100644 samples/landlock/sandbox.c diff --git a/samples/Makefile b/samples/Makefile index 2e3b523d7097..42e6a613f728 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ - configfs/ connector/ v4l/ + configfs/ connector/ v4l/ landlock/ diff --git a/samples/landlock/.gitignore b/samples/landlock/.gitignore new file mode 100644 index ..f6c6da930a30 --- /dev/null +++ b/samples/landlock/.gitignore @@ -0,0 +1 @@ +/sandbox diff --git a/samples/landlock/Makefile b/samples/landlock/Makefile new file mode 100644 index ..d1044b2afd27 --- /dev/null +++ b/samples/landlock/Makefile @@ -0,0 +1,16 @@ +# kbuild trick to avoid linker error. Can be omitted if a module is built. +obj- := dummy.o + +hostprogs-$(CONFIG_SECURITY_LANDLOCK) := sandbox +sandbox-objs := sandbox.o + +always := $(hostprogs-y) + +HOSTCFLAGS += -I$(objtree)/usr/include + +# Trick to allow make to be run from this directory +all: + $(MAKE) -C ../../ $$PWD/ + +clean: + $(MAKE) -C ../../ M=$$PWD clean diff --git a/samples/landlock/sandbox.c b/samples/landlock/sandbox.c new file mode 100644 index ..86604963c30c --- /dev/null +++ b/samples/landlock/sandbox.c @@ -0,0 +1,295 @@ +/* + * Landlock LSM - Sandbox Example + * + * Copyright (C) 2016 Mickaël Salaün + * + * The code may be used by anyone for any purpose, and can serve as a starting + * point for developing a sandbox. + */ + +#define _GNU_SOURCE +#include +#include /* open() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../tools/include/linux/filter.h" + +#include "../bpf/libbpf.c" + +#ifndef seccomp +static int seccomp(unsigned int op, unsigned int flags, void *args) +{ + errno = 0; + return syscall(__NR_seccomp, op, flags, args); +} +#endif + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +static int apply_sandbox(const char **allowed_paths, int path_nb, const char **cgroup_paths, int cgroup_nb) +{ + __u32 key; + int i, ret = 0, map_fs = -1, map_cg = -1, offset; + + /* set up the test sandbox */ + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(no_new_priv)"); + return 1; + } + + /* register a new syscall filter */ + struct sock_filter filter0[] = { + /* pass a cookie containing 5 to the LSM hook filter */ + BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LANDLOCK | 5), + }; + struct sock_fprog prog0 = { + .len = (unsigned short)ARRAY_SIZE(filter0), + .filter = filter0, + }; + if (seccomp(SECCOMP_SET_MODE_FILTER, 0, )) { + perror("seccomp(set_filter)"); + return 1; + } + + if (path_nb) { + map_fs = bpf_create_map(BPF_MAP_TYPE_LANDLOCK_ARRAY, sizeof(key), sizeof(struct landlock_handle), 10, 0); + if (map_fs < 0) { + fprintf(stderr, "bpf_create_map(fs"); + perror(")"); + return 1; + } + for (key = 0; key < path_nb; key++) { + int fd = open(allowed_paths[key], O_RDONLY | O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "open(fs: \"%s\"", allowed_paths[key]); + perror(")"); + return 1; + } + struct landlock_handle handle = { + .type = BPF_MAP_HANDLE_TYPE_LANDLOCK_FS_FD, + .fd = (__u64)fd, + }; + + /* register a new LSM handle */ + if (bpf_update_elem(map_fs, ,