Landlock update v1.0.0 - #16005
Open
regit wants to merge 27 commits into
Open
Conversation
In the case of --set=foo.0=bar, the 0 was not creating a sequence if ever the sequence is not existing. Ticket: 8606
A YAML sequence of single key maps, such as `outputs`, stores its entries at outputs.<n>.<name> so a direct lookup of outputs.<name> never matches. Add SCConfNodeLookupInSequence() to walk such a sequence and return the entries matching a given name. Ticket: 8606
The landlock read and write path helpers were static and only usable from the sandboxing function itself. Rename them to the SC prefixed public API and declare them in the header so that other parts of the engine, and later plugins and output modules, can declare the paths they need before the sandbox is enforced. The ruleset is passed as an opaque void pointer to avoid exposing the landlock internal structure to callers, and the helpers are no-op when landlock is not available so they can be called unconditionally. Ticket: 8606
Landlock gained network access control in ABI version 4 (Linux 6.7), allowing to restrict TCP bind and connect to a set of ports. Handle the network access rights in the ruleset and add two helpers, SCLandlockGrantNetBindTCP() and SCLandlockGrantNetConnectTCP(), so that the components needing to bind or connect a socket can declare the port they use before the sandbox is enforced. The ABI check is turned into a switch as the number of features depending on the kernel version is growing: the network access rights are removed from the ruleset when running on a kernel with an ABI lower than 4. Ticket: 8606
Recent kernels added filesystem access rights that were not handled by the ruleset: LANDLOCK_ACCESS_FS_TRUNCATE (ABI 3), IOCTL_DEV (ABI 5) and RESOLVE_UNIX (ABI 9). As they are not part of the handled access, they were simply allowed, weakening the sandbox. Add them to the write access set and extend the ABI switch to remove the ones that are not known by the running kernel. Asking for an access right the kernel does not know makes the ruleset creation fail, so a missing case here would disable the sandbox instead of loosening it. Ticket: 8606
A plugin opening a file or a socket is denied by the sandbox as it has no way to declare the accesses it needs. Add an optional LandlockEnable callback to the SCPlugin structure: it is called on every loaded plugin just before the ruleset is enforced and the plugin can use the SCLandlockGrant* helpers to declare what it needs to work properly. The plugin API version is bumped as the SCPlugin structure is modified. Ticket: 8606
Output modules write to files or sockets that are not necessarily under the default log directory, and the sandbox has no way to know about them. Add an optional LandlockEnable callback to OutputModule which is called on every registered output module just before the ruleset is enforced, so a module can grant the accesses it needs with the SCLandlockGrant* helpers. Ticket: 8606
Iterating over the outputs sequence to find every enabled instance of a given output is needed by each module implementing a LandlockEnable callback. Provide it once in util-landlock.c so no module has to walk the sequence itself and get the outputs.<n>.<name> shape wrong. Ticket: 8606
As the plugin may not implement correctly landlock, user has a way to override the configuration. Ticket: 8606
Some paths in dev, sys, proc were needed to get Suricata function properly. Fallback was working but we were loosing some features there. These are the paths glibc, jemalloc and the Rust standard library read during startup and runtime. Granting them read access avoids spurious EACCES errors and the Landlock audit noise coming with them without widening the sandbox in a meaningful way as any process on the system can already read them. Ticket: 8606
This patch triggers Landlock sandboxing earlier. This is useful as the sandboxing is now applied before output is initiated which triggers network and file access. Thus restriction apply from the start and not at file reopening. This is safer and should allow better debugging in case of problem. Ticket: 8606
In the case the implementation of plugins is not trusted, the new `plugin-setup` option can be used to disallow plugin to set up their sandboxing. Ticket: 8606
This patch adds the function needed to add to Landlock ruleset what is needed for the module to function properly. Ticket: 8606
This patch adds configuration for Landlock in eve including for new network capabilities linked to redis. Ticket: 8606
In profiling modules, the setting `append: no` is using truncate() call which are prevented by landlock. This patch adds a new utility SCLandlockGrantFile which allows a module to ask for truncate on a specific file. By using a file as parameter, we will avoid any unwanted truncation (for example of eve.json). It also add a new helper to register file permission at init before landlock sandbox is created. Ticket: 8606
The classification and reference files need read access. The access is granted per file as classification.config, reference.config and threshold.config can be set to a path outside of any of the granted directories. When the configuration key is not set, Suricata falls back to the compiled-in CONFIG_DIR default which is granted too if the file exists. Ticket: 8606
The file store writes its files under a temporary directory and renames them into the final tree, which requires LANDLOCK_ACCESS_FS_REFER on the file store directory. As the rules are attached to an existing inode, the directory is also created if it does not exist yet. Ticket: 8606
It is using write that does an implicit truncate so we need to add truncate capability in the dataset directory. Datasets declared in the configuration have a known state file so the truncate permission is set on this file only. Rules can declare their own dataset and their files are not known when the sandbox is set up, so the permission is set on the data directory. This is only done if datasets.rules.allow-write is not disabled as it is the setting deciding whether such rules are loaded at all. Ticket: 8606
This write permission was too lax as it was including the right to remove a file. As we don't want Suricata to be able to remove files that it has written (like eve.json) to cover traces we should not allow this. As a result, a new function providing write and remove has been added. It is, for example, necessary to use this for log-pcap or PID file. Ticket: 8606
The access is asked for on the file itself and not on the parent directory as `filename: /dev/null` is a common way to enable the module while discarding its output and granting write access on the whole /dev would widen the sandbox for no reason. Ticket: 8606
Ticket: 8606
The firewall rule file (--firewall-rules-exclusive) is loaded from the path as provided so an absolute one can be outside of every directory granted by the sandbox. It is thus granted per file. A relative path is resolved against firewall.rule-path which is already granted as a directory. Ticket: 8606
This is needed to be able to get for example dataset saving state in custom directories. Truncation is not part of the default write access as zeroing a file is an anti-forensics primitive, so it has to be asked for explicitly on a directory owned by the caller. Ticket: 8606
Run S-V with landlock enable. Ticket: 8606
struct landlock_ruleset_attr gained the scoped field in Linux 6.12 (Landlock ABI 6) and handled_access_net in Linux 6.7 (ABI 4). Missing constants can be defined by hand, a struct member cannot, so both need their own configure check and the code using them has to be guarded. Ticket: 8606
A directory listed in the configuration that does not exist on the system is not an error, there is simply nothing to grant. This is for example the case of the sysconfdir when Suricata is run from a build tree. Anything else than ENOENT is still reported as a warning. Ticket: 8606
Also just allow sockets usage in socket dirs. File removal, truncation and socket creation are not part of the default write access anymore. Removal and truncation are classic anti-forensics primitives, unlinking or zeroing logs and state files to erase traces, and socket creation is only needed by the unix command socket as connecting to an existing socket does not require it. The subsystems legitimately needing one of them now ask for it on the directory or the file they own. Directory creation stays in as creating a subdirectory on the fly is common enough (tls-store certs directory, a log filename holding a path, the Hyperscan cache) that removing it would only push the same grant into most of the callers. Ticket: 8606
regit
requested review from
jasonish,
jufajardini and
victorjulien
as code owners
August 11, 2026 08:23
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #16005 +/- ##
==========================================
- Coverage 83.01% 82.88% -0.13%
==========================================
Files 1001 1002 +1
Lines 276611 277000 +389
==========================================
- Hits 229616 229600 -16
- Misses 46995 47400 +405
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Contributor
Author
|
Regarding coverage, I think we can improve it if the S-V run with landlock added in this PR is in coverage. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR updates Landlock support to latest Landlock capabilities and introduces mechanism to have plugins and output module to declare themselves to Landlock. A new Github workflow has been added to run S-V with Landlock enable. This has been instrumental in finding issues in the Landlock sandboxing.
Contribution style:
https://docs.suricata.io/en/latest/devguide/contributing/contribution-process.html
Our Contribution agreements:
https://suricata.io/about/contribution-agreement/ (note: this is only required once)
Changes (if applicable):
(including schema descriptions)
https://redmine.openinfosecfoundation.org/projects/suricata/issues
Link to ticket: https://redmine.openinfosecfoundation.org/issues/8606
Describe changes:
SV_BRANCH=OISF/suricata-verify#3269