☰
ULLI安全架构深潜:pkexec root-helper如何用JSON-RPC实现Linux权限隔离
2026/11/3 1:46:20 网站建设 项目流程

【免费下载链接】ulli

USB-less Linux installer for Linux and Windows. Install Linux without a USB stick.

项目地址:https://gitcode.com/gh_mirrors/ul/ulli
点击查看免费下载

ULLI(USB-less Linux Installer,无U盘Linux安装器)是一款免U盘、免手动BIOS配置的Linux装机工具,它的Linux版本用pkexec root-helper + JSON-RPC实现了一套堪称教科书级的权限隔离设计:GUI进程全程不以root运行,只有真正的磁盘操作才会穿过一条受严格校验的JSON-RPC通道。本文将拆解这套机制的工作原理。

一、为什么"无U盘Linux安装器"必须做权限隔离?

ULLI 的核心任务是直接改写硬盘的分区表和 UEFI 引导配置(参见 README.md),这类操作必须使用 root 权限。

最"省事"的做法是整个程序都以 root 启动。ULLI 确实支持这种模式(sudo python3 ulli-linux.py),但它同时提供了另一种更安全的运行方式:

  • GUI 进程保持普通用户权限——它要下载 ISO、解析磁盘信息、处理用户点击,攻击面并不小;
  • 只有一个极小的"root 助手"进程拥有 root,且这个进程不执行任意代码,只接受受白名单约束的 JSON 请求。

这种"把特权面压到最小"的思路,正是 ULLI 安全架构的出发点。

二、架构总览:GUI 进程 + root-helper 进程

ULLI Linux 版采用双进程架构,两个进程通过标准输入/输出管道通信:

┌─────────────────────┐ pkexec(polkit认证) ┌─────────────────────────┐ │ GUI 进程(普通权限) │ ──────────────────────▶ │ root-helper 进程(root) │ │ GTK 界面 / 逻辑 │ ◀────────────────────── │ 只执行白名单内的操作 │ └─────────────────────┘ JSON-RPC 请求/响应 └─────────────────────────┘

关键特性(见 PrivilegedHelper 类 的注释):

  • 助手进程惰性启动:只在第一次需要特权操作时,通过pkexec一次性拉起;
  • GUI 全程无特权,只有磁盘操作跨越权限边界;
  • 通信走 "JSON-over-pipes":一行一个请求,一行一个响应,无端口、无网络、无第三方库。

三、一个脚本双重角色:--root-helper开关的妙处

打开 linux/ulli-linux.py,文件开头就有一个分支:当命令行包含--root-helper时,脚本不加载任何 GUI 依赖,直接以 JSON-RPC 服务子进程的身份运行。

也就是说,同一个文件既是安装器主程序,又是特权助手。拉起方式在 PrivilegedHelper.init中:

pkexec <python解释器> ulli-linux.py --root-helper

pkexec是 polkit 体系的命令行入口,它会弹出图形认证对话框,由用户确认后助手进程才获得 root。如果系统缺少 polkit,程序会给出清晰的安装指引(Debian/Ubuntu 装policykit-1,Fedora 装polkit);用户取消认证时也会得到友好提示"Root privileges are required",而不是神秘崩溃。

四、JSON-RPC 协议详解:两个进程如何对话?

协议极其简洁,但五脏俱全(主循环见 ulli-linux.py):

请求:GUI 端把一行 JSON 写入助手的 stdin,形如:

{"type": "run", "cmd": ["parted", "/dev/sda", "unit", "MiB", "print"]} {"type": "write", "path": "/boot/efi/EFI/refind/refind.conf", "content": "..."}

支持 6 种请求类型(请求类型白名单):

类型作用典型场景
run执行白名单内命令分区、格式化、挂载、写引导项
mkdir创建目录建立/mnt/linux_installer_boot等挂载点
read读文件读取并打补丁的引导配置文件
write写文件写 rEFInd 配置、udev 规则
unlink删除文件安装完成后清理 udev 规则
exists判断路径存在存在性检查

响应:助手把一行 JSON 写回 stdout,核心字段为rc(返回码)、out/err(标准输出/错误输出)。GUI 端通过 _send 方法 完成"写一行 → flush → 读一行"的同步往返,模型清晰、无并发竞争。

助手是常驻进程:整个安装会话只认证一次,后续上百次磁盘操作全部复用这条通道,用户体验流畅。

五、四层安全校验:从请求类型到路径穿越防御

助手端对每个请求都先过 _validate_request 这道"安检门",共设四道关卡:

1️⃣ 请求类型白名单

未知类型的请求直接拒绝,杜绝协议扩展带来的意外攻击面。

2️⃣ 命令白名单(39 个)

run类型的命令名必须命中 ALLOWED_COMMANDS——parted、sfdisk、mkfs.ext4、btrfs、rsync、mount、efibootmgr、wipefs等磁盘工具,一个不多、一个不少。bash、sh、curl、python3都不在其中,这意味着即便通道被滥用,也无法借此执行任意解释器。

3️⃣ 危险模式拦截

命令拼成字符串后会扫描高危模式(拦截规则):重定向>>、<<、管道符|,以及chmod 777、/etc/shadow、/etc/sudoers等敏感目标,命中即报 "Dangerous pattern detected"。

4️⃣ 路径前缀白名单 + realpath 防穿越

文件类操作(mkdir/read/write/unlink/exists)的路径先用os.path.realpath解析,把../这类相对跳转展平,再检查是否落在 ALLOWED_PREFIXES 之内:

/mnt/ /run/udev/ /boot/ /sys/ /dev/ /proc/

这正好覆盖安装器真正需要触碰的区域(挂载点、UEFI 引导区、udev 规则、块设备),/etc、/home、/usr全部在防护圈之外,路径穿越攻击在此被彻底封堵。

六、用户体验与容错设计

  • 认证时机自然:打开界面后第一次刷新磁盘信息(_refresh_disk_info)就会触发 polkit 弹窗,认证失败则界面明确显示 "Root privileges required",不会让用户不知所措;
  • 助手死亡检测:若助手进程意外退出(如用户中断),读取响应会得到空行,GUI 端立即抛出"Privileged helper died unexpectedly",错误不静默;
  • 双模式路由:全局开关_is_root = os.geteuid() == 0(L122)配合 run 路由函数 和 priv_* 系列辅助函数——以sudo运行时直接本地执行,以普通用户运行则自动转投 root-helper,业务代码对此完全无感知。

七、安全价值总结:纵深防御一览

维度朴素做法(整进程 sudo)ULLI 的隔离方案
GUI 进程权限root普通用户
特权进程职责执行全部逻辑只接受 6 类校验请求
可执行命令任意39 项命令白名单
可写路径全盘6 个前缀白名单 + 穿越检测
认证粒度启动即 rootpolkit 按需认证,可审计

🔒一句话总结:ULLI 用"pkexec 按需授权 + 常驻 JSON-RPC 助手 + 四层白名单校验",把一个需要 root 的磁盘装机工具改造成了最小权限模型——GUI 可以被攻破,但能做的事非常有限;root 助手拥有全权,却只能执行被白名单焊死的操作。这正是"权限隔离"在真实开源项目中的落地范本。

💡 想动手验证?克隆仓库后执行python3 linux/ulli-linux.py --check-deps检查依赖(命令见 linux/README.md),再通读 linux/ulli-linux.py 的 root-helper 主循环,约 90 行代码即可完整理解这套机制。开发约定可参考 AGENTS.md。

【免费下载链接】ulli

USB-less Linux installer for Linux and Windows. Install Linux without a USB stick.

项目地址:https://gitcode.com/gh_mirrors/ul/ulli
点击查看免费下载

相关推荐

上一篇:Bevy 排他函数系统统一改造指南:`&mut World` 任意位置与 `SystemAccess` 运行时独占判定
下一篇:探索OpenWebRX:从入门到精通的SDRWeb界面使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询