当前位置:首页 > 文章列表 > 文章 > linux > Linux Landlock 怎样限制普通进程访问文件目录

Linux Landlock 怎样限制普通进程访问文件目录

来源:17golang原创 2026-10-09 21:20:56 0浏览 收藏

普通 Linux 进程可以用 Landlock 主动限制自己能访问的文件目录,而且不必先取得 root 权限。做法是:声明要由 Landlock 处理的文件操作,创建规则集,为允许访问的目录添加 PATH_BENEATH 规则,再设置 no_new_privs 并调用 landlock_restrict_self()。规则生效后无法撤销,只能继续叠加更严格的限制。

官方文档:https://docs.kernel.org/userspace-api/landlock.html

要点速览
  • Landlock 是进程“自我收紧”的安全层,不会绕过 DAC、ACL 或其他 LSM,也不会授予新权限。
  • handled_access_fs 决定哪些操作进入规则集的默认拒绝范围,目录规则只为指定层级放行其中一部分权限。
  • 普通进程通常先设置 PR_SET_NO_NEW_PRIVS,再对当前线程施加规则集。
  • 策略会被后续创建的子线程和子进程继承;已有兄弟线程不会自动获得经典单线程调用施加的策略。

我更愿意把 Landlock 看成“进程内最小权限层”

第一次接触 Landlock 时,最容易把它理解成另一个文件权限系统。实际更准确的定位是:应用已经通过用户、组、ACL、SELinux 或 AppArmor 获得一组环境权限,Landlock 再从这组权限里减去应用当前阶段不需要的部分。它不能让进程读取原本无权读取的文件,也不会替代系统管理员配置的全局策略。

这种模式特别适合内容解析器、构建工具、插件宿主、文档转换器和网络服务中的受限工作阶段。例如,一个转换器需要只读系统运行库、读写自己的工作目录,却完全没有必要访问用户的 SSH 密钥。与其依赖“代码绝不会碰到”,不如让内核拒绝不在白名单层级内的已处理操作。

普通进程通过 Landlock 规则集声明文件权限并绑定只读和可写目录的静态结构图
图1:Landlock 规则集组成说明图,展示规则定义、允许目录与自我限制之间的静态关系,不是命令执行流程或运行截图。

规则集为什么要先声明 handled_access_fs

Landlock 不是把所有文件操作一次性变成默认拒绝,而是先由应用声明“哪些访问权由本规则集处理”。这些位组成 handled_access_fs。一旦某项权利被处理,没有匹配允许规则的文件层级就会拒绝该操作;没有纳入 handled 集合的操作则不受这一层规则集限制。

这也是为什么只写 READ_FILE 不能得到完整的“只读沙箱”。要限制目录遍历,还要考虑 READ_DIR;要限制覆盖文件,通常要同时处理 WRITE_FILE 与 TRUNCATE;要限制新建和删除,则要纳入相应的 MAKE_*、REMOVE_FILE 与 REMOVE_DIR。具体可用位受运行内核的 Landlock ABI 约束,应用应先查询 ABI,再按支持范围裁剪。

一个普通进程怎样建立只读和可写目录

下面的 C 示例把一个目录设为只读,把另一个目录设为可读写。它故意采用“内核不支持就退出”的闭合策略,适合把沙箱视为安全前提的程序;如果你的应用允许降级运行,应明确记录降级并让部署者选择,而不是悄悄假装已受保护。

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static int ll_create(const struct landlock_ruleset_attr *attr,
                     size_t size, __u32 flags) {
    /* 直接调用 Landlock 系统调用,返回规则集文件描述符或 ABI 版本 */
    return (int)syscall(SYS_landlock_create_ruleset, attr, size, flags);
}

static int ll_add(int ruleset_fd,
                  const struct landlock_path_beneath_attr *rule) {
    /* PATH_BENEATH 规则把允许权限绑定到一个目录层级 */
    return (int)syscall(SYS_landlock_add_rule, ruleset_fd,
                        LANDLOCK_RULE_PATH_BENEATH, rule, 0);
}

static int ll_restrict(int ruleset_fd) {
    /* flags 为 0,采用广泛兼容的经典自我限制方式 */
    return (int)syscall(SYS_landlock_restrict_self, ruleset_fd, 0);
}

static int add_path_rule(int ruleset_fd, const char *path,
                         __u64 allowed_access) {
    int path_fd = open(path, O_PATH | O_CLOEXEC);
    if (path_fd  \n", argv[0]);
        return 2;
    }

    /* 先查询运行内核支持的 Landlock ABI,避免盲用新权限位 */
    int abi = ll_create(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
    if (abi = 2)
        write_access |= LANDLOCK_ACCESS_FS_REFER;
    if (abi >= 3)
        write_access |= LANDLOCK_ACCESS_FS_TRUNCATE;

    struct landlock_ruleset_attr attr = {
        .handled_access_fs = read_access | write_access,
    };
    int ruleset_fd = ll_create(&attr, sizeof(attr), 0);
    if (ruleset_fd 

代码中的两个目录都只是调用者传入的示例边界。真实应用还要把动态库、配置、证书、时区数据、插件目录等运行依赖纳入设计。我的取舍是先列出业务阶段实际需要的目录,再逐个授予最小权限;若一开始直接允许整个主目录,Landlock 的收益会迅速变小。

限制自身之前,三个调用各自负责什么

调用职责失败时的含义
landlock_create_ruleset()查询 ABI 或创建包含 handled 权限的规则集内核不支持、功能被禁用或参数与 ABI 不匹配
landlock_add_rule()把允许权限关联到打开的目录层级目录锚点、权限位或规则类型无效
landlock_restrict_self()把规则集叠加到当前线程的 Landlock 域no_new_privs、能力、规则集或 flags 条件不满足

策略成功施加后没有“撤销”按钮。后续规则层只能继续收紧,子线程和子进程会继承父线程已经进入的 Landlock 域。这个不可逆特性正是安全价值的一部分,也意味着初始化顺序必须在架构设计阶段确定。

Landlock 只会收紧,不能抬高原有权限

某次文件访问最终能否成功,不只取决于 Landlock。传统 DAC、ACL、其他 LSM 与每一层 Landlock 策略都必须允许。Landlock 规则允许读取某目录,并不代表进程可以越过文件所有者和模式位;反过来,即使 DAC 允许,Landlock 也可以拒绝。

DAC 其他 LSM 和多层 Landlock 共同决定新文件访问结果的静态关系图
图2:多层权限交集说明图,展示现有访问控制与 Landlock 层共同约束新文件访问;这不是运行结果或性能数据。

这种叠加模型让我觉得 Landlock 更像应用自带的“最后一道围栏”,而不是系统权限的替代方案。它很适合把安全意图随程序一起交付:应用最清楚自己在解析、构建或转换阶段需要哪些目录,管理员则继续控制主机级权限。

四个反例会让沙箱看起来比实际更强

施加策略前已经打开敏感文件

Landlock 文件访问检查主要发生在打开或操作对象的相关时点。官方文档明确提醒,沙箱前已打开的文件不受后续路径访问规则的同等限制。进入沙箱前应关闭不需要的文件描述符,并审查从父进程继承或通过 IPC 传入的描述符。

多线程程序只限制了其中一个线程

经典 landlock_restrict_self() 针对调用线程及其后代。已经存在的父线程或兄弟线程不会自动被同一调用限制。最稳妥的架构是在创建工作线程前施加策略,或者依据运行 ABI 研究并采用官方支持的线程同步限制能力,而不是假设“限制一个线程等于限制整个进程”。

忽略 ABI,直接使用当前头文件的所有权限位

编译环境的头文件可能比运行内核新。应用应查询 ABI,并仅把运行内核支持的权限纳入 handled 与 allowed 集合。官方推荐 best-effort 兼容模式;安全关键程序则可以在缺少必需能力时明确拒绝启动。无论选择哪种,都要让行为可观察。

白名单目录过大

把 /home、/etc 或根目录整体加入规则,虽然省事,却会让策略失去最小权限价值。官方建议尽可能把权限授予文件层级叶子:只读文档目录与可写临时目录分开,比给父目录宽权限再期待子目录“更严格”更容易维护。

什么时候值得采用 Landlock

  • 应用能清楚列出当前阶段需要读取、执行、创建和修改的目录。
  • 策略可以在打开敏感资源、创建线程或加载不可信输入前建立。
  • 团队愿意按运行内核 ABI 处理兼容,并明确决定不支持时是降级还是拒绝运行。
  • 目标是降低应用漏洞的文件系统影响面,而不是替代身份、容器、seccomp 或主机级 LSM。
  • 可以为白名单外访问失败准备清晰日志,并把依赖目录变化纳入回归检查。

常见问题

普通用户真的可以使用 Landlock 吗?

可以。Landlock 的目标之一就是让无特权进程安全地限制自身。普通进程通常需要先设置 no_new_privs,而运行内核也必须启用并支持 Landlock。

Landlock 能让程序读取原本无权访问的目录吗?

不能。它只会收紧权限,现有 DAC、ACL 和其他 LSM 仍然生效,所有相关层都允许时访问才可能成功。

规则生效后还能删除或放宽吗?

不能放宽。进入 Landlock 域后只能继续叠加更严格的规则层,这也是初始化顺序需要提前设计的原因。

为什么白名单外仍能操作某个已打开文件?

先检查该文件描述符是否在施加策略前就已打开或从其他进程传入。Landlock 不是自动关闭已有能力的文件描述符清理器,敏感描述符必须在沙箱前处理。

如果把 Landlock 视为“应用自己声明的附加最小权限层”,设计会清楚很多:先确认运行 ABI,再声明要处理的访问权,为必要目录添加最小允许规则,关闭多余资源,最后在正确的线程时机不可逆地限制自身。它的价值不在于取代所有安全机制,而在于让普通进程也能主动缩小文件系统攻击面。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
用 http.Protocols 控制反向代理上游协议用 http.Protocols 控制反向代理上游协议
上一篇
用 http.Protocols 控制反向代理上游协议
Web Locks API 的等待请求如何支持用户主动取消
下一篇
Web Locks API 的等待请求如何支持用户主动取消
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    395次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    474次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    479次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    424次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    250次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码