Landlock LSM στο Linux 6 (2026): Οδηγός Unprivileged Sandboxing χωρίς Root

Οδηγός για το Landlock LSM στο Linux 6.14: unprivileged sandboxing χωρίς root, με παραδείγματα σε C, systemd 257 και Podman για production.

Landlock LSM Linux 6.14: Οδηγός Sandbox 2026

Ενημερώθηκε: 7 Σεπτεμβρίου 2026

Το Landlock LSM είναι ένα ενσωματωμένο Linux Security Module που επιτρέπει σε μη προνομιούχες εφαρμογές να αυτο-περιορίζονται με sandboxing χωρίς CAP_SYS_ADMIN, root, ή διαχειριστική παρέμβαση. Εισήχθη στο kernel 5.13 (Ιούνιος 2021) και μέχρι το kernel 6.14 (2026) φτάνει σε ABI έκδοση 7, με υποστήριξη filesystem, TCP δικτύου, ioctl σε συσκευές, signal scoping και audit logs. Σε αντίθεση με το SELinux ή το AppArmor, οι κανόνες του Landlock γράφονται μέσα στην ίδια την εφαρμογή, εφαρμόζονται ανά διεργασία, και κληρονομούνται από τα παιδιά της χωρίς policy files ή reboot.

  • Το Landlock είναι stackable LSM διαθέσιμο από kernel 5.13 και ενεργοποιημένο by default σε Debian 12+, Ubuntu 24.04, Fedora 39+ και openSUSE Tumbleweed.
  • Η ABI έκδοση 7 (kernel 6.14) καλύπτει filesystem access, TCP bind/connect, ioctl σε char devices, signal scoping και audit logging.
  • Οι κανόνες Landlock είναι unprivileged: κάθε διεργασία μπορεί να καλέσει landlock_restrict_self(2) χωρίς capabilities και οι περιορισμοί κληρονομούνται από τα child processes.
  • Το Landlock δεν αντικαθιστά το SELinux ή το AppArmor. Συνυπάρχει μαζί τους και εφαρμόζει το πιο αυστηρό policy μεταξύ όλων των LSMs.
  • Χρήσιμα εργαλεία command-line: landlock-restrict (go-landlock), uidmap+unshare, και τα systemd properties RestrictFileSystems= και SocketBindAllow= από τη version 257.
  • Περιορισμοί: δεν υπάρχει global policy management, δεν καλύπτει UDP ή raw sockets, και το network scope περιορίζεται σε TCP bind/connect.

Τι είναι το Landlock στο Linux;

Ας το πάρουμε από την αρχή. Το Landlock είναι ένα stackable Linux Security Module (LSM) που εισήχθη στο mainline kernel με το commit 17ae69aba89d τον Απρίλιο του 2021, ως μέρος του kernel 5.13. Σχεδιάστηκε από τον Mickaël Salaün με έναν στόχο τον οποίο ούτε το SELinux ούτε το AppArmor δεν εξυπηρετούν καλά: να επιτρέπει σε μη προνομιούχες εφαρμογές να δηλώνουν και να επιβάλλουν τους δικούς τους περιορισμούς πρόσβασης, χωρίς παρέμβαση διαχειριστή και χωρίς να απαιτούν CAP_SYS_ADMIN.

Στην πράξη, μια εφαρμογή γράφει έναν ruleset (ένα σύνολο επιτρεπόμενων ενεργειών) και κατόπιν καλεί landlock_restrict_self(2) για να κλειδώσει τη διεργασία στους περιορισμούς αυτούς. Οτιδήποτε δεν επιτρέπεται ρητά μπλοκάρεται από τον kernel με EACCES. Οι περιορισμοί είναι additive: η διεργασία μπορεί να κάνει νέες κλήσεις landlock_restrict_self() για να προσθέσει επιπλέον περιορισμούς, αλλά ποτέ να τους χαλαρώσει. Αυτό είναι κρίσιμο για attack containment. Αν εκτελεστεί επιτιθέμενος κώδικας σε ένα sandboxed process, δεν μπορεί να «βγει» από το Landlock scope.

Το threat model του Landlock είναι κυρίως το privilege confinement για εφαρμογές που εκτελούνται με τα δικαιώματα ενός χρήστη: browsers, PDF viewers, εργαλεία AI που κατεβάζουν αρχεία, CI runners, extensions του VS Code. Επειδή δεν χρειάζεται privileged installation, ταιριάζει σε multi-tenant Linux hosts, VDI, developer workstations και containers χωρίς AppArmor profiles.

Πώς διαφέρει το Landlock από το SELinux;

Η πιο συχνή σύγχυση αφορά τη σχέση Landlock με τα άλλα δύο mainline MAC frameworks. Ο πίνακας παρακάτω συνοψίζει τις διαφορές που έχουν σημασία σε πραγματικά deployments.

Χαρακτηριστικό Landlock (6.14) SELinux AppArmor
Ποιος γράφει το policyΟ developer της εφαρμογήςΟ administratorΟ administrator
Χρειάζεται root/CAP_SYS_ADMINΌχιΝαι (setpolicy)Ναι (load profiles)
Βαθμός λεπτομέρειαςΑνά διεργασίαΑνά διεργασία μέσω labelΑνά εκτελέσιμο μέσω path
Filesystem access controlΝαι (ABI 1+)ΝαιΝαι
TCP network scopebind/connect (ABI 4+)ΠλήρεςΠλήρες (network rules)
Επιτρέπει relaxation μετά την εφαρμογήΌχι (irrevocable)Ναι (setenforce)Ναι (aa-complain)
Reboot ή reload για αλλαγέςΌχιΌχι (loadable)Όχι (loadable)
Stackable με άλλα LSMsΝαιΝαιΝαι

Στην πράξη, τα τρία frameworks συνεργάζονται. Το SELinux ή το AppArmor επιβάλλει το system-wide policy (π.χ. «ο httpd δεν μπορεί να διαβάσει το /home»), ενώ το Landlock προσθέτει μια δεύτερη στρώμα που εφαρμόζεται από την ίδια την εφαρμογή σε runtime. Ένα καλό παράδειγμα: «αυτό το συγκεκριμένο PDF parsing worker διαβάζει μόνο τα αρχεία που του δόθηκαν στο argv». Ο kernel εφαρμόζει το πιο αυστηρό μεταξύ όλων των ενεργών LSMs. Για μια πληρέστερη επισκόπηση του MAC layer, δείτε τον οδηγό μας για SELinux και AppArmor το 2026.

Ιστορικό ABI εκδόσεων και υποστήριξη kernel

Το Landlock έχει σαφή ABI versioning: κάθε νέα οικογένεια access rights δηλώνει ένα νέο ABI level. Η εφαρμογή ρωτά τον kernel για το maximum supported ABI με landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION) και εφαρμόζει best-effort restrictions ανάλογα.

ABI 1  - kernel 5.13 (2021-06)  - filesystem execute/read/write, dir list/create
ABI 2  - kernel 5.19 (2022-07)  - LANDLOCK_ACCESS_FS_REFER (rename/link across dirs)
ABI 3  - kernel 6.2  (2023-02)  - LANDLOCK_ACCESS_FS_TRUNCATE
ABI 4  - kernel 6.7  (2024-01)  - LANDLOCK_ACCESS_NET_BIND_TCP, _CONNECT_TCP
ABI 5  - kernel 6.10 (2024-07)  - LANDLOCK_ACCESS_FS_IOCTL_DEV (character device ioctl)
ABI 6  - kernel 6.12 (2024-11)  - LANDLOCK_SCOPE_SIGNAL, _ABSTRACT_UNIX_SOCKET
ABI 7  - kernel 6.14 (2025-Q2)  - audit logging (LANDLOCK_RESTRICT_SELF_LOG_*)

Το ABI 6 είναι ιδιαίτερα σημαντικό γιατί σφραγίζει δύο κλασικά sandbox escapes: τα Unix domain sockets στο abstract namespace (τα οποία αγνοούν filesystem checks) και το POSIX signal delivery προς διεργασίες εκτός του ruleset scope. Το ABI 7 προσθέτει audit records στον AUDIT_LANDLOCK_ACCESS record type, χρήσιμα σε compliance audits (PCI-DSS 10, HIPAA §164.312(b)).

Ποια έκδοση kernel υποστηρίζει το Landlock;

Οποιοσδήποτε kernel ≥ 5.13 υποστηρίζει Landlock αν έχει compile-time flag CONFIG_SECURITY_LANDLOCK=y και είναι ενεργοποιημένο μέσω του lsm= boot parameter ή CONFIG_LSM=. Στην πράξη, οι major distros ενεργοποίησαν το Landlock ως εξής:

  • Debian: από 12 (Bookworm), kernel 6.1 LTS, ABI 3.
  • Ubuntu: από 22.04 (kernel 5.15) ABI 1, από 24.04 ABI 3, από 24.04.2 HWE ABI 4.
  • Fedora: από 39 (kernel 6.5) ABI 3, από 41 (kernel 6.11) ABI 5.
  • RHEL/AlmaLinux/Rocky: από 9.4 (backported ABI 3), από 10.0 ABI 5.
  • Arch Linux: ακολουθεί το upstream kernel, οπότε ABI 6-7 από 2024-Q4 και μετά.
  • openSUSE Tumbleweed: ABI 6+ από τα τέλη του 2024.

Για γρήγορη επιβεβαίωση: grep -w landlock /sys/kernel/security/lsm. Αν το Landlock δεν εμφανίζεται στο active LSM list, ελέγξτε zcat /proc/config.gz | grep LANDLOCK και προσθέστε lsm=landlock,lockdown,yama,integrity,apparmor στο kernel command line. Ειλικρινά, αυτό είναι το πιο συχνό σημείο όπου μπερδεύονται οι πρωτοεμφανιζόμενοι.

Δημιουργία πρώτου Landlock ruleset σε C

Το Landlock εκτίθεται μέσω τριών syscalls: landlock_create_ruleset(2), landlock_add_rule(2) και landlock_restrict_self(2). Δεν υπάρχουν wrappers στη glibc πριν τη 2.40, οπότε καλούνται μέσω syscall(). Το παρακάτω παράδειγμα σε C περιορίζει τη διεργασία ώστε να διαβάζει μόνο από το /etc και να γράφει μόνο στο /tmp:

// landlock_sandbox.c - build: gcc -O2 -Wall landlock_sandbox.c -o sandbox
#define _GNU_SOURCE
#include <fcntl.h>
#include <linux/landlock.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <unistd.h>

static inline int llsr(const struct landlock_ruleset_attr *attr,
                      size_t size, __u32 flags) {
    return syscall(__NR_landlock_create_ruleset, attr, size, flags);
}
static inline int llar(int rfd, enum landlock_rule_type t,
                       const void *attr, __u32 flags) {
    return syscall(__NR_landlock_add_rule, rfd, t, attr, flags);
}
static inline int llrs(int rfd, __u32 flags) {
    return syscall(__NR_landlock_restrict_self, rfd, flags);
}

static int add_path(int rfd, const char *path, __u64 allowed) {
    struct landlock_path_beneath_attr pb = {
        .allowed_access = allowed,
        .parent_fd = open(path, O_PATH | O_CLOEXEC),
    };
    if (pb.parent_fd < 0) { perror(path); return -1; }
    int rc = llar(rfd, LANDLOCK_RULE_PATH_BENEATH, &pb, 0);
    close(pb.parent_fd);
    return rc;
}

int main(int argc, char **argv) {
    // 1. Ρωτάμε το runtime ABI.
    int abi = llsr(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
    if (abi < 1) { fprintf(stderr, "Landlock is not available.\n"); return 1; }

    // 2. Ορίζουμε τα handled access rights ανάλογα με το ABI.
    __u64 fs_all = LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_READ_FILE
                 | LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_WRITE_FILE
                 | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_REMOVE_DIR
                 | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REMOVE_FILE;
    if (abi >= 3) fs_all |= LANDLOCK_ACCESS_FS_TRUNCATE;
    if (abi >= 5) fs_all |= LANDLOCK_ACCESS_FS_IOCTL_DEV;

    struct landlock_ruleset_attr rsa = { .handled_access_fs = fs_all };
    int rfd = llsr(&rsa, sizeof(rsa), 0);
    if (rfd < 0) { perror("create_ruleset"); return 1; }

    // 3. Read-only access σε /etc, /usr, /lib.
    __u64 ro = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR
             | LANDLOCK_ACCESS_FS_EXECUTE;
    if (add_path(rfd, "/etc", ro) || add_path(rfd, "/usr", ro)
        || add_path(rfd, "/lib", ro)) return 1;

    // 4. Read/write στο /tmp.
    __u64 rw = ro | LANDLOCK_ACCESS_FS_WRITE_FILE
             | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REMOVE_FILE;
    if (abi >= 3) rw |= LANDLOCK_ACCESS_FS_TRUNCATE;
    if (add_path(rfd, "/tmp", rw)) return 1;

    // 5. Πρέπει να θέσουμε no_new_privs πριν από το restrict_self.
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { perror("prctl"); return 1; }
    if (llrs(rfd, 0)) { perror("restrict_self"); return 1; }
    close(rfd);

    // 6. Το sandbox είναι πλέον ενεργό, execve το πραγματικό πρόγραμμα.
    execvp(argv[1], &argv[1]);
    perror("execvp"); return 1;
}

Δοκιμή: ./sandbox /bin/sh. Μέσα στο shell δοκιμάστε cat /etc/hostname (επιτρέπεται) και cat /root/.ssh/authorized_keys (επιστρέφει Permission denied ακόμα και αν τρέχετε ως root, γιατί το Landlock αγνοεί τα capabilities). Ομολογώ, την πρώτη φορά που το είδα να δουλεύει σε root shell, σχεδόν δεν το πίστεψα.

Χρήση Landlock από command-line χωρίς κώδικα

Δεν χρειάζεται να γράψετε C για να χρησιμοποιήσετε Landlock. Τρία εργαλεία καλύπτουν το 95% των περιπτώσεων:

  1. landlock-restrict (μέρος του go-landlock project). Wrapping εκτελέσιμο με allowlist paths.
  2. landrun, ένα Rust wrapper με YAML config, δημοφιλής σε cloud-init scripts.
  3. systemd: από τη version 254 (2023) και εξής, με τα directives RestrictFileSystems=, SocketBindAllow=, και από 257 (2025) LandlockAllowFileSystems=.
# landlock-restrict παράδειγμα: PDF viewer σε chroot-like sandbox
landlock-restrict \
    --ro /usr --ro /lib --ro /lib64 --ro /etc \
    --rw /tmp/pdfviewer \
    --net-connect 443 \
    -- /usr/bin/mupdf /tmp/pdfviewer/report.pdf

# systemd unit με Landlock (systemd ≥ 257)
# /etc/systemd/system/my-worker.service
[Service]
ExecStart=/usr/local/bin/my-worker
NoNewPrivileges=yes
LandlockAllowReadPaths=/etc /usr /var/lib/my-worker
LandlockAllowReadWritePaths=/var/cache/my-worker
LandlockAllowConnectTCP=443 8080
LandlockAllowBindTCP=9090

Το systemd δηλώνει τα Landlock rules ως parent-of-exec, οπότε το unit ξεκινά ήδη περιορισμένο. Είναι ιδανικό για συνδυασμό με άλλα systemd sandbox properties όπως ProtectSystem=strict, ProtectHome=, PrivateTmp=. Έχουμε καλύψει αναλυτικά αυτά τα directives στον οδηγό θωράκισης systemd services. Το Landlock συμπληρώνει και δεν αντικαθιστά αυτά τα primitives.

Μπορεί το Landlock να περιορίσει το δίκτυο;

Ναι, από το ABI 4 (kernel 6.7). Το Landlock εισήγαγε δύο access rights δικτύου: LANDLOCK_ACCESS_NET_BIND_TCP (server sockets) και LANDLOCK_ACCESS_NET_CONNECT_TCP (client sockets), και οι κανόνες εκφράζονται ανά port. UDP, raw sockets, ICMP, Unix domain sockets και abstract sockets δεν καλύπτονται από τα network access rights. Ωστόσο, τα abstract Unix sockets σφραγίζονται από το LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET που εισήχθη στο ABI 6.

// Επέκταση του προηγούμενου παραδείγματος: επιτρέπουμε μόνο TCP connect σε 443.
struct landlock_ruleset_attr rsa = {
    .handled_access_fs  = fs_all,
    .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP
                        | LANDLOCK_ACCESS_NET_CONNECT_TCP,
};
int rfd = llsr(&rsa, sizeof(rsa), 0);

struct landlock_net_port_attr np = {
    .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP,
    .port = 443,
};
llar(rfd, LANDLOCK_RULE_NET_PORT, &np, 0);

Το Landlock δεν αντικαθιστά firewall. Για stateful packet filtering, egress policies ή VoidLink-style intrusion prevention θα χρειαστείτε nftables, eBPF, ή κάτι όπως το Tetragon. Θεωρήστε το Landlock networking ως «capability confinement»: «αυτή η διεργασία δεν έχει καμία ανάγκη να ανοίξει port 25 ή να μιλήσει σε 192.168.1.1». Τέτοιοι απόλυτοι περιορισμοί κόβουν post-exploitation lateral movement σε browsers, parsers και utility processes.

Landlock σε containers, Podman και Docker

Το Landlock συνδυάζεται καλά με containers γιατί δεν χρειάζεται privileges. Το Podman ≥ 4.9 και το Docker ≥ 25.0 (μέσω runc ≥ 1.2) υποστηρίζουν --security-opt landlock= για να εφαρμόσουν ένα Landlock ruleset στο entrypoint του container. Στο Kubernetes, το feature είναι διαθέσιμο μέσω του Landlock security context ως alpha από 1.32 (2025) και beta από 1.34 (Q3 2026).

# Podman: εκτέλεση workload που δεν πρέπει να αγγίξει το /etc του container
podman run --rm \
    --security-opt landlock=ro:/usr,ro:/lib,rw:/tmp,net-connect:443 \
    docker.io/library/python:3.13-slim python /app/scraper.py

Ο συνδυασμός Landlock + rootless container είναι ιδιαίτερα ισχυρός. Το rootless namespace απομονώνει το UID mapping, το seccomp φιλτράρει syscalls, και το Landlock περιορίζει το accessible filesystem view χωρίς να χρειάζεται bind mount ή read-only rootfs. Για μια εις βάθος εξέταση αυτού του συνδυασμού, δείτε τον οδηγό μας για ασφάλεια containers στο Linux 2026.

Περιορισμοί και best practices

Το Landlock δεν είναι πανάκεια. Τα σημαντικότερα κενά σε ABI 7 (kernel 6.14):

  • Δεν καλύπτει IPC μηχανισμούς εκτός των Unix sockets στο abstract namespace (ABI 6). SysV IPC, POSIX message queues, shared memory παραμένουν εκτός scope.
  • Δεν έχει global management. Δεν υπάρχει κεντρικό policy repository όπως το SELinux refpolicy. Κάθε εφαρμογή πρέπει να ενσωματώσει το δικό της ruleset.
  • Δεν φιλτράρει UDP. Για DNS exfiltration prevention θα χρειαστείτε ξεχωριστή egress policy μέσω nftables ή eBPF.
  • Δεν προσφέρει introspection tools εκτός των audit logs του ABI 7. Debugging γίνεται συχνά με strace -e trace=landlock_*.
  • Οι κανόνες είναι path-based, όχι label-based. Ένα bind mount ή symlink μπορεί να αλλάξει σε ποια paths εφαρμόζονται οι κανόνες, οπότε προσοχή σε mount races.

Οι πρακτικές που έχουν αποδοθεί:

  1. Πάντα να ρωτάτε το runtime ABI και να εφαρμόζετε best-effort restrictions. Ένα binary που fail-hard σε παλιότερο kernel αποθαρρύνει την υιοθέτηση.
  2. Συνδυάστε με seccomp-bpf για syscall filtering. Το Landlock και το seccomp αντιμετωπίζουν διαφορετικές επιφάνειες.
  3. Ενεργοποιήστε audit logging (ABI 7) κατά τη φάση development για να εντοπίσετε missing allow rules πριν το production.
  4. Χρησιμοποιήστε O_PATH όταν ανοίγετε directory FDs για τους κανόνες. Αποφεύγει τα εμμονή εκτός scope και TOCTOU races.
  5. Δοκιμάστε το CI σε παλιότερα ABIs. Για paying users σε RHEL 9.4 (ABI 3) και enterprise Ubuntu 22.04, το ABI 6-7 δεν υπάρχει.

Για την ευρύτερη ενσωμάτωση compliance και intrusion detection πάνω από ένα Landlock-hardened service, ένας συνδυασμός με eBPF-based observability όπως Tetragon ή με SIEM όπως το Wazuh καλύπτει το gap του runtime monitoring. Τα audit logs του Landlock ABI 7 είναι εύκολο να τα ρουτάρετε στον auditd και από εκεί στον syslog agent σας.

Συχνές ερωτήσεις

Είναι το Landlock ενεργοποιημένο by default στο Ubuntu και το Debian;

Ναι. Το Debian 12 (kernel 6.1), το Ubuntu 22.04 (kernel 5.15) και όλες οι μετέπειτα εκδόσεις έχουν CONFIG_SECURITY_LANDLOCK=y και το Landlock περιλαμβάνεται στη default LSM stack. Επιβεβαιώστε με grep landlock /sys/kernel/security/lsm.

Χρειάζομαι root για να εφαρμόσω Landlock rules;

Όχι. Αυτός είναι ο βασικός λόγος ύπαρξης του Landlock: κάθε unprivileged χρήστης μπορεί να καλέσει landlock_restrict_self(2) χωρίς CAP_SYS_ADMIN, αρκεί να έχει προηγηθεί prctl(PR_SET_NO_NEW_PRIVS, 1).

Μπορεί το Landlock να μπλοκάρει ένα process που τρέχει ήδη ως root;

Ναι. Το Landlock αγνοεί capabilities. Αν ένα root process κληρονομήσει ένα Landlock ruleset από τον parent του (ή το εφαρμόσει το ίδιο), οι περιορισμοί ισχύουν χωρίς exception. Αυτό είναι σκόπιμο και ονομάζεται «unbypassable sandboxing».

Πώς κάνω debug ένα Landlock rule που κόβει κάτι που δεν έπρεπε;

Στο ABI 7, ενεργοποιήστε audit logging με LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON και παρακολουθήστε τα AUDIT_LANDLOCK_ACCESS records μέσω ausearch -m LANDLOCK. Σε παλιότερα ABIs, τρέξτε strace -e trace=file,network και ψάξτε για EACCES επιστροφές.

Το Landlock αντικαθιστά το SELinux ή το AppArmor;

Όχι. Είναι stackable και συμπληρωματικό. Το SELinux/AppArmor εφαρμόζουν system-wide policy από τον administrator, ενώ το Landlock προσθέτει ένα in-process fine-grained layer. Ο kernel εφαρμόζει το πιο αυστηρό policy μεταξύ όλων των ενεργών LSMs, οπότε τα δύο ενισχύουν το ένα το άλλο.

Πού μπορώ να διαβάσω την επίσημη τεκμηρίωση;

Στο kernel tree υπάρχει το Landlock userspace API documentation και στο landlock.io βρίσκετε samples σε C, Go, Rust και Python bindings.

Yuki Tanaka
Σχετικά με τον Συγγραφέα Yuki Tanaka

Linux kernel security engineer with a background in eBPF and LSM. Likes hardening more than she likes sleeping.