Arch 打包准则/安全 - Arch Linux 中文维基

跳转到内容

# Arch 打包准则/安全

来自 Arch Linux 中文维基
< Arch 打包准则
Arch 打包准则

32 位 – 安全 – CLR – CMake – DKMS – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – 交叉编译工具 – KDE – Lisp – Meson – MinGW – 内核模块 – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – Shell – VCS – Web – Wine – 字体

翻译状态：

- 本文（或部分内容）译自 Arch package guidelines/Security，最近一次同步于 2026-01-21，若英文版本有所更改，则您可以帮助同步与翻译更改的内容。
- 您可以在 ArchWiki 的对应页面找到本文翻译的原始修订历史。
- 本文可能与英文原文存在出入。

本文描述了适用于 Arch Linux 软件包的打包安全指引。对于 C/C++ 项目，可以为编译器和链接器应用安全加固选项。Arch Linux 默认会启用 PIE、FORTIFY_SOURCE、栈保护、nx 和 relro。

## 用法

可以使用 checksec包 检查强化加固保护选项：

    $ checksec --file=/usr/bin/cat

提示：Namcap 也可以报告本文描述的一些安全问题。

## RELRO

RELRO 是用于加固 ELF 二进制文件和进程的一种通用缓解技术。在程序加载时，链接器需要写入几个 ELF 内存区段，但在将控制权交给程序前，可以将这些区段设为只读，由此防止攻击者覆盖掉部分 ELF 区段。有两种 RELRO 模式：

- 部分 RELRO（`-Wl,-z,relro`）：程序加载后部分区段被设为只读，但 GOT（`.got.plt`）仍为可写。
- 完全 RELRO（`-Wl,-z,now`）：程序加载时解析所有动态符号，使得整个 GOT 都可被设为只读。

如果应用汇报使用了部分 RELRO，需检查构建工具是否使用了我们传递的 LDFLAGS，以及是否允许覆写 LDFLAGS。对于 Go 软件包，需检查构建方法是否将 `build.go` 作为了纯 golang Makefile 替代使用，该方法不允许传递 LDFLAGS。

### Haskell

暂不清楚如何为 Haskell 实现完全 RELRO。

### Go

参见 Go 语言软件打包准则#Flags and build options。

## Stack canary

Stack canary（又称栈警惕标志）由编译器添加在栈的缓冲区和控制数据之间。如果该已知值被破坏，就代表出现了缓冲区溢出，运行中的程序就会报出段错误（segfaults），以防止执行潜在的错误代码。

gcc包 包默认通过 --enable-default-ssp 编译选项启用了栈保护。

## NX

### C/C++

可执行空间保护会将内存区域标记为非可执行，使得在该区域执行机器码时会出现报错。该功能使用了类似 NX 位（No-eXecute bit，禁止执行位）的硬件功能，有时也会使用软件模拟这些特性。

## PIE

### C/C++

gcc包 包默认通过 --enable-default-pie 选项为 C/C++ 启用了该特性。

### Golang

将以下标志传递给 `go build`：

    export GOFLAGS='-buildmode=pie'
    export CGO_CPPFLAGS="-D_FORTIFY_SOURCE=3"
    export CGO_LDFLAGS="-Wl,-z,relro,-z,now"

### Haskell

将以下标志传递给 `runhaskell Setup.hs configure`：

    --ghc-option='-pie'

## RPATH/RUNPATH

RUNPATH/RPATH 为包含该参数的对象提供了更多的搜索路径（适用于可执行文件和共享对象）：

    $ objdump -x /usr/bin/perl | grep -E 'RPATH|RUNPATH'

如果 RPATH 的值包含了攻击者可控制的路径，那就有可能通过对应目录下的恶意库执行代码（例如 CVE-2006-1566 和 CVE-2005-4280）。更多信息请参考 Debian:RpathIssue。

RPATH 是通过向 LDFLAGS 传递类似 `-Wl,-rpath -Wl,/usr/local/lib` 的参数，然后由链接器负责设置的。如果要设置 RUNPATH，请将 `--enable-new-dtags` 添加到链接器标志中。

## FORTIFY

Fortify source 是一个宏，可以为执行内存和字符串操作的函数添加缓冲区溢出保护。它会检测是否有攻击者尝试通过负责更多的字节来溢出缓冲区，并停止程序的运行。该保护项已在默认 `CPPFLAGS` 中启用：

    makepkg.conf

    CPPFLAGS="-D_FORTIFY_SOURCE=3"

更多信息请参考 makepkg#配置。

## systemd 服务

此页面或章节适合移动到 systemd/Sandboxing。

附注： 内容主题与 systemd#应用程序环境沙盒 相同，两者可被汇总到单独页面，草稿可参考 User:NetSysFire/systemd sandboxing。（在 Talk:Security#systemd unit hardening and system.conf tweaks 讨论）

如果上游不提供 systemd 服务文件，使得需随软件包附带，请检查是否需要使用以下 systemd 服务加固功能。Systemd 提供并为服务启用了分析安全特性的方法：

    $ systemd-analyze security reflector.service

### 文件访问

可以通过限制文件系统访问来加固服务。

为执行的进程配置一个新的文件系统命名空间，并在内部挂载私有 `/tmp` 和 `var/tmp` 目录，使得其不与命名空间外部的进程共享。该方法适用于会向 `/tmp` 目录写入数据的程序：

    PrivateTmp=true

ProtectSystem 参数对于执行中进程有三种只读挂载方式，其中 “full” 选项会将 `/usr`、`/boot` 和 `/etc` 目录挂载为只读。ProtectHome 会使进程无法访问 `/home`、`/root` 和 `/run/user` 目录：

    ProtectSystem=strict
    ProtectHome=true

PrivateDevices 会为执行中的进程配置新的 `/dev` 命名空间，其中只包含类似 `/dev/null`、`/dev/zero` 和 `/dev/random` 的 API 伪设备，不包含任何物理设备、系统内存、系统端口和其它设备。该选项可以防止进程直接向物理设备进行写入，systemd 还会为 `@raw-io` 集添加系统调用过滤器：

    PrivateDevices=true

以下选项会使执行中进程无法修改可通过 `/proc/sys` 和 `/sys` 等路径访问的内核变量。ProtectControlGroups 会使 `/sys/fs/cgroup` 层次结构变为只读：

    ProtectKernelTunables=true
    ProtectControlGroups=true

以下方法可禁止访问部分文件路径：

    InaccessiblePaths=/etc

更多信息请参考 systemd.exec(5)。

### 用户

确保执行中的进程和其子进程无法通过 execve(2) 获得新权限：

    NoNewPrivileges=true

### 内存

禁止创建同时为可写和可执行的内存映射、将映射修改为可执行和创建可执行共享内存。该方法会将进程沙箱化，防止攻击者向可执行的内存部分写入数据。注意，该方法与使用 JIT 的应用不兼容：

    MemoryDenyWriteExecute=true

### 系统调用

锁定 personality(2) 系统调用，使内核执行域无法被修改：

    LockPersonality=true

还可以限制服务的系统调用，以下命令将显示 systemd 可以过滤的系统调用：

    $ systemd-analyze syscall-filter

可以使用预定义组，以下示例为使用推荐的系统服务调用白名单配置起点：

    SystemCallFilter=@system-service

还可以按架构来限制系统调用，例如限制在 64 位设备上执行 32 位二进制文件（即非原生架构二进制文件）：

    SystemCallArchitectures=native

### 网络

如果进程不需要访问网络，可以为进程配置一个新的网络命名空间，并只配置回环接口，以此完全禁用网络访问：

    PrivateNetwork=true

如果需要网络，还可以限制 socket(2) 系统调用可使用的地址族类型，以只允许 UNIX socket 为例：

    RestrictAddressFamilies=AF_UNIX

也可以对只需连接到 localhost（本机）或特定 IP 段的情况进行限制，以只允许 localhost 为例：

    IPAddressAllow=localhost
    IPAddressDeny=any

更多网络过滤相关的信息请参考 systemd.resource-control(5)。

### 其它

为执行的进程配置新的 UTS 命名空间，并禁止修改主机名或域名：

    ProtectHostname=true

分类：​

- Arch 打包准则
- 安全
- 使用“模板:Move”标记的页面或章节

Arch 打包准则/安全
添加话题