Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160// SPDX-License-Identifier: GPL-2.0-only/* * Landlock - Capability hooks * * Copyright © 2026 Cloudflare, Inc. */
#include <linux/capability.h>#include <linux/cred.h>#include <linux/lsm_audit.h>#include <linux/lsm_hooks.h>#include <uapi/linux/landlock.h>
#include "cap.h"#include "cred.h"#include "domain.h"#include "limits.h"#include "log.h"#include "ruleset.h"#include "setup.h"
static const struct access_masks cap_permission = { .permissions = LANDLOCK_PERMISSION_CAPABILITY_USE,};
/** * hook_capable - Deny capability use for Landlock-sandboxed processes * * @cred: Credentials being checked. * @ns: Target user namespace (intentionally ignored; policy depends on the * acting credentials and @cap, not namespace ownership). * @cap: Capability number (CAP_*). * @opts: Capability check options. CAP_OPT_NOAUDIT skips the denial record: * no audit record, no trace event, and no denial count. * * Pure bitmask check: denies the capability if it is not in the layer's allowed * set. This hook is purely restrictive: commoncap is registered with * LSM_ORDER_FIRST so cap_capable() always runs first, which means Landlock can * deny capabilities that commoncap would allow, but never grant capabilities * that commoncap denied. * * Return: 0 if allowed, -EPERM if capability use is denied. */static int hook_capable(const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts){ const struct landlock_cred_security *subject; size_t denied_layer;
subject = landlock_get_applicable_subject(cred, cap_permission, NULL); if (!subject) return 0;
denied_layer = landlock_permission_is_denied( subject->domain, LANDLOCK_PERMISSION_CAPABILITY_USE, landlock_cap_to_bit(cap)); if (!denied_layer) return 0;
if (!(opts & CAP_OPT_NOAUDIT)) landlock_log_denial( subject, &(struct landlock_request){ .type = LANDLOCK_REQUEST_CAPABILITY, .audit.type = LSM_AUDIT_DATA_CAP, .audit.u.cap = cap, .permission = LANDLOCK_PERMISSION_CAPABILITY_USE, .layer_plus_one = denied_layer, });
return -EPERM;}
static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(capable, hook_capable),};
__init void landlock_add_cap_hooks(void){ security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), &landlock_lsmid);}
#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST
#include <kunit/test.h>
static void test_cap_to_bit(struct kunit *const test){ KUNIT_EXPECT_EQ(test, BIT_ULL(0), landlock_cap_to_bit(0)); KUNIT_EXPECT_EQ(test, BIT_ULL(CAP_NET_RAW), landlock_cap_to_bit(CAP_NET_RAW)); KUNIT_EXPECT_EQ(test, BIT_ULL(CAP_SYS_ADMIN), landlock_cap_to_bit(CAP_SYS_ADMIN)); KUNIT_EXPECT_EQ(test, BIT_ULL(CAP_LAST_CAP), landlock_cap_to_bit(CAP_LAST_CAP));}
static void test_cap_to_bit_invalid(struct kunit *const test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG");
/* clang-format off */ kunit_warning_suppress(test) { /* clang-format on */ KUNIT_EXPECT_EQ(test, 0ULL, landlock_cap_to_bit(-1)); KUNIT_EXPECT_EQ(test, 0ULL, landlock_cap_to_bit(CAP_LAST_CAP + 1)); }}
static void test_caps_to_bits_valid(struct kunit *const test){ KUNIT_EXPECT_EQ(test, (u64)CAP_VALID_MASK, landlock_caps_to_bits(CAP_VALID_MASK)); KUNIT_EXPECT_EQ(test, BIT_ULL(CAP_NET_RAW), landlock_caps_to_bits(BIT_ULL(CAP_NET_RAW)));}
static void test_caps_to_bits_unknown(struct kunit *const test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG");
/* clang-format off */ kunit_warning_suppress(test) { /* clang-format on */ KUNIT_EXPECT_EQ( test, 0ULL, landlock_caps_to_bits(BIT_ULL(CAP_LAST_CAP + 1))); }}
static void test_caps_to_bits_zero(struct kunit *const test){ KUNIT_EXPECT_EQ(test, 0ULL, landlock_caps_to_bits(0));}
static struct kunit_case test_cases[] = { /* clang-format off */ KUNIT_CASE(test_cap_to_bit), KUNIT_CASE(test_cap_to_bit_invalid), KUNIT_CASE(test_caps_to_bits_valid), KUNIT_CASE(test_caps_to_bits_unknown), KUNIT_CASE(test_caps_to_bits_zero), {} /* clang-format on */};
static struct kunit_suite test_suite = { .name = "landlock_cap", .test_cases = test_cases,};
kunit_test_suite(test_suite);
#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */