Commit 35e886e8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'landlock-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux

Pull landlock updates from Mickaël Salaün:
 "Some miscellaneous improvements, including new KUnit tests, extended
  documentation and boot help, and some cosmetic cleanups.

  Additional test changes already went through the net tree"

* tag 'landlock-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux:
  samples/landlock: Don't error out if a file path cannot be opened
  landlock: Use f_cred in security_file_open() hook
  landlock: Rename "ptrace" files to "task"
  landlock: Simplify current_check_access_socket()
  landlock: Warn once if a Landlock action is requested while disabled
  landlock: Extend documentation for kernel support
  landlock: Add support for KUnit tests
  selftests/landlock: Clean up error logs related to capabilities
parents 29da654b a17c60e5
......@@ -19,11 +19,12 @@ unexpected/malicious behaviors in user space applications. Landlock empowers
any process, including unprivileged ones, to securely restrict themselves.
We can quickly make sure that Landlock is enabled in the running system by
looking for "landlock: Up and running" in kernel logs (as root): ``dmesg | grep
landlock || journalctl -kg landlock`` . Developers can also easily check for
Landlock support with a :ref:`related system call <landlock_abi_versions>`. If
Landlock is not currently supported, we need to :ref:`configure the kernel
appropriately <kernel_support>`.
looking for "landlock: Up and running" in kernel logs (as root):
``dmesg | grep landlock || journalctl -kb -g landlock`` .
Developers can also easily check for Landlock support with a
:ref:`related system call <landlock_abi_versions>`.
If Landlock is not currently supported, we need to
:ref:`configure the kernel appropriately <kernel_support>`.
Landlock rules
==============
......@@ -499,6 +500,9 @@ access rights.
Kernel support
==============
Build time configuration
------------------------
Landlock was first introduced in Linux 5.13 but it must be configured at build
time with ``CONFIG_SECURITY_LANDLOCK=y``. Landlock must also be enabled at boot
time as the other security modules. The list of security modules enabled by
......@@ -507,11 +511,52 @@ contains ``CONFIG_LSM=landlock,[...]`` with ``[...]`` as the list of other
potentially useful security modules for the running system (see the
``CONFIG_LSM`` help).
Boot time configuration
-----------------------
If the running kernel does not have ``landlock`` in ``CONFIG_LSM``, then we can
still enable it by adding ``lsm=landlock,[...]`` to
Documentation/admin-guide/kernel-parameters.rst thanks to the bootloader
enable Landlock by adding ``lsm=landlock,[...]`` to
Documentation/admin-guide/kernel-parameters.rst in the boot loader
configuration.
For example, if the current built-in configuration is:
.. code-block:: console
$ zgrep -h "^CONFIG_LSM=" "/boot/config-$(uname -r)" /proc/config.gz 2>/dev/null
CONFIG_LSM="lockdown,yama,integrity,apparmor"
...and if the cmdline doesn't contain ``landlock`` either:
.. code-block:: console
$ sed -n 's/.*\(\<lsm=\S\+\).*/\1/p' /proc/cmdline
lsm=lockdown,yama,integrity,apparmor
...we should configure the boot loader to set a cmdline extending the ``lsm``
list with the ``landlock,`` prefix::
lsm=landlock,lockdown,yama,integrity,apparmor
After a reboot, we can check that Landlock is up and running by looking at
kernel logs:
.. code-block:: console
# dmesg | grep landlock || journalctl -kb -g landlock
[ 0.000000] Command line: [...] lsm=landlock,lockdown,yama,integrity,apparmor
[ 0.000000] Kernel command line: [...] lsm=landlock,lockdown,yama,integrity,apparmor
[ 0.000000] LSM: initializing lsm=lockdown,capability,landlock,yama,integrity,apparmor
[ 0.000000] landlock: Up and running.
The kernel may be configured at build time to always load the ``lockdown`` and
``capability`` LSMs. In that case, these LSMs will appear at the beginning of
the ``LSM: initializing`` log line as well, even if they are not configured in
the boot loader.
Network support
---------------
To be able to explicitly allow TCP operations (e.g., adding a network rule with
``LANDLOCK_ACCESS_NET_BIND_TCP``), the kernel must support TCP
(``CONFIG_INET=y``). Otherwise, sys_landlock_add_rule() returns an
......
// SPDX-License-Identifier: BSD-3-Clause
/*
* Simple Landlock sandbox manager able to launch a process restricted by a
* user-defined filesystem access control policy.
* Simple Landlock sandbox manager able to execute a process restricted by
* user-defined file system and network access control policies.
*
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
* Copyright © 2020 ANSSI
......@@ -120,9 +120,11 @@ static int populate_ruleset_fs(const char *const env_var, const int ruleset_fd,
if (path_beneath.parent_fd < 0) {
fprintf(stderr, "Failed to open \"%s\": %s\n",
path_list[i], strerror(errno));
goto out_free_name;
continue;
}
if (fstat(path_beneath.parent_fd, &statbuf)) {
fprintf(stderr, "Failed to stat \"%s\": %s\n",
path_list[i], strerror(errno));
close(path_beneath.parent_fd);
goto out_free_name;
}
......@@ -227,7 +229,7 @@ int main(const int argc, char *const argv[], char *const *const envp)
ENV_FS_RO_NAME, ENV_FS_RW_NAME, ENV_TCP_BIND_NAME,
ENV_TCP_CONNECT_NAME, argv[0]);
fprintf(stderr,
"Launch a command in a restricted environment.\n\n");
"Execute a command in a restricted environment.\n\n");
fprintf(stderr,
"Environment variables containing paths and ports "
"each separated by a colon:\n");
......@@ -248,7 +250,7 @@ int main(const int argc, char *const argv[], char *const *const envp)
ENV_TCP_CONNECT_NAME);
fprintf(stderr,
"\nexample:\n"
"%s=\"/bin:/lib:/usr:/proc:/etc:/dev/urandom\" "
"%s=\"${PATH}:/lib:/usr:/proc:/etc:/dev/urandom\" "
"%s=\"/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp\" "
"%s=\"9418\" "
"%s=\"80:443\" "
......@@ -383,6 +385,7 @@ int main(const int argc, char *const argv[], char *const *const envp)
cmd_path = argv[1];
cmd_argv = argv + 1;
fprintf(stderr, "Executing the sandboxed command...\n");
execvpe(cmd_path, cmd_argv, envp);
fprintf(stderr, "Failed to execute \"%s\": %s\n", cmd_path,
strerror(errno));
......
CONFIG_KUNIT=y
CONFIG_SECURITY=y
CONFIG_SECURITY_LANDLOCK=y
CONFIG_SECURITY_LANDLOCK_KUNIT_TEST=y
......@@ -20,3 +20,18 @@ config SECURITY_LANDLOCK
If you are unsure how to answer this question, answer N. Otherwise,
you should also prepend "landlock," to the content of CONFIG_LSM to
enable Landlock at boot time.
config SECURITY_LANDLOCK_KUNIT_TEST
bool "KUnit tests for Landlock" if !KUNIT_ALL_TESTS
depends on KUNIT=y
depends on SECURITY_LANDLOCK
default KUNIT_ALL_TESTS
help
Build KUnit tests for Landlock.
See the KUnit documentation in Documentation/dev-tools/kunit
Run all KUnit tests for Landlock with:
./tools/testing/kunit/kunit.py run --kunitconfig security/landlock
If you are unsure how to answer this question, answer N.
obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o
landlock-y := setup.o syscalls.o object.o ruleset.o \
cred.o ptrace.o fs.o
cred.o task.o fs.o
landlock-$(CONFIG_INET) += net.o
......@@ -17,4 +17,6 @@
#define pr_fmt(fmt) LANDLOCK_NAME ": " fmt
#define BIT_INDEX(bit) HWEIGHT(bit - 1)
#endif /* _SECURITY_LANDLOCK_COMMON_H */
This diff is collapsed.
......@@ -64,12 +64,11 @@ static const struct landlock_ruleset *get_current_net_domain(void)
static int current_check_access_socket(struct socket *const sock,
struct sockaddr *const address,
const int addrlen,
const access_mask_t access_request)
access_mask_t access_request)
{
__be16 port;
layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_NET] = {};
const struct landlock_rule *rule;
access_mask_t handled_access;
struct landlock_id id = {
.type = LANDLOCK_KEY_NET_PORT,
};
......@@ -164,9 +163,9 @@ static int current_check_access_socket(struct socket *const sock,
BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));
rule = landlock_find_rule(dom, id);
handled_access = landlock_init_layer_masks(
access_request = landlock_init_layer_masks(
dom, access_request, &layer_masks, LANDLOCK_KEY_NET_PORT);
if (landlock_unmask_layers(rule, handled_access, &layer_masks,
if (landlock_unmask_layers(rule, access_request, &layer_masks,
ARRAY_SIZE(layer_masks)))
return 0;
......
......@@ -14,8 +14,8 @@
#include "cred.h"
#include "fs.h"
#include "net.h"
#include "ptrace.h"
#include "setup.h"
#include "task.h"
bool landlock_initialized __ro_after_init = false;
......@@ -34,7 +34,7 @@ const struct lsm_id landlock_lsmid = {
static int __init landlock_init(void)
{
landlock_add_cred_hooks();
landlock_add_ptrace_hooks();
landlock_add_task_hooks();
landlock_add_fs_hooks();
landlock_add_net_hooks();
landlock_initialized = true;
......
......@@ -33,6 +33,18 @@
#include "ruleset.h"
#include "setup.h"
static bool is_initialized(void)
{
if (likely(landlock_initialized))
return true;
pr_warn_once(
"Disabled but requested by user space. "
"You should enable Landlock at boot time: "
"https://docs.kernel.org/userspace-api/landlock.html#boot-time-configuration\n");
return false;
}
/**
* copy_min_struct_from_user - Safe future-proof argument copying
*
......@@ -173,7 +185,7 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
/* Build-time checks. */
build_check_abi();
if (!landlock_initialized)
if (!is_initialized())
return -EOPNOTSUPP;
if (flags) {
......@@ -398,7 +410,7 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
struct landlock_ruleset *ruleset;
int err;
if (!landlock_initialized)
if (!is_initialized())
return -EOPNOTSUPP;
/* No flag for now. */
......@@ -458,7 +470,7 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
struct landlock_cred_security *new_llcred;
int err;
if (!landlock_initialized)
if (!is_initialized())
return -EOPNOTSUPP;
/*
......
......@@ -16,9 +16,9 @@
#include "common.h"
#include "cred.h"
#include "ptrace.h"
#include "ruleset.h"
#include "setup.h"
#include "task.h"
/**
* domain_scope_le - Checks domain ordering for scoped ptrace
......@@ -113,7 +113,7 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {
LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
};
__init void landlock_add_ptrace_hooks(void)
__init void landlock_add_task_hooks(void)
{
security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
&landlock_lsmid);
......
......@@ -6,9 +6,9 @@
* Copyright © 2019 ANSSI
*/
#ifndef _SECURITY_LANDLOCK_PTRACE_H
#define _SECURITY_LANDLOCK_PTRACE_H
#ifndef _SECURITY_LANDLOCK_TASK_H
#define _SECURITY_LANDLOCK_TASK_H
__init void landlock_add_ptrace_hooks(void);
__init void landlock_add_task_hooks(void);
#endif /* _SECURITY_LANDLOCK_PTRACE_H */
#endif /* _SECURITY_LANDLOCK_TASK_H */
......@@ -43,6 +43,7 @@ CONFIG_REGMAP_BUILD=y
CONFIG_SECURITY=y
CONFIG_SECURITY_APPARMOR=y
CONFIG_SECURITY_LANDLOCK=y
CONFIG_SOUND=y
CONFIG_SND=y
......
......@@ -74,31 +74,19 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all)
EXPECT_EQ(0, cap_set_secbits(noroot));
cap_p = cap_get_proc();
EXPECT_NE(NULL, cap_p)
{
TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_clear(cap_p))
{
TH_LOG("Failed to cap_clear: %s", strerror(errno));
}
EXPECT_NE(NULL, cap_p);
EXPECT_NE(-1, cap_clear(cap_p));
if (!drop_all) {
EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED,
ARRAY_SIZE(caps), caps, CAP_SET))
{
TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
}
ARRAY_SIZE(caps), caps, CAP_SET));
}
/* Automatically resets ambient capabilities. */
EXPECT_NE(-1, cap_set_proc(cap_p))
{
TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_free(cap_p))
{
TH_LOG("Failed to cap_free: %s", strerror(errno));
TH_LOG("Failed to set capabilities: %s", strerror(errno));
}
EXPECT_NE(-1, cap_free(cap_p));
/* Quickly checks that ambient capabilities are cleared. */
EXPECT_NE(-1, cap_get_ambient(caps[0]));
......@@ -122,22 +110,13 @@ static void _change_cap(struct __test_metadata *const _metadata,
cap_t cap_p;
cap_p = cap_get_proc();
EXPECT_NE(NULL, cap_p)
{
TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_set_flag(cap_p, flag, 1, &cap, value))
{
TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
}
EXPECT_NE(NULL, cap_p);
EXPECT_NE(-1, cap_set_flag(cap_p, flag, 1, &cap, value));
EXPECT_NE(-1, cap_set_proc(cap_p))
{
TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
}
EXPECT_NE(-1, cap_free(cap_p))
{
TH_LOG("Failed to cap_free: %s", strerror(errno));
TH_LOG("Failed to set capability %d: %s", cap, strerror(errno));
}
EXPECT_NE(-1, cap_free(cap_p));
}
static void __maybe_unused set_cap(struct __test_metadata *const _metadata,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment