Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Libraries/LibSandbox/Seccomp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ static constexpr unsigned read_only_open_flags = O_CLOEXEC;
#define IF_DEFINED_unlinkat(if_defined, if_not_defined) if_defined
#define IF_DEFINED_umask(if_defined, if_not_defined) if_defined
#define IF_DEFINED_uname(if_defined, if_not_defined) if_defined
#define IF_DEFINED_utimensat(if_defined, if_not_defined) if_defined
#define IF_DEFINED_wait4(if_defined, if_not_defined) if_defined
#define IF_DEFINED_waitid(if_defined, if_not_defined) if_defined
#define IF_DEFINED_write(if_defined, if_not_defined) if_defined
Expand Down Expand Up @@ -472,6 +473,10 @@ static constexpr unsigned read_only_open_flags = O_CLOEXEC;
# undef IF_DEFINED_umask
# define IF_DEFINED_umask(if_defined, if_not_defined) if_not_defined
#endif
#ifndef __NR_utimensat
# undef IF_DEFINED_utimensat
# define IF_DEFINED_utimensat(if_defined, if_not_defined) if_not_defined
#endif
#ifndef __NR_wait4
# undef IF_DEFINED_wait4
# define IF_DEFINED_wait4(if_defined, if_not_defined) if_not_defined
Expand Down Expand Up @@ -685,6 +690,9 @@ static char const* syscall_name(long syscall_number)
#endif
#ifdef __NR_unlinkat
CASE_SYSCALL_NAME(unlinkat);
#endif
#ifdef __NR_utimensat
CASE_SYSCALL_NAME(utimensat);
#endif
default:
return "unknown";
Expand Down Expand Up @@ -855,6 +863,9 @@ void SeccompPolicy::allow_filesystem_writes()
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, fdatasync);
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, fallocate);
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, flock);
// NB: Mesa's shader disk cache updates entry mtimes for LRU eviction, and glibc routes the
// whole utime() family through utimensat() on modern kernels.
SECCOMP_APPEND_ALLOW_SYSCALL_IF_DEFINED(*this, utimensat);
Comment on lines +866 to +868

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Seccomp.cpp relevant section ==\n'
sed -n '820,900p' Libraries/LibSandbox/Seccomp.cpp

printf '\n== Search for utimensat and Landlock references ==\n'
rg -n "utimensat|utime|Landlock|restrict_filesystem_with_landlock|shader cache|filesystem-write" Libraries/LibSandbox -S

Repository: LadybirdBrowser/ladybird

Length of output: 5528


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Sandbox.cpp Landlock section ==\n'
sed -n '380,520p' Libraries/LibSandbox/Sandbox.cpp

printf '\n== Search utimensat call sites ==\n'
rg -n "\butimensat\b|\butime(ns)?\b" -S .

Repository: LadybirdBrowser/ladybird

Length of output: 7233


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== allow_filesystem_writes call sites ==\n'
rg -n "allow_filesystem_writes\(" Libraries/LibSandbox -S

printf '\n== Restrict filesystem call sites ==\n'
rg -n "restrict_filesystem_with_landlock\(" -S .

Repository: LadybirdBrowser/ladybird

Length of output: 1074


🌐 Web query:

Landlock utimensat utime family support handled_access_fs timestamp updates kernel documentation

💡 Result:

As of July 18, 2026, the Linux Landlock LSM does not support restricting the utime(2) family of system calls (which includes utimensat(2)) via the handled_access_fs mechanism [1][2][3]. Official kernel documentation explicitly states that it is currently not possible to restrict several file-related actions, including those accessible through utime(2), within a Landlock domain [1][2]. Consequently, operations that update file timestamps (such as utimes, utime, and utimensat) remain outside the scope of current Landlock filesystem access control bitmasks [1][3]. The documentation notes that future evolutions of Landlock are intended to enable the restriction of these syscalls [1][2][3].

Citations:


Authorization Bypass (CWE-863): Incorrect Authorization

Reachability: External

Keep utimensat() out of the shared filesystem-write policy
Landlock does not restrict the utime(2) family, so allowing raw utimensat() here lets a sandboxed process retimestamp any DAC-accessible path outside the Landlock-granted tree. If Mesa needs this for shader-cache eviction, broker it through trusted code that only targets the cache directory, or gate it behind a much narrower allowlist.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Libraries/LibSandbox/Seccomp.cpp` around lines 866 - 868, Remove the
utimensat entry from the shared filesystem-write policy in the seccomp policy
setup. Do not allow raw utimensat access globally; if Mesa shader-cache eviction
still requires timestamp updates, route them through trusted code restricted to
the cache directory or apply a narrowly scoped, cache-specific allowlist.


append(BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_fcntl, 0, 5));
append(SECCOMP_LOAD_ARGUMENT(1));
Expand Down