Inter-revision diff: patch 11

Comparing v21 (message) to v28 (message)

--- v21
+++ v28
@@ -1,14 +1,45 @@
 From: Mickaël Salaün <mic@linux.microsoft.com>
 
 Add a basic sandbox tool to launch a command which can only access a
-whitelist of file hierarchies in a read-only or read-write way.
+list of file hierarchies in a read-only or read-write way.
 
 Cc: James Morris <jmorris@namei.org>
-Cc: Jann Horn <jannh@google.com>
 Cc: Kees Cook <keescook@chromium.org>
 Cc: Serge E. Hallyn <serge@hallyn.com>
 Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com>
+Reviewed-by: Jann Horn <jannh@google.com>
 ---
+
+Changes since v27:
+* Add samples/landlock/ to MAINTAINERS.
+* Update landlock_restrict_self(2).
+* Tweak Kconfig title and description.
+
+Changes since v25:
+* Improve comments and fix help (suggested by Jann Horn).
+* Add a safeguard for errno check (suggested by Jann Horn).
+* Allows users to not use all possible restrictions (e.g. use LL_FS_RO
+  without LL_FS_RW).
+* Update syscall names.
+* Improve Makefile:
+  - Replace hostprogs/always-y with userprogs-always-y, available since
+    commit faabed295ccc ("kbuild: introduce hostprogs-always-y and
+    userprogs-always-y").
+  - Depends on CC_CAN_LINK.
+* Add Reviewed-by Jann Horn.
+
+Changes since v25:
+* Remove useless errno set in the syscall wrappers.
+* Cosmetic variable renames.
+
+Changes since v23:
+* Re-add hints to help users understand the required kernel
+  configuration.  This was removed with the removal of
+  landlock_get_features(2).
+
+Changes since v21:
+* Remove LANDLOCK_ACCESS_FS_CHROOT.
+* Clean up help.
 
 Changes since v20:
 * Update with new syscalls and type names.
@@ -50,18 +81,31 @@
 Previous changes:
 https://lore.kernel.org/lkml/20190721213116.23476-9-mic@digikod.net/
 ---
+ MAINTAINERS                  |   1 +
  samples/Kconfig              |   7 ++
  samples/Makefile             |   1 +
  samples/landlock/.gitignore  |   1 +
- samples/landlock/Makefile    |  15 +++
- samples/landlock/sandboxer.c | 220 +++++++++++++++++++++++++++++++++++
- 5 files changed, 244 insertions(+)
+ samples/landlock/Makefile    |  13 ++
+ samples/landlock/sandboxer.c | 238 +++++++++++++++++++++++++++++++++++
+ 6 files changed, 261 insertions(+)
  create mode 100644 samples/landlock/.gitignore
  create mode 100644 samples/landlock/Makefile
  create mode 100644 samples/landlock/sandboxer.c
 
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 3df7b12dc7f1..cf49d9431439 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -9943,6 +9943,7 @@ S:	Supported
+ W:	https://landlock.io
+ T:	git https://github.com/landlock-lsm/linux.git
+ F:	include/uapi/linux/landlock.h
++F:	samples/landlock/
+ F:	security/landlock/
+ F:	tools/testing/selftests/landlock/
+ K:	landlock
 diff --git a/samples/Kconfig b/samples/Kconfig
-index 0ed6e4d71d87..092962924f0d 100644
+index 0ed6e4d71d87..30ad633cd82c 100644
 --- a/samples/Kconfig
 +++ b/samples/Kconfig
 @@ -124,6 +124,13 @@ config SAMPLE_HIDRAW
@@ -69,17 +113,17 @@
  	depends on CC_CAN_LINK && HEADERS_INSTALL
  
 +config SAMPLE_LANDLOCK
-+	bool "Build Landlock sample code"
-+	depends on HEADERS_INSTALL
++	bool "Build Landlock example"
++	depends on CC_CAN_LINK && HEADERS_INSTALL
 +	help
-+	  Build a simple Landlock sandbox manager able to launch a process
-+	  restricted by a user-defined filesystem access-control security policy.
++	  Build a simple Landlock sandbox manager able to start a process
++	  restricted by a user-defined filesystem access control policy.
 +
  config SAMPLE_PIDFD
  	bool "pidfd sample"
  	depends on CC_CAN_LINK && HEADERS_INSTALL
 diff --git a/samples/Makefile b/samples/Makefile
-index 754553597581..4a6ce8f64a4c 100644
+index c3392a595e4b..087e0988ccc5 100644
 --- a/samples/Makefile
 +++ b/samples/Makefile
 @@ -11,6 +11,7 @@ obj-$(CONFIG_SAMPLE_KDB)		+= kdb/
@@ -99,17 +143,15 @@
 +/sandboxer
 diff --git a/samples/landlock/Makefile b/samples/landlock/Makefile
 new file mode 100644
-index 000000000000..21eda5774948
+index 000000000000..5d601e51c2eb
 --- /dev/null
 +++ b/samples/landlock/Makefile
-@@ -0,0 +1,15 @@
+@@ -0,0 +1,13 @@
 +# SPDX-License-Identifier: BSD-3-Clause
 +
-+hostprogs := sandboxer
-+
-+always-y := $(hostprogs)
-+
-+KBUILD_HOSTCFLAGS += -I$(objtree)/usr/include
++userprogs-always-y := sandboxer
++
++userccflags += -I usr/include
 +
 +.PHONY: all clean
 +
@@ -120,14 +162,14 @@
 +	$(MAKE) -C ../.. M=samples/landlock/ clean
 diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c
 new file mode 100644
-index 000000000000..53ebc19aad3d
+index 000000000000..7a15910d2171
 --- /dev/null
 +++ b/samples/landlock/sandboxer.c
-@@ -0,0 +1,220 @@
+@@ -0,0 +1,238 @@
 +// SPDX-License-Identifier: BSD-3-Clause
 +/*
 + * Simple Landlock sandbox manager able to launch a process restricted by a
-+ * user-defined filesystem access-control security policy.
++ * user-defined filesystem access control policy.
 + *
 + * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
 + * Copyright © 2020 ANSSI
@@ -152,7 +194,6 @@
 +		const struct landlock_ruleset_attr *const attr,
 +		const size_t size, const __u32 flags)
 +{
-+	errno = 0;
 +	return syscall(__NR_landlock_create_ruleset, attr, size, flags);
 +}
 +#endif
@@ -162,19 +203,16 @@
 +		const enum landlock_rule_type rule_type,
 +		const void *const rule_attr, const __u32 flags)
 +{
-+	errno = 0;
 +	return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type,
 +			rule_attr, flags);
 +}
 +#endif
 +
-+#ifndef landlock_enforce_ruleset_current
-+static inline int landlock_enforce_ruleset_current(const int ruleset_fd,
++#ifndef landlock_restrict_self
++static inline int landlock_restrict_self(const int ruleset_fd,
 +		const __u32 flags)
 +{
-+	errno = 0;
-+	return syscall(__NR_landlock_enforce_ruleset_current, ruleset_fd,
-+			flags);
++	return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
 +}
 +#endif
 +
@@ -184,20 +222,20 @@
 +
 +static int parse_path(char *env_path, const char ***const path_list)
 +{
-+	int i, path_nb = 0;
++	int i, num_paths = 0;
 +
 +	if (env_path) {
-+		path_nb++;
++		num_paths++;
 +		for (i = 0; env_path[i]; i++) {
 +			if (env_path[i] == ENV_PATH_TOKEN[0])
-+				path_nb++;
++				num_paths++;
 +		}
 +	}
-+	*path_list = malloc(path_nb * sizeof(**path_list));
-+	for (i = 0; i < path_nb; i++)
++	*path_list = malloc(num_paths * sizeof(**path_list));
++	for (i = 0; i < num_paths; i++)
 +		(*path_list)[i] = strsep(&env_path, ENV_PATH_TOKEN);
 +
-+	return path_nb;
++	return num_paths;
 +}
 +
 +#define ACCESS_FILE ( \
@@ -209,7 +247,7 @@
 +		const char *const env_var, const int ruleset_fd,
 +		const __u64 allowed_access)
 +{
-+	int path_nb, i;
++	int num_paths, i, ret = 1;
 +	char *env_path_name;
 +	const char **path_list = NULL;
 +	struct landlock_path_beneath_attr path_beneath = {
@@ -218,18 +256,23 @@
 +
 +	env_path_name = getenv(env_var);
 +	if (!env_path_name) {
++		/* Prevents users to forget a setting. */
 +		fprintf(stderr, "Missing environment variable %s\n", env_var);
 +		return 1;
 +	}
 +	env_path_name = strdup(env_path_name);
 +	unsetenv(env_var);
-+	path_nb = parse_path(env_path_name, &path_list);
-+	if (path_nb == 1 && path_list[0][0] == '\0') {
-+		fprintf(stderr, "Missing path in %s\n", env_var);
-+		goto err_free_name;
-+	}
-+
-+	for (i = 0; i < path_nb; i++) {
++	num_paths = parse_path(env_path_name, &path_list);
++	if (num_paths == 1 && path_list[0][0] == '\0') {
++		/*
++		 * Allows to not use all possible restrictions (e.g. use
++		 * LL_FS_RO without LL_FS_RW).
++		 */
++		ret = 0;
++		goto out_free_name;
++	}
++
++	for (i = 0; i < num_paths; i++) {
 +		struct stat statbuf;
 +
 +		path_beneath.parent_fd = open(path_list[i], O_PATH |
@@ -238,11 +281,11 @@
 +			fprintf(stderr, "Failed to open \"%s\": %s\n",
 +					path_list[i],
 +					strerror(errno));
-+			goto err_free_name;
++			goto out_free_name;
 +		}
 +		if (fstat(path_beneath.parent_fd, &statbuf)) {
 +			close(path_beneath.parent_fd);
-+			goto err_free_name;
++			goto out_free_name;
 +		}
 +		path_beneath.allowed_access = allowed_access;
 +		if (!S_ISDIR(statbuf.st_mode))
@@ -252,23 +295,21 @@
 +			fprintf(stderr, "Failed to update the ruleset with \"%s\": %s\n",
 +					path_list[i], strerror(errno));
 +			close(path_beneath.parent_fd);
-+			goto err_free_name;
++			goto out_free_name;
 +		}
 +		close(path_beneath.parent_fd);
 +	}
++	ret = 0;
++
++out_free_name:
 +	free(env_path_name);
-+	return 0;
-+
-+err_free_name:
-+	free(env_path_name);
-+	return 1;
++	return ret;
 +}
 +
 +#define ACCESS_FS_ROUGHLY_READ ( \
 +	LANDLOCK_ACCESS_FS_EXECUTE | \
 +	LANDLOCK_ACCESS_FS_READ_FILE | \
-+	LANDLOCK_ACCESS_FS_READ_DIR | \
-+	LANDLOCK_ACCESS_FS_CHROOT)
++	LANDLOCK_ACCESS_FS_READ_DIR)
 +
 +#define ACCESS_FS_ROUGHLY_WRITE ( \
 +	LANDLOCK_ACCESS_FS_WRITE_FILE | \
@@ -296,11 +337,12 @@
 +		fprintf(stderr, "usage: %s=\"...\" %s=\"...\" %s <cmd> [args]...\n\n",
 +				ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]);
 +		fprintf(stderr, "Launch a command in a restricted environment.\n\n");
-+		fprintf(stderr, "Environment variables containing paths, each separated by a colon:\n");
++		fprintf(stderr, "Environment variables containing paths, "
++				"each separated by a colon:\n");
 +		fprintf(stderr, "* %s: list of paths allowed to be used in a read-only way.\n",
 +				ENV_FS_RO_NAME);
 +		fprintf(stderr, "* %s: list of paths allowed to be used in a read-write way.\n",
-+				ENV_FS_RO_NAME);
++				ENV_FS_RW_NAME);
 +		fprintf(stderr, "\nexample:\n"
 +				"%s=\"/bin:/lib:/usr:/proc:/etc:/dev/urandom\" "
 +				"%s=\"/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp\" "
@@ -311,7 +353,24 @@
 +
 +	ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
 +	if (ruleset_fd < 0) {
++		const int err = errno;
++
 +		perror("Failed to create a ruleset");
++		switch (err) {
++		case ENOSYS:
++			fprintf(stderr, "Hint: Landlock is not supported by the current kernel. "
++					"To support it, build the kernel with "
++					"CONFIG_SECURITY_LANDLOCK=y and prepend "
++					"\"landlock,\" to the content of CONFIG_LSM.\n");
++			break;
++		case EOPNOTSUPP:
++			fprintf(stderr, "Hint: Landlock is currently disabled. "
++					"It can be enabled in the kernel configuration by "
++					"prepending \"landlock,\" to the content of CONFIG_LSM, "
++					"or at boot time by setting the same content to the "
++					"\"lsm\" kernel parameter.\n");
++			break;
++		}
 +		return 1;
 +	}
 +	if (populate_ruleset(ENV_FS_RO_NAME, ruleset_fd,
@@ -326,7 +385,7 @@
 +		perror("Failed to restrict privileges");
 +		goto err_close_ruleset;
 +	}
-+	if (landlock_enforce_ruleset_current(ruleset_fd, 0)) {
++	if (landlock_restrict_self(ruleset_fd, 0)) {
 +		perror("Failed to enforce ruleset");
 +		goto err_close_ruleset;
 +	}
@@ -337,7 +396,8 @@
 +	execvpe(cmd_path, cmd_argv, envp);
 +	fprintf(stderr, "Failed to execute \"%s\": %s\n", cmd_path,
 +			strerror(errno));
-+	fprintf(stderr, "Hint: access to the binary, the interpreter or shared libraries may be denied.\n");
++	fprintf(stderr, "Hint: access to the binary, the interpreter or "
++			"shared libraries may be denied.\n");
 +	return 1;
 +
 +err_close_ruleset:
@@ -345,5 +405,5 @@
 +	return 1;
 +}
 -- 
-2.28.0
-
+2.30.0
+
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help