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 打包準則/安全
新增話題