From: "Mickaël Salaün" <mic@digikod.net>
To: "Günther Noack" <gnoack@google.com>
Cc: "Mickaël Salaün" <mic@digikod.net>,
"Ada Smith" <adasmithgt@gmail.com>,
"Hungyu Lin" <dennylin0707@gmail.com>,
"James Morris" <jmorris@namei.org>,
"Josef Bacik" <josef@toxicpanda.com>,
"Paul Moore" <paul@paul-moore.com>,
"Serge Hallyn" <serge@hallyn.com>,
kernel-team@cloudflare.com, linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org
Subject: [PATCH 2/6] landlock: Mediate CAP_SYS_RAWIO for mappings below mmap_min_addr
Date: Tue, 10 Nov 2026 21:24:30 +0100 [thread overview]
Message-ID: <20261110202436.2408244-3-mic@digikod.net> (raw)
In-Reply-To: <20261110202436.2408244-1-mic@digikod.net>
Until now, a process in a domain that denies CAP_SYS_RAWIO could still
map memory below the vm.mmap_min_addr limit if it held this capability.
cap_mmap_addr() is commoncap's mmap_addr hook, and it checks
CAP_SYS_RAWIO with cap_capable(), not security_capable(), so the check
never reaches hook_capable(). Mapping the lowest pages is what this
limit protects against, because it helps to exploit kernel NULL pointer
dereferences.
Add a Landlock mmap_addr hook that checks CAP_SYS_RAWIO against the
domain under the same condition as cap_mmap_addr(). With the same
vm.mmap_min_addr value, the hook only denies mappings for which
commoncap required the capability. security_mmap_addr() stops at
commoncap's error, so processes without the capability get the same
result as before. This also covers the x86 vm86() syscalls, which use
the same check for address 0.
Making cap_mmap_addr() call capable() would also fix this, but it would
send every low mapping through the capable hook of all LSMs (SELinux,
AppArmor, SafeSetID, BPF LSM programs), adding capability checks that
their policies never had to handle. For instance, SELinux checks
mmap_zero in its own mmap_addr hook and keeps it separate from the
capability on purpose. LSMs with their own policy for low mappings
implement it in this hook, so Landlock does the same.
Cc: Günther Noack <gnoack@google.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Serge Hallyn <serge@hallyn.com>
Reported-by: Ada Smith <adasmithgt@gmail.com>
Fixes: 97c8386f1d74 ("landlock: Enforce capability restrictions")
Signed-off-by: Mickaël Salaün <mic@digikod.net>
---
security/landlock/cap.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/security/landlock/cap.c b/security/landlock/cap.c
index fa59118e3486..10e1ca772b9c 100644
--- a/security/landlock/cap.c
+++ b/security/landlock/cap.c
@@ -9,6 +9,7 @@
#include <linux/cred.h>
#include <linux/lsm_audit.h>
#include <linux/lsm_hooks.h>
+#include <linux/security.h>
#include <uapi/linux/landlock.h>
#include "cap.h"
@@ -90,8 +91,29 @@ static int hook_capable(const struct cred *cred, struct user_namespace *ns,
return check_cap(cred, cap, opts);
}
+/**
+ * hook_mmap_addr - Restrict mappings below dac_mmap_min_addr
+ *
+ * @addr: Address of the new mapping.
+ *
+ * cap_mmap_addr() requires CAP_SYS_RAWIO to map below dac_mmap_min_addr, but
+ * calls cap_capable() directly, which skips hook_capable(). Check the same
+ * condition against the domain. commoncap runs first, so this only sees
+ * mappings that commoncap allowed.
+ *
+ * Return: 0 if allowed, -EPERM if CAP_SYS_RAWIO use is denied.
+ */
+static int hook_mmap_addr(unsigned long addr)
+{
+ if (addr >= dac_mmap_min_addr)
+ return 0;
+
+ return check_cap(current_cred(), CAP_SYS_RAWIO, CAP_OPT_NONE);
+}
+
static struct security_hook_list landlock_hooks[] __ro_after_init = {
LSM_HOOK_INIT(capable, hook_capable),
+ LSM_HOOK_INIT(mmap_addr, hook_mmap_addr),
};
__init void landlock_add_cap_hooks(void)
--
2.56.0
next prev parent reply other threads:[~2026-11-10 20:24 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 20:24 [PATCH 0/6] Fix Landlock mediation of commoncap's capability checks Mickaël Salaün
2026-11-10 20:24 ` [PATCH 1/6] landlock: Factor out capability denial checks Mickaël Salaün
2026-11-10 20:24 ` Mickaël Salaün [this message]
2026-11-10 20:24 ` [PATCH 3/6] landlock: Mediate CAP_SETPCAP for inheritable capabilities Mickaël Salaün
2026-11-10 20:24 ` [PATCH 4/6] landlock: Mediate CAP_SYS_ADMIN for the admin memory reserve Mickaël Salaün
2026-11-10 20:24 ` [PATCH 5/6] selftests/landlock: Test capability checks outside the capable hook Mickaël Salaün
2026-11-10 20:24 ` [PATCH 6/6] landlock: Fix capability restriction documentation Mickaël Salaün
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110202436.2408244-3-mic@digikod.net \
--to=mic@digikod.net \
--cc=adasmithgt@gmail.com \
--cc=dennylin0707@gmail.com \
--cc=gnoack@google.com \
--cc=jmorris@namei.org \
--cc=josef@toxicpanda.com \
--cc=kernel-team@cloudflare.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=paul@paul-moore.com \
--cc=serge@hallyn.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®