From: "Günther Noack" <gnoack@google.com>
To: "Mickaël Salaün" <mic@digikod.net>
Cc: linux-security-module@vger.kernel.org,
linux-fsdevel@vger.kernel.org, Tingmao Wang <m@maowtm.org>,
Justin Suess <utilityemal77@gmail.com>
Subject: landlock bug: procfs denials because inodes have unstable identity
Date: Fri, 30 Oct 2026 16:45:04 +0100 [thread overview]
Message-ID: <auS7gAFy13EOp_Zt@google.com> (raw)
Hello!
The Landlock LSM lets processes define policies which are attached to
struct inode objects internally. As a consequence, if filesystems
forget these inodes and start using new inode objects for the same
files or directories later on, these policies do not work as intended
any more.
As it turns out, procfs has that property as well and can lose inode
identities over time, even though it does not happen immediately.
In my understanding, this is not intended. Landlock has explicit
selftests to exercise that Landlock policies work in Procfs.
For reference, similar issues have been investigated also for hostfs
[1] and 9p [2]:
[1] https://lore.kernel.org/all/20230309165455.175131-2-mic@digikod.net/
[2] https://lore.kernel.org/all/cover.1756935780.git.m@maowtm.org/
Steps to reproduce
==================
Process A:
* Enter a Landlock domain where access to /proc/sys/kernel/random
(and files below it) is allowed.
* Repeatedly open and close the boot_id file from that same directory
At the same time, the dentry caches get freed up.
We can emulate this by writing to /proc/sys/vm/drop_caches from
another (root) process:
# echo 2 > /proc/sys/vm/drop_caches
Observed result: Process A fails because of a Landlock refusal opening
the boot_id file. When Landlock walks the path for the check, the
inodes have now a different identity than before and don't match, so
Landlock denies the operation.
Expected result: Dropping the caches should not affect Landlock's
behaviour.
At the bottom of this email, I am including the source code for a
program that does Process A -- you can run this to reproduce, and then
write into the drop_caches file from another process as root.
Solution...?
============
I don't have a fix for it yet.
I am open to suggestions. Is this feasible to change in procfs?
—Günther
Reproducer program, for easier reproduction (don't forget to drop
caches in parallel):
---landlock_uuid.c
#define _GNU_SOURCE
#include <err.h>
#include <fcntl.h>
#include <linux/landlock.h>
#include <stddef.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <unistd.h>
static int landlock_create_ruleset(struct landlock_ruleset_attr *attr,
size_t size, __u32 flags)
{
return syscall(__NR_landlock_create_ruleset, attr, size, flags);
}
static int landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type,
void *rule_attr, __u32 flags)
{
return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type,
rule_attr, flags);
}
static int landlock_restrict_self(int ruleset_fd, __u32 flags)
{
return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
}
int main(void)
{
struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs =
LANDLOCK_ACCESS_FS_EXECUTE |
LANDLOCK_ACCESS_FS_WRITE_FILE |
LANDLOCK_ACCESS_FS_READ_FILE |
LANDLOCK_ACCESS_FS_READ_DIR |
LANDLOCK_ACCESS_FS_REMOVE_DIR |
LANDLOCK_ACCESS_FS_REMOVE_FILE |
LANDLOCK_ACCESS_FS_MAKE_CHAR |
LANDLOCK_ACCESS_FS_MAKE_DIR |
LANDLOCK_ACCESS_FS_MAKE_REG |
LANDLOCK_ACCESS_FS_MAKE_SOCK |
LANDLOCK_ACCESS_FS_MAKE_FIFO |
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
LANDLOCK_ACCESS_FS_MAKE_SYM |
LANDLOCK_ACCESS_FS_REFER |
LANDLOCK_ACCESS_FS_TRUNCATE |
LANDLOCK_ACCESS_FS_IOCTL_DEV |
LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
};
/*
* Backwards compatibility checks omitted for brevity.
* Assuming Linux 7.3 here. :)
*/
int ruleset_fd = landlock_create_ruleset(&ruleset_attr,
sizeof(ruleset_attr), 0);
if (ruleset_fd < 0)
err(1, "landlock_create_ruleset");
int parent_fd = open("/proc/sys/kernel/random", O_PATH | O_CLOEXEC);
if (parent_fd < 0)
err(1, "open(/proc/sys/kernel/random)");
struct landlock_path_beneath_attr path_beneath = {
.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE,
.parent_fd = parent_fd,
};
if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath, 0) < 0)
err(1, "landlock_add_rule");
close(parent_fd);
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
err(1, "prctl(PR_SET_NO_NEW_PRIVS)");
if (landlock_restrict_self(ruleset_fd, 0) < 0)
err(1, "landlock_restrict_self");
close(ruleset_fd);
/* Print out the boot_id file once a second. */
for (;;) {
int fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY);
if (fd < 0)
err(1, "open(/proc/sys/kernel/random/boot_id)");
char buf[64];
ssize_t n;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
if (write(STDOUT_FILENO, buf, n) < 0)
err(1, "write");
}
if (n < 0)
err(1, "read");
close(fd);
sleep(1);
}
return 0;
}
---
reply other threads:[~2026-10-30 15:45 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=auS7gAFy13EOp_Zt@google.com \
--to=gnoack@google.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=mic@digikod.net \
--cc=utilityemal77@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.