尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SerenityOS unveil(1) 命令指南:在受限路径白名单下安全运行任意命令

SerenityOS unveil(1) 命令指南:在受限路径白名单下安全运行任意命令 SerenityOS unveil(1) 命令指南在受限路径白名单下安全运行任意命令【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity导读unveil是 SerenityOS 提供的一个命令行工具它的核心作用是在启动一个目标程序之前预先通过unveil(2)系统调用为它设置文件系统访问白名单veil然后在受限环境下执行该程序。读完本文你将掌握unveil(1)的完整语法与参数格式、五种权限字符r/w/x/c/b的确切语义、它的底层系统调用实现原理以及如何在日常 Shell 操作中用它隔离那些你不完全信任的命令。命令概览unveil是什么unveil(1)是一个用于在受限路径下运行命令的工具。手册对其功能给出了一句非常精炼的定义Run a command under certain path restrictions by usingunveil(2)。也就是说它本身并不实现任何权限判断逻辑而是作为unveil(2)系统调用的命令行封装先通过系统调用为即将执行的程序搭建好路径白名单随后exec出真正的目标命令。其基本调用形式为$ unveil [--path] [command...]从实现上看该工具位于 Userland/Utilities/unveil.cpp其主流程非常清晰用Core::ArgsParser解析参数并在遇到第一个非选项参数后停止选项解析set_stop_on_first_non_option(true)从而保证目标命令自身的参数不会被误当作 unveil 的选项校验至少提供了一个--path否则直接报错No unveil paths were specified.逐个把permissions,path格式的字符串拆分为权限与路径两部分必须恰好拆成两段否则报Unveil path being specified is invalid.并调用Core::System::unveil_after_exec最终通过Core::System::exec在 PATH 中查找并执行目标命令。值得注意的细节是该工具使用的是unveil_after_exec对应内核中的UnveilFlags::AfterExec语义这些 unveil 设置并不会立刻套用到 unveil 进程自身而是被暂存下来在真正execve目标程序时一并生效从而让目标程序从一开始就运行在受限的 veil 之下。相关标志位定义可见 Kernel/API/Unveil.hCurrentProgram与AfterExec。选项详解unveil(1)的选项非常精简只有一个核心选项选项长选项说明-u--path解除unveil一个路径格式为permissions,path该选项可以重复使用任意多次每使用一次就向白名单中追加一条路径授权。手册原文对格式的说明是Unveil a path, with the format of permissions,path。在源码 Userland/Utilities/unveil.cpp 中可以看到--path的取值会被按逗号拆分为恰好两段parts[0]是权限字符串如r、rwparts[1]是绝对路径如/etc/timezone如果拆分结果不是恰好 2 段例如缺少逗号、路径中带多余逗号命令会直接报错退出而不会静默忽略。一个值得强调的约束来自底层系统调用unveil(2)要求路径必须是绝对路径以/开头否则返回EINVAL。这一点在 Kernel/Syscalls/unveil.cpp 中有直接校验。因此给unveil(1)传相对路径是无法生效的。权限字符语义r、w、x、c、bpermissions字段由若干权限字符组成可以一次性组合多个字符如rwc。五种字符的权威定义来自unveil(2)手册与内核实现完全一致字符含义手册原文内核对应标志Kernel/Syscalls/unveil.cpprMay read a file at this path可读取该路径下的文件UnveilAccess::ReadwMay write to a file at this path可写入该路径下的文件UnveilAccess::WritexMay execute a program image at this path可执行该路径下的程序映像UnveilAccess::ExecutecMay create or remove a file at this path可在该路径下创建或删除文件UnveilAccess::CreateOrRemovebMay browse directories at this path可浏览该路径下的目录UnveilAccess::Browse围绕这些权限手册与实现还给出了几条关键行为约束权限只会收紧不会放宽对同一个路径再次调用 unveil 时新权限只能是之前权限的子集。如果试图追加此前没有授予的权限系统调用会返回EPERM。在 Tests/Kernel/TestKernelUnveil.cpp 中这一行为有非常直白的测试佐证先unveil(/etc, r)成功随后再对其追加w、x、c均被拒绝。unveil 不替代常规权限检查即使进程对某路径 unveil 成功如果它本身没有相应的 Unix 文件权限owner/group/other访问依然会被拒绝。veil 只是白名单不是权限放大。目录 unveil 的递归性unveil 一个目录意味着进程可以访问该目录内的所有文件与子目录。c权限的特例为尚不存在的路径指定c权限是允许的进程打算稍后自己创建该文件。内核在路径解析遇到ENOENT时只要请求包含CreateOrRemove权限就会改用父目录的 custody 继续登记而不是直接报错这在 Tests/Kernel/TestKernelUnveil.cppunveil(/tmp/doesnotexist, c)必须成功与 Kernel/Syscalls/unveil.cpp 中均有体现。符号链接的处理unveil 针对的是解析后的真实路径符号链接目标同样受白名单约束。专门的符号链接测试位于 Tests/Kernel/unveil-symlinks.cpp。完整使用示例手册给出了两个可直接复制的实战示例以下完整保留并逐条解读。示例一在受限路径下运行ls -la /sys/kernel$ unveil --pathr,/etc/timezone --pathr,/usr/lib --pathr,/sys/ --pathr,/etc/passwd --pathr,/etc/group ls -la /sys/kernel该命令仅向白名单中登记了五个只读路径/etc/timezone、/usr/lib、/sys/、/etc/passwd、/etc/group。由于目标ls需要读取这些系统文件与目录才能正常完成对/sys/kernel的列目录操作这些授权刚好覆盖了它的最小需求而/sys/kernel之外的绝大多数文件系统区域对ls而言都是不可见的。示例二在受限路径下运行ps -ef$ unveil --pathr,/etc/timezone --pathr,/usr/lib --pathr,/sys/ --pathr,/etc/passwd --pathr,/etc/group ps -efps同样需要读取时区、动态库/usr/lib、系统信息/sys/以及用户账户映射/etc/passwd、/etc/group才能正确解析进程信息并打印完整格式输出因此白名单与示例一保持一致。两个示例的共同模式是先穷举目标程序正常运行所需的全部路径再以只读r方式逐条登记最后才执行命令。如果白名单漏掉某个路径目标程序访问该路径时会直接失败——这正是 unveil 作为能力最小化沙箱工具的核心用法。底层原理sys$unveil与 veil 状态机unveil(1)的价值建立在unveil(2)系统调用的实现之上其内核实现位于 Kernel/Syscalls/unveil.cpp。理解以下几个实现细节有助于判断何时该用、何时不该用这个工具。1. 白名单以树组织内核为每个进程维护一棵 unveil 路径树UnveilData::paths路径按目录层级逐段插入。插入时通过update_intermediate_node_permissions把父节点的权限继承给中间节点并标记explicitly_unveiled的节点从而实现unveil 目录即覆盖其下所有子路径的语义。2. 状态机Dropped → Locked → LockedInherited进程的 veil 状态由VeilState描述。一旦使用unveil(nullptr, nullptr)锁定见 Kernel/Syscalls/unveil.cpp后续任何 unveil 调用都会返回EPERM。若已锁定的状态通过execve序列被继承则进入LockedInherited状态此时新进程对 unveil 请求会静默忽略防止绕过。3. fork/exec 语义fork()会把 unveil 状态完整复制给子进程而execve()成功后 veil 状态会被重置。unveil(1)之所以能用unveil_after_exec精准控制目标程序正是依赖这套exec 时套用的机制。4. 参数校验严格权限字符串长度超过 5 个字符返回E2BIG包含未知字符如f返回EINVAL路径为空或非绝对路径返回EINVALpath/permissions二选一为 null 返回EINVAL。这些边界全部被 Tests/Kernel/TestKernelUnveil.cpp 的test_argument_validation用例逐一覆盖。常见错误与排查当unveil(1)包裹的命令运行异常时可以按以下线索快速定位现象可能原因依据目标程序访问某文件失败白名单遗漏该路径或路径未以绝对路径形式登记权限校验见 Kernel/Syscalls/unveil.cppUnveil path being specified is invalid.--path值没有恰好拆成permissions,path两段Userland/Utilities/unveil.cppNo unveil paths were specified.没有提供任何--pathUserland/Utilities/unveil.cpp目标程序需要写权限但被拒绝只授予了r或权限字符串不含w/c权限集约束见 man2 与测试test_failures另外要记住veil 是进程级白名单只影响目标进程的文件系统可见性不会降低目标进程自身的 Unix 权限如 root 身份也不会拦截网络、信号等其他资源。若需要更全面的进程级能力约束应与pledge(2)或系统整体缓解机制见Mitigations(7)配合使用。相关参考unveil(1)本文介绍的命令行工具手册即本指南对应的原始文档unveil(2)系统调用手册含完整错误码与 C 语言示例Userland/Utilities/unveil.cppunveil(1)的命令行实现Kernel/Syscalls/unveil.cppsys$unveil内核实现Kernel/API/Unveil.hUnveilFlags标志位定义Tests/Kernel/TestKernelUnveil.cpp参数校验与权限收紧的测试Tests/Kernel/unveil-symlinks.cpp符号链接场景测试【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表