Skip to content

Commit

Permalink
Merge pull request #121 from lidaxian121/master
Browse files Browse the repository at this point in the history
pseudo_syscalls translation complete
  • Loading branch information
mudongliang authored Aug 15, 2024
2 parents 4771336 + 4fa5947 commit aca08b1
Showing 1 changed file with 21 additions and 79 deletions.
100 changes: 21 additions & 79 deletions sources/syzkaller/pseudo_syscalls.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,25 @@
---
status: translating
status: translated
title: "Pseudo-syscalls"
author: Syzkaller Community
collector: mudongliang
collected_date: 20240229
translator: lidaxian121
translated_date: 20240719
link: https://github.com/google/syzkaller/blob/master/docs/pseudo_syscalls.md
---

# Pseudo-syscalls
# 伪系统调用

Besides regular system calls, a [syscall
description](syscall_descriptions.md) file can also contain
pseudo-syscalls. These are C functions defined in the
executor. When a test program uses a pseudo-syscall, the executor
will generate the pseudo-syscall function code in the resulting C program.
除了常规系统调用外,[系统调用描述](https://github.com/hust-open-atom-club/TranslateProject/blob/master/sources/syzkaller/syscall_descriptions.md)文件也包含伪系统调用。它们是在执行器中定义的 C 函数。当测试程序使用伪系统调用时,执行器将在生成的 C 程序中生成伪系统调用函数。

This allows a test program to have specific code blocks to perform
certain actions, they may also be used as more test-friendly wrappers
for primitive syscalls.
伪系统调用的存在使得测试程序可以拥有执行特定操作的特定代码块,它们还可以作为更加测试友好的原始系统调用包装器来使用。

Use of pseudo-syscalls is generally **discouraged** because they ruin all
advantages of the declarative descriptions (declarativeness, conciseness,
fuzzer control over all aspects, possibility of global improvements to
the logic, static checking, fewer bugs, etc), increase maintenance burden,
are non-reusable and make C reproducers longer. However, syzlang is not
expressive enough to cover all possible cases, so use of pseudo-syscalls
needs to be considered on a case-by-cases basis (additional benefit,
amount of code, possibility of extending syzlang to cover this case, etc).
通常来说是**不建议**使用伪系统调用的,这是因为它们破坏了声明性描述的所有优势(声明性,简洁性,模糊器对所有方面的控制,全局逻辑改进的可能性,静态检查,减少错误等),增加了维护负担,不可重复使用,并且使 C 重现器(C reproducers)更长。然而,syzkaller 语言(syzlang)的表现力不足以涵盖所有可能的情况,因此需要根据具体情况考虑是否使用伪系统调用(额外的好处、代码量、扩展 syzkaller 语言以涵盖此情况的可能性等)。

## How to add a pseudo-syscall to the executor
## 如何将伪系统调用添加到执行器中

First, think about the scope of the pseudo-syscall and which systems and
subsystems it will be related to. The executor includes a fixed set of C
header files containing the code of the pseudo-syscalls. Check if the
new one can fit in one of the existing files before creating a new
one. These header files are defined in [gen.go](../pkg/csource/gen.go):
首先,考虑伪系统调用的范围以及它将涉及的系统和子系统。执行器包含一组固定的 C 头文件,其中包含伪系统调用的代码。在创建新文件之前,检查新伪系统调用是否可以适应现有文件之一。这些头文件在 [gen.go](https://github.com/google/syzkaller/blob/master/pkg/compiler/gen.go) 中定义:

executorFilenames := []string{
"common_linux.h",
Expand All @@ -54,10 +38,9 @@ one. These header files are defined in [gen.go](../pkg/csource/gen.go):
"kvm_amd64.S.h",
}

For instance, if our new pseudo-syscall is Linux-specific, then
[common_linux.h](../executor/common_linux.h) would be the place to put it.
例如,如果我们的新伪系统调用特定于 Linux,则 [common_linux.h](https://github.com/google/syzkaller/blob/master/executor/common_linux.h) 将是放置它的地方。

The actual pseudo-syscall function may look something like this:
真正的伪系统调用函数可能看起来就像下面的这个例子一样:

#if SYZ_EXECUTOR || __NR_syz_mycall
/* Add all the necessary #include and #define headers */
Expand All @@ -68,67 +51,26 @@ The actual pseudo-syscall function may look something like this:
}
#endif

Make sure that all the function requirements are met and that it can
be compiled. Note that the function name must start with "syz_". It may
also take a different number of arguments. Type of arguments must be
`volatile long`, return type - `long`. `long` is required to avoid
potential calling convention issues because it is casted to a function
pointer that accepts `long`'s. The reason for `volatile` is interesting:
lots of libc functions are annotated with various argument constraints
(e.g. this argument should not be `NULL`, or that argument must be a
valid file descriptor); C reproducers may call these functions with
constant arguments and compiler may see that some of these constraints
are violated (e.g. passing `NULL` to a `non-NULL` argument, or passing
`-1` as file descriptor) and produce errors/warnings. `volatile` prevents
that.

Now, to handle the pseudo-syscall properly we have to update the
`isSupportedSyzkall` in
[syscalls_linux.go](../pkg/host/syscalls_linux.go) and add a particular
case for this syscall, enabling it when necessary. If we want to enable
it unconditionally we can simply make `isSupportedSyzkall` return `true,
""` for it:
确保满足所有函数的要求并且可以编译成功。注意,函数名称必须以 "syz_" 开头。它还可以接受不同数量的参数。参数的类型必须是 `volatile long`,返回类型是 `long`。之所以需要使用 `long` ,是为了避免潜在的调用约定问题,因为它被转换为接受 `long` 的函数指针。用 `volatile` 的原因很有趣:许多libc函数都用各种参数约束注释(例如,此参数不应为 `NULL`,或者该参数必须是有效的文件描述符);复现程序(C reproducers)可能使用常量参数调用这些函数,而编译器可能会看到某些约束被违反(例如,将 `NULL` 传递给 `non-NULL` 参数,或者将 `-1` 作为文件描述符传递),并生成错误或者警告。使用 `volatile` 可以防止这种情况。

现在,为了正确处理伪系统调用,我们必须更新 [syscalls_linux.go](https://github.com/google/syzkaller/blob/master/pkg/host/syscalls_linux.go) 中的 `isSupportedSyzkall` 并为某个系统调用添加特定的情况,必要时启用它。如果我们想无条件启用它,我们可以简单地让 `isSupportedSyzkall` 为其返回 `true,""`

func isSupportedSyzkall(sandbox string, c *prog.Syscall) (bool, string) {
switch c.CallName {
...
case "syz_mycall":
return true, ""

Finally, run `make generate`. Now you can use it in a syscall
description file as if it was a regular system call:
最后,运行 `make generate`。现在,你可以将它当作系统调用描述文件中的普通系统调用一样使用:

syz_mycall(arg0 pid, arg1 const[0])

<div id="dependencies"/>

## External Dependencies

The implementation must not use any external libraries nor external headers,
except for the most basic and standard ones (like `<unistd.h>` and
`<sys/mman.h>`). In particular, it must not depend on libraries/headers
installed by additional packages nor on headers for recently added kernel
subsystems. External dependencies have proved to be brittle and easily cause
build breakage because all dependencies will be required for any build/run on
the fuzzer and any C reproducer. For example, packages/headers may be missing
on some distros, named differently, be of a wrong version, broken, or conflict
with other headers. Unfortunately, there is no way to reliably specify such
dependencies and requirements for C programs. Therefore, if the pseudo-syscall
requires definitions of some structures, constants, or helper functions, these
should be described in the executor code itself as minimally as possible (they
will be part of C reproducers).

## Testing

Each new pseudo-syscall should have at least one test in `sys/OS/test`.
See [Linux tests](/sys/linux/test) for an example. A tests is just a program
with checked syscall return values. There should be at least one test
that contains "the main successful scenario" of using the pseudo-syscall.
See [io_uring test](/sys/linux/test/io_uring) as a good example.
Such tests are important because they ensure that the pseudo-syscall code
does not contain "stupid" bugs (e.g. crash on NULL-deref each time),
that it is possible for the fuzzer to come up with the successful scenario
(as a combination of the pseudo-syscall and the surrounding descriptions)
and that it will continue to work in future.
See [Testing of descriptions](syscall_descriptions.md#testing)
for details about the tests.
## 外部依赖

伪系统调用的实现不能使用任何外部库或外部头文件,除了一些最基本和标准的库(比如 `<unistd.h>``<sys/mman.h>` )。特别是,它不能依赖于附加软件包安装的库或者头文件,也不能依赖于最近添加的内核子系统的头文件。外部依赖性已经被证明是脆弱的,并且很容易导致构建中断,因为模糊测试器上任何的构建和运行以及 C 复现器都需要所有依赖项。例如,软件包或者头文件可能在某些发行版上缺少,命名不同,版本错误,损坏,或与其他头文件冲突。不幸的是,无法可靠地指定此类依赖项以及 C 程序的要求。因此,如果伪系统调用需要某些结构,常量或辅助函数的定义,则这些应该尽可能简短地在执行器代码中描述(它们将成为复现程序(C reproducers)的一部分)。

## 测试

每个新的伪系统调用应该在 `sys/OS/test` 中至少有一个测试。参见 [Linux tests](https://github.com/google/syzkaller/blob/master/sys/linux/test) 作为示例。测试只是一个检查系统调用返回值的程序。对于某个伪系统调用应该至少有一个测试包含使用它的“主要成功场景”。可以看看 [io_uring 测试](https://github.com/google/syzkaller/blob/master/sys/linux/test/io_uring),这是一个很好的例子。这样的测试很重要,因为它们确保伪系统调用的代码不包含“愚蠢”的错误(例如,每次在 NULL-deref 上崩溃)。这样,模糊测试器才可以想出成功的方案(伪系统调用和周围描述的组合),并且在将来能够持续工作。有关测试的详细信息,请参见[描述的测试](https://github.com/hust-open-atom-club/TranslateProject/blob/master/sources/syzkaller/syscall_descriptions.md)

0 comments on commit aca08b1

Please sign in to comment.