> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/man/man7/sprog.7.md).

# sprog.7

`sprog` — 安全编程实践

## 名称

`sprog`

## 描述

多年来，安全问题已悄然潜入许多系统。本文档是防止这些问题发生的编程实践指南。

### 概述

编写安全的应用程序需要非常审慎和悲观的态度。应用程序应遵循“`最小权限`”原则运行，使得任何进程都不应拥有超出完成其功能所需的最少访问权限。应尽可能重用已测试过的代码。通常，任何超出程序控制范围的东西都不应被信任。这包括所有形式的用户输入、系统资源、进程间通信以及事件的时序。

### 缓冲区溢出

缓冲区溢出是最常见的安全问题类型之一。简而言之，如果程序对所接收的数据不够小心，这些数据可能会被写入到内存中越界位置，覆盖函数调用的返回地址，程序将被强制运行执行恶意行为的代码。

标准 C 库中有许多函数在使用时难以甚至不可能防止缓冲区溢出。这些函数包括 fscanf(3)、gets(3)、getwd(3)、realpath(3)、scanf(3)、sprintf(3)、strcat(3)、strcpy(3)、vscanf(3) 和 vsprintf(3)。

许多其他处理字符串的函数如果使用不当，也可能引发潜在的缓冲区溢出。例如，strncat(3) 并不会主动提供 NUL 字符终止。当然，必须始终指定正确的长度。使用 strlcat(3) 和 strlcpy(3) 可确保字符串以 null 终止并且具有指定的长度。

接收字符串格式的函数也必须小心使用。字符串可能包含额外的格式说明符，这为缓冲区溢出打开了另一种可能性。切勿在不使用 `%s` 的情况下传递包含不可信数据的字符串。始终使用正确的安全惯用法：

```sh
function("%s", string);
```

在库和编译器层面存在一些为这些问题提供后盾的机制，但是，没有任何东西能够替代编写良好的代码。

### Set-user-ID 问题

在许多情况下，程序可能需要以提升的权限集合运行。原因包括绑定受保护套接字、读写某些文件和目录以及访问各种资源。使用 setuid 程序通常是解决方案。然而，程序尽快放弃这些权限非常重要。例如，如果程序正在绑定到受保护套接字，它应在完成绑定后立即放弃其权限。这通过 setuid(2) 系列系统调用完成。

### 受限环境

限制进程的传统方法是使用 chroot(2) 系统调用。此系统调用更改根目录，进程及其任何子进程的所有其他路径都从该根目录引用。当然，进程必须首先具有对此路径的访问权限。新环境在调用 chdir(2) 将进程放入新环境之前实际上不会生效。遗憾的是，如果获得了 root 访问权限，进程可以突破此环境。

通常，jail(2) 可用于创建比 chroot(2) 所能提供的更完整和封闭的环境。Jail 限制该环境内的所有进程，包括具有超级用户权限的进程。

POSIX.1e 扩展所描述的细粒度权限目前仍在开发中，是 TrustedBSD 项目的重点。更多信息可在 `http://www.TrustedBSD.org/` 找到。

### 信任

程序不应对其运行环境做出假设。这包括用户输入、信号、环境变量、系统资源、进程间通信和共享内存等超出程序控制范围的内容。它们也不应假设能够检测到所有形式的无效数据。相反，应使用正向过滤，仅允许已知安全的特定输入子集。这与管理员应应用于防火墙的逻辑相同，即默认拒绝并指定要接受的内容。

### 竞态条件

竞态条件是由事件的相对时序引起的异常行为。程序不应假设特定事件会在另一事件之前发生。竞态条件最常见的原因是信号、访问检查和文件读取。信号本质上是异步的，因此在处理它们时必须格外小心。尝试使用顺序非原子操作来检查访问权限是个非常糟糕的主意，因为文件可以在任何时候被移动和更改。不要使用 access(2) 和 open(2) 的序列，而应使用 seteuid(2) 然后直接调用 open(2)。事先正确设置 umask(2)。

## 参见

jail(2), setuid(2), strlcat(3), strlcpy(3)

## 作者

Eric Melville <eric@FreeBSD.org> 最初基于 Murray Stokely <murray@FreeBSD.org> 编写的 FreeBSD Developer's Handbook 的一章撰写了本文档。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/man/man7/sprog.7.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
