mirror of
https://github.com/gatieme/LDD-LinuxDeviceDrivers.git
synced 2026-08-18 17:17:39 +08:00
kptr_restrict 向用户空间内核中的指针(/proc/kallsyms-modules显示value全部为0)--http://blog.csdn.net/gatieme/article/details/78311841
This commit is contained in:
@@ -90,26 +90,40 @@ When kptr_restrict is set to (2), kernel pointers printed using
|
||||
|
||||
>注意 `kptr_restrict` 对内核中很多地址和符号表的信息导出都有影响, 比如 `/proc/modules` 等.
|
||||
|
||||
#3 kptr_restrict的设计
|
||||
# 3 kptr_restrict的设计
|
||||
-------
|
||||
|
||||
|
||||
|
||||
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|
||||
|:----:|:----:|:---:|:----:|:---------:|:----:|
|
||||
| 2020/09/17 | Dan Rosenberg <drosenberg@vsecurity.com> | [kptr_restrict for hiding kernel pointers from unprivileged users](https://lore.kernel.org/patchwork/cover/229987) | 引入 kptr_restrict 限制都内核指针的读取 | v7 ☑ 2.6.38-rc1| [v7 PatchWork](https://lore.kernel.org/patchwork/cover/228326)<br>*-*-*-*-*-*-*-* <br>[v7 PatchWork](https://lore.kernel.org/patchwork/cover/229987)<br>*-*-*-*-*-*-*-* <br>[commit 455cd5ab305c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=455cd5ab305c90ffc422dd2e0fb634730942b257) |
|
||||
| 2010/12/23 | Dan Rosenberg <drosenberg@vsecurity.com> | [kptr_restrict for hiding kernel pointers from unprivileged users](https://lore.kernel.org/patchwork/cover/229987) | 引入 kptr_restrict 限制都内核指针的读取 | v7 ☑ 2.6.38-rc1| [v7 PatchWork](https://lore.kernel.org/patchwork/cover/228326)<br>*-*-*-*-*-*-*-* <br>[v7 PatchWork](https://lore.kernel.org/patchwork/cover/229987)<br>*-*-*-*-*-*-*-* <br>[commit 455cd5ab305c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=455cd5ab305c90ffc422dd2e0fb634730942b257) |
|
||||
| 2017/11/19 | Tobin C. Harding <me@tobin.cc> | [hash addresses printed with %p](https://lore.kernel.org/patchwork/cover/856356) | 内核中 %p 打印的地址会暴露内核态地址信息, 是极其不安全的, 因此限制 %p 的打印信息, 它将打印一个散列值, 并不是实际的地址. 如果想要打印实际地址, 需要显式指定 %px. | v11 ☑ 4.15-rc2 | [PatchWork](https://lore.kernel.org/patchwork/cover/856356)<br>*-*-*-*-*-*-*-* <br>[关键 commit 57e734423add](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=57e734423adda83f3b05505875343284efe3b39c) |
|
||||
| 2019/04/17 | Petr Mladek <pmladek@suse.com> | [vsprintf: Prevent silent crashes and consolidate error handling](https://lore.kernel.org/patchwork/cover/1063193) | 此处填写补丁描述 | v7 ☑ 5.2-rc1 | [PatchWork](https://lore.kernel.org/patchwork/cover/1063193)<br>*-*-*-*-*-*-*-* <br>[commit 6eea242f9bcd](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6eea242f9bcdf828bb56334d8ee5c7cb466e4bcd) |
|
||||
| 2017/11/29 | Linus Torvalds <torvalds@linux-foundation.org> | vsprintf: don't use 'restricted_pointer()' when not restricting | 如果发现 kptr_restrict 为 0, 则直接跳过 restricted_pointer() 流程. 这个补丁将影响 kptr_restrict 为 0 时, %pK 等同于 %p 输出散列地址. | v1 4.15-rc2 | [commit ef0010a30935 ("vsprintf: don't use 'restricted_pointer()' when not restricting")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ef0010a30935de4e0211cbc7bdffc30446cdee9b) |
|
||||
| 2018/02/16 | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | [lib/vsprintf: Deduplicate pointer_string()](https://lore.kernel.org/patchwork/patch/888079) | 简单的重构, 删除了一些重复的判断, 逻辑没有任何修正 | [PatchWork](https://lore.kernel.org/patchwork/cover/888079)<br>*-*-*-*-*-*-*-* <br>[关键 commit 496a9a5f3806](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=496a9a5f3806d58b14ae06b390d5b1ffa26e9f9a) |
|
||||
| 2019/04/17 | Petr Mladek <pmladek@suse.com> | [hvsprintf: Prevent silent crashes and consolidate error handling](https://lore.kernel.org/patchwork/cover/1063203) | 修复上面补丁引入的一个小问题, 限制 restricted_pointer 中 kptr_restrict 为 0 时, 输出散列地址. | v7 ☑ 5.2-rc1 | [PatchWork](https://lore.kernel.org/patchwork/cover/1063193)<br>*-*-*-*-*-*-*-* <br>[关键 commit 1ac2f9789c4b](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1ac2f9789c4b76ad749870c25ffae0cbcd1f510f) |
|
||||
| 2020/02/19 | Ilya Dryomov <idryomov@gmail.com> | [vsprintf: don't obfuscate NULL and error pointers](https://lore.kernel.org/patchwork/patch/1196790) | 同样的, 之前 NULL 指针和错误指针的输出也很混乱, 进行了归一化. | v2 ☑ 5.7-rc7 | [PatchWork](https://lore.kernel.org/patchwork/cover/1196790)<br>*-*-*-*-*-*-*-* <br>[关键 commit 7bd57fbc4a4d](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7bd57fbc4a4ddedc664cad0bbced1b469e24e921) |
|
||||
|
||||
|
||||
## 3.1 v4.14 之前设计
|
||||
## 3.1 v4.14 之前的设计
|
||||
-------
|
||||
|
||||
在 4.x 的内核中 `kptr_restrict` 在内核 [`commit 455cd5ab305c ("kptr_restrict for hiding kernel pointers from unprivileged users")`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=455cd5ab305c90ffc422dd2e0fb634730942b257), 具体实现源码位于 [`lib/vsprintf.c, line 1708`](http://elixir.free-electrons.com/linux/v4.13.9/source/lib/vsprintf.c#L1708)
|
||||
在 linux 2.6.38 中 [`commit 455cd5ab305c ("kptr_restrict for hiding kernel pointers from unprivileged users")`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=455cd5ab305c90ffc422dd2e0fb634730942b257) 引入了 `kptr_restrict` 用来限制用户态读取内核指针的显示.
|
||||
|
||||

|
||||
|
||||
具体处理 kptr_restrict 实现在 pointer 函数中, 该函数用于处理指针格式的 fmt 输出, 源码位于 [`lib/vsprintf.c, v4.13.9, line 1794`](http://elixir.free-electrons.com/linux/v4.13.9/source/lib/vsprintf.c#L1794), 自 2.6.x 到 4.14 之前的版本这段流程没有太大的改动.
|
||||
|
||||
|
||||
|
||||
```cpp
|
||||
// https://elixir.bootlin.com/linux/v4.13.9/source/lib/vsprintf.c#L1708
|
||||
// https://elixir.bootlin.com/linux/v4.13.9/source/lib/vsprintf.c#L1794
|
||||
static noinline_for_stack
|
||||
char *pointer(const char *fmt, char *buf, char *end, void *ptr,
|
||||
struct printf_spec spec)
|
||||
{
|
||||
// ......
|
||||
|
||||
case 'K':
|
||||
switch (kptr_restrict) {
|
||||
case 0:
|
||||
@@ -151,9 +165,29 @@ When kptr_restrict is set to (2), kernel pointers printed using
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// ......
|
||||
}
|
||||
```
|
||||
|
||||
## 3.2 v5.2 之前设计
|
||||
可见, kptr_restrict
|
||||
|
||||
* 为 0 时, 未作任何处理, 直接输出, 这样对所有用户都没有限制.
|
||||
|
||||
* 为 1 时, 中断上下文则不允许输出, 否则则校验了用户的权限.
|
||||
|
||||
* 为 2 时, 将指针直接置 NULL, 这样所有用户都只能看到全 0.
|
||||
|
||||
整体思路还是比较清晰的. 想要详细了解实现全貌的, 可以直接查阅该特性合入时的 patchwork 或者 commit.
|
||||
|
||||
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|
||||
|:----:|:----:|:---:|:----:|:---------:|:----:|
|
||||
| 2010/12/23 | Dan Rosenberg <drosenberg@vsecurity.com> | [kptr_restrict for hiding kernel pointers from unprivileged users](https://lore.kernel.org/patchwork/cover/229987) | 引入 kptr_restrict 限制都内核指针的读取 | v7 ☑ 2.6.38-rc1| [v7 PatchWork](https://lore.kernel.org/patchwork/cover/228326)<br>*-*-*-*-*-*-*-* <br>[v7 PatchWork](https://lore.kernel.org/patchwork/cover/229987)<br>*-*-*-*-*-*-*-* <br>[commit 455cd5ab305c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=455cd5ab305c90ffc422dd2e0fb634730942b257) |
|
||||
|
||||
|
||||
## 3.2 v4.15 开始的设计
|
||||
-------
|
||||
|
||||
### 3.2.1 printk 地址散列化
|
||||
-------
|
||||
|
||||
```CPP
|
||||
@@ -161,9 +195,225 @@ When kptr_restrict is set to (2), kernel pointers printed using
|
||||
```
|
||||
|
||||
|
||||
## 3.3 v5.2 之后设计
|
||||
在 linux 4.15 中 [commit 57e734423add ("vsprintf: refactor %pK code out of pointer()")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=57e734423adda83f3b05505875343284efe3b39c) 将 point 中对 `%pK`(kptr_restrict) 的处理都封装到了 restricted_pointer 函数中. 这个修改比较简单, 就不详细描述了. 想要详细了解的同学可以查看提交的 commit
|
||||
|
||||
这次修改所属的 patchset 最主要是为了限制 %p 直接暴露内核的地址. 在早期内核中, 我们可以通过 System.map 或者 vmlinux 获取内核符号的地址信息, 内核中也较多的使用 %p 输出一些调试信息, 帮助用户显示一些符号的地址. 但是随着内核不断的演进, 开发者们发现, 随意暴露内核的地址是十分不安全的.
|
||||
|
||||
内核实现了越老越多的安全特性, 比如[内核地址随机化](https://lore.kernel.org/patchwork/cover/639469)等等. 正常情况下, kernel image 会按照 vmlinux 链接脚本中的链接地址去映射虚拟地址, 如果开启kaslr, 则会重新再映射一次, 映射到 链接地址 + offset的新地址上去. 如果 offset 每次开机都由 bootloader 随机生成, 那么每次开机后, kernel image最后映射的虚拟地址都不一样, 这就是内核地址随机化.
|
||||
|
||||
通过反汇编 vmlinux 以及读取 System.map 得不到内核中函数或者汇编语句的真正地址, 因为攻击者并不知道 kaslr 的 offset. 但是 %p 暴露内核地址将打破了这个限定. 攻击者通过 %p 打印中获取到的地址和 vmlinux 中该符号的地址进行比较, 就可以直接获取到 offset 偏移, 进而整个地址随机化机制将形同虚设.
|
||||
|
||||
最直接的办法就是将 %p 的打印全部处理掉.
|
||||
|
||||
1. 没必要的从内核中删除掉
|
||||
|
||||
2. 有必要但是可以限制的限制下(比如替换成 %pK).
|
||||
|
||||
3. 特殊流程下, 要绕过限制直接打印实际地址的, 不做修改(比如 crash 流程输出 PANIC 日志的时候, 有必要输出实际地址.).
|
||||
|
||||
但是这些打印太多了, 改起来太麻烦了. 因此社区讨论后, 提出了一种新的方案.
|
||||
|
||||
1. 限制 %p 的输出, 不再输出实际的地址, 而是输出一个散列化的地址.
|
||||
|
||||
2. 想要在 crash 等流程输出实际地址时, 则使用 %px 输出内核符号的实际地址.
|
||||
|
||||
这样不用繁多的删动 %p 打印, 只需要限制 %p 的输出即可. 对于那些有必要输出实际地址的流程, 将 %p 替换为 %px, 这种路径通常是极少的, 改动起来也很少.
|
||||
|
||||
### 3.2.2 对 %pK 输出的影响
|
||||
-------
|
||||
|
||||
那么在 %p 的输出被散列的情况下, 对 %pK 输出的影响是什么呢?
|
||||
首先我们看下实现
|
||||
|
||||

|
||||
|
||||
```cpp
|
||||
// https://elixir.bootlin.com/linux/v5.1/source/lib/vsprintf.c#L1481
|
||||
static noinline_for_stack
|
||||
char *restricted_pointer(char *buf, char *end, const void *ptr,
|
||||
struct printf_spec spec)
|
||||
{
|
||||
switch (kptr_restrict) {
|
||||
case 0:
|
||||
/* Always print %pK values */
|
||||
break;
|
||||
case 1: {
|
||||
const struct cred *cred;
|
||||
|
||||
/*
|
||||
* kptr_restrict==1 cannot be used in IRQ context
|
||||
* because its test for CAP_SYSLOG would be meaningless.
|
||||
*/
|
||||
if (in_irq() || in_serving_softirq() || in_nmi()) {
|
||||
if (spec.field_width == -1)
|
||||
spec.field_width = 2 * sizeof(ptr);
|
||||
return string(buf, end, "pK-error", spec);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only print the real pointer value if the current
|
||||
* process has CAP_SYSLOG and is running with the
|
||||
* same credentials it started with. This is because
|
||||
* access to files is checked at open() time, but %pK
|
||||
* checks permission at read() time. We don't want to
|
||||
* leak pointer values if a binary opens a file using
|
||||
* %pK and then elevates privileges before reading it.
|
||||
*/
|
||||
cred = current_cred();
|
||||
if (!has_capability_noaudit(current, CAP_SYSLOG) ||
|
||||
!uid_eq(cred->euid, cred->uid) ||
|
||||
!gid_eq(cred->egid, cred->gid))
|
||||
ptr = NULL;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
default:
|
||||
/* Always print 0's for %pK */
|
||||
ptr = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return pointer_string(buf, end, ptr, spec);
|
||||
}
|
||||
```
|
||||
|
||||
| kptr_restrict | 实现 | 输出 |
|
||||
|:-------------:|:---:|:----:|
|
||||
| 0 | 不做任何处理, 直接 pointer_string 输出 | 不限制, 所有用户都可以看到实际地址 |
|
||||
| 1 | 如果有权限(root 用户等), 直接 pointer_string 输出, 否则置 NULL | 部分限制, 普通用户看到全 0, root 等用户看到实际地址 |
|
||||
| 2 | 直接置 NULL | 全限制, 任何用户都看到全 0 |
|
||||
|
||||
想要详细了解具体实现的, 可以直接查阅该特性合入时的 [patchwork ("hash addresses printed with %p")](https://lore.kernel.org/patchwork/cover/856356) 或者 [commit 57e734423add ("vsprintf: refactor %pK code out of pointer()")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=57e734423adda83f3b05505875343284efe3b39c).
|
||||
, 可以直接查看 [`restricted_pointer 函数, v5.1, Line 1481`](https://elixir.bootlin.com/linux/v5.1/source/lib/vsprintf.c#L1481).
|
||||
|
||||
上面的提交是最早一版本实现, 后来 Linus 提交了 [commit ef0010a30935 ("vsprintf: don't use 'restricted_pointer()' when not restricting")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ef0010a30935de4e0211cbc7bdffc30446cdee9b).
|
||||
|
||||
```cpp
|
||||
static noinline_for_stack
|
||||
char *pointer(const char *fmt, char *buf, char *end, void *ptr,
|
||||
struct printf_spec spec)
|
||||
{
|
||||
// ......
|
||||
case 'K':
|
||||
if (!kptr_restrict)
|
||||
break;
|
||||
return restricted_pointer(buf, end, ptr, spec);
|
||||
// ......
|
||||
|
||||
/* default is to _not_ leak addresses, hash before printing */
|
||||
return ptr_to_id(buf, end, ptr, spec);
|
||||
}
|
||||
```
|
||||
|
||||
这个提交在发现如果 kptr_restrict 为 0 的时候, 就不再走 restricted_pointer() 流程, 而是走标准的 %p 格式处理流程, 这个会打印散列的地址. 这本身是合理的, 但是 kptr_restrict 的影响发生了变化. 当然只是 kptr_restrict == 0 时, 等同于 %p, 输出的是散列地址.
|
||||
|
||||
|
||||
| kptr_restrict | 实现 | 输出 |
|
||||
|:-------------:|:---:|:----:|
|
||||
| 0 | 不做任何处理, 直接跳过 restricted_pointer() 流程, 使用 ptr_to_id() 输出散列地址 | 限制, 所有用户都可以看到散列地址, 相当于 %p 输出. |
|
||||
| 1 | 如果有权限(root 用户等), 直接 pointer_string() 输出, 否则置 NULL | 部分限制, 普通用户看到全 0, root 等用户看到实际地址 |
|
||||
| 2 | 直接置 NULL | 全限制, 任何用户都看到全 0 |
|
||||
|
||||
但是大家发现没发现, 上面的补丁其实有个问题, 存在一个空隙. 如果在处理 %pK 输出
|
||||
|
||||
1. 在走到 pointer 的时候, 判断 kptr_restrict 不为 0, 走到 restricted_pointer() 流程.
|
||||
|
||||
2. restricted_pointer() 流程中, 如果会继续检查 kptr_restrict 的值, 去做不同的处理.
|
||||
|
||||
这里就有间隙了. 前后两次判断 kptr_restrict 的过程中, 并没有加锁, 因此如果前后读取的过程中 kptr_restrict 的值被修改了, 那么行为会变的很奇怪. 因为在 restricted_pointer 流程中, 如果发现 kptr_restrict 为 0, 则是直接用 pointer_string() 输出了实际地址的. 而如果在 restricted_pointer 函数外面, 则等同于 %p, 输出的散列地址. 可见不同时机 %pK 的输出在 kptr_restrict == 0 的时候表现竟然不一样.
|
||||
|
||||
这有两种处理办法, 一种是加锁, 让这段流程成为临界区, 互斥执行. 但是这显然没必要. 另外一种方法最简单, 不保证互斥, 只是在 restricted_pointer 流程中如果发现用户期望不限制(kptr_restrict == 0), 则同样打印散列地址.
|
||||
|
||||
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|
||||
|:----:|:----:|:---:|:----:|:---------:|:----:|
|
||||
| 2017/11/19 | Tobin C. Harding <me@tobin.cc> | [hash addresses printed with %p](https://lore.kernel.org/patchwork/cover/856356) | 内核中 %p 打印的地址会暴露内核态地址信息, 是极其不安全的, 因此限制 %p 的打印信息, 它将打印一个散列值, 并不是实际的地址. 如果想要打印实际地址, 需要显式指定 %px. | v11 ☑ 4.15-rc2 | [PatchWork](https://lore.kernel.org/patchwork/cover/856356)<br>*-*-*-*-*-*-*-* <br>[关键 commit 57e734423add](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=57e734423adda83f3b05505875343284efe3b39c) |
|
||||
| 2017/11/29 | Linus Torvalds <torvalds@linux-foundation.org> | vsprintf: don't use 'restricted_pointer()' when not restricting | 如果发现 kptr_restrict 为 0, 则直接跳过 restricted_pointer() 流程. 这个补丁将影响 kptr_restrict 为 0 时, %pK 等同于 %p 输出散列地址. | v1 4.15-rc2 | [commit ef0010a30935 ("vsprintf: don't use 'restricted_pointer()' when not restricting")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ef0010a30935de4e0211cbc7bdffc30446cdee9b) |
|
||||
| 2019/04/17 | Petr Mladek <pmladek@suse.com> | [hvsprintf: Prevent silent crashes and consolidate error handling](https://lore.kernel.org/patchwork/cover/1063203) | 修复上面补丁引入的一个小问题, 限制 restricted_pointer 中 kptr_restrict 为 0 时, 输出散列地址. | v7 ☑ 5.2-rc1 | [PatchWork](https://lore.kernel.org/patchwork/cover/1063193)<br>*-*-*-*-*-*-*-* <br>[关键 commit 1ac2f9789c4b](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1ac2f9789c4b76ad749870c25ffae0cbcd1f510f) |
|
||||
|
||||
|
||||
### 3.2.3 示例
|
||||
-------
|
||||
|
||||
我们制作一个非常简单的用例, 分别用 %p, %pK, %px 打印一下子驱动中指针指向的数组的地址(指针的值)和指针本身的地址.
|
||||
|
||||
```cpp
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
|
||||
#define SIZE 10
|
||||
int array[SIZE];
|
||||
|
||||
int *p_arr = array;
|
||||
static int __init exam_seq_init(void)
|
||||
{
|
||||
pr_info("%%p = %p, %%pK = %pK, %%px = %px\n", p_arr, p_arr, p_arr);
|
||||
pr_info("%%p = %p, %%pK = %pK, %%px = %px\n", &p_arr, &p_arr, &p_arr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exam_seq_exit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
module_init(exam_seq_init);
|
||||
module_exit(exam_seq_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
```
|
||||
|
||||
我们写个脚本, 分别在 kptr_restrict 为 0, 1, 2 时插入模块, 显示下 %p* 的输出.
|
||||
|
||||
```cpp
|
||||
#cat test.sh
|
||||
#!/bin/bash
|
||||
|
||||
dmesg -c
|
||||
|
||||
|
||||
for kptr in `seq 0 2`
|
||||
do
|
||||
echo $kptr > /proc/sys/kernel/kptr_restrict
|
||||
KPTR=`cat /proc/sys/kernel/kptr_restrict`
|
||||
echo "/proc/sys/kernel/kptr_restrict: $KPTR"
|
||||
insmod ./kptr_restrict_test.ko
|
||||
dmesg -c
|
||||
done
|
||||
```
|
||||
|
||||

|
||||
|
||||
可以看到输出的内容与我的分析一致.
|
||||
|
||||
|
||||
|
||||
### 3.2.4 v5.7 的修正
|
||||
-------
|
||||
|
||||
| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |
|
||||
|:----:|:----:|:---:|:----:|:---------:|:----:|
|
||||
| 2020/02/19 | Ilya Dryomov <idryomov@gmail.com> | [vsprintf: don't obfuscate NULL and error pointers](https://lore.kernel.org/patchwork/patch/1196790) | 同样的, 之前 NULL 指针和错误指针的输出也很混乱, 进行了归一化. | v2 ☑ 5.7-rc7 | [PatchWork](https://lore.kernel.org/patchwork/cover/1196790)<br>*-*-*-*-*-*-*-* <br>[关键 commit 7bd57fbc4a4d](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7bd57fbc4a4ddedc664cad0bbced1b469e24e921) |
|
||||
|
||||
进一步处理了 errr-ptr 和 NULL-ptr 的输出, 让在所有情况下, 显示都保持清晰, 一致.
|
||||
|
||||
```cpp
|
||||
ptr error-ptr NULL
|
||||
%p: 0000000001f8cc5b fffffffffffffff2 0000000000000000
|
||||
%pK, kptr = 0: 0000000001f8cc5b fffffffffffffff2 0000000000000000
|
||||
%px: ffff888048c04020 fffffffffffffff2 0000000000000000
|
||||
%pK, kptr = 1: ffff888048c04020 fffffffffffffff2 0000000000000000
|
||||
%pK, kptr = 2: 0000000000000000 0000000000000000 0000000000000000
|
||||
|
||||
```
|
||||
|
||||
# 4 参考
|
||||
-------
|
||||
|
||||
@@ -182,4 +432,4 @@ When kptr_restrict is set to (2), kernel pointers printed using
|
||||
|
||||
* 采用<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="知识共享许可协议" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可. 欢迎转载、使用、重新发布, 但务必保留文章署名[成坚gatieme](http://blog.csdn.net/gatieme) ( 包含链接: http://blog.csdn.net/gatieme ), 不得用于商业目的.
|
||||
|
||||
* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问,请与我联系.
|
||||
* 基于本文修改后的作品务必以相同的许可发布. 如有任何疑问, 请与我联系.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@@ -0,0 +1,407 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://excalidraw.com",
|
||||
"elements": [
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 450,
|
||||
"versionNonce": 552683567,
|
||||
"isDeleted": false,
|
||||
"id": "s_ygkG3FRv1ahkVIoxcay",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 414.25,
|
||||
"y": -192.375,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#82c91e",
|
||||
"width": 111.00000000000003,
|
||||
"height": 36.00000000000002,
|
||||
"seed": 1870171530,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"boundElementIds": [
|
||||
"hC97PmiA9GpSyZPfCGdGv",
|
||||
"3SxvWp5giaQFb8YaHyiTB",
|
||||
"QN25t4_XOP7-HRxAuV7Y2",
|
||||
"DhBK1onobgdtoteMzJ3RY",
|
||||
"EVuGS3oXm7jYXCy8DsY2V",
|
||||
"7-zXi5_a33f7uUIc7_j_9",
|
||||
"OWrGRSWgDTVld8aCb9xUP",
|
||||
"E-FoU4T3WQM9Nik2oNqPM",
|
||||
"K5G4weFlvtjSkRkqHREH2",
|
||||
"szZiIxpZJ5n5knUoyU-Tt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 221,
|
||||
"versionNonce": 67825519,
|
||||
"isDeleted": false,
|
||||
"id": "0Hga3UldDfoZg-zvVzbAY",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 424.25,
|
||||
"y": -189.375,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 80,
|
||||
"height": 27,
|
||||
"seed": 1279813654,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "round",
|
||||
"boundElementIds": [
|
||||
"QN25t4_XOP7-HRxAuV7Y2",
|
||||
"VGI_QGiy6and7H_GNB7Pc",
|
||||
"nGXxbhYzARGmuHcQu1X-m",
|
||||
"K5G4weFlvtjSkRkqHREH2",
|
||||
"szZiIxpZJ5n5knUoyU-Tt",
|
||||
"uUtqz6iqZjLmujW-TUWwG"
|
||||
],
|
||||
"fontSize": 20,
|
||||
"fontFamily": 1,
|
||||
"text": "vsnprintf",
|
||||
"baseline": 20,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top"
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 726,
|
||||
"versionNonce": 733684961,
|
||||
"isDeleted": false,
|
||||
"id": "1yIXzrgDu_Y-3KB8OraLv",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 472.75,
|
||||
"y": -99.875,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#15aabf",
|
||||
"width": 296.99999999999994,
|
||||
"height": 36.99999999999998,
|
||||
"seed": 1222790218,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"boundElementIds": [
|
||||
"hC97PmiA9GpSyZPfCGdGv",
|
||||
"3SxvWp5giaQFb8YaHyiTB",
|
||||
"K5G4weFlvtjSkRkqHREH2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 563,
|
||||
"versionNonce": 2063149455,
|
||||
"isDeleted": false,
|
||||
"id": "_tWQGmwtx0m11a2BVdQ3I",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 479.75,
|
||||
"y": -94.875,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 284,
|
||||
"height": 27,
|
||||
"seed": 1718547798,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "round",
|
||||
"boundElementIds": [
|
||||
"EVuGS3oXm7jYXCy8DsY2V",
|
||||
"_vUFgioABe191JEmcUjY2",
|
||||
"z7YM5rJ0BgMPL8eaXkxtS",
|
||||
"K5G4weFlvtjSkRkqHREH2",
|
||||
"uDp2m25cLFz65IObaCZFH",
|
||||
"HgJeBMwls67bGFfkIpmbO",
|
||||
"szZiIxpZJ5n5knUoyU-Tt",
|
||||
"uUtqz6iqZjLmujW-TUWwG"
|
||||
],
|
||||
"fontSize": 20,
|
||||
"fontFamily": 1,
|
||||
"text": " format_decode(fmt, &spec);",
|
||||
"baseline": 20,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top"
|
||||
},
|
||||
{
|
||||
"type": "arrow",
|
||||
"version": 251,
|
||||
"versionNonce": 646848673,
|
||||
"isDeleted": false,
|
||||
"id": "YcCfbsKqX2VS1g1P_bC-m",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 440.25,
|
||||
"y": -34.375,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#82c91e",
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"seed": 874918666,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"boundElementIds": [],
|
||||
"startBinding": null,
|
||||
"endBinding": null,
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow"
|
||||
},
|
||||
{
|
||||
"type": "rectangle",
|
||||
"version": 996,
|
||||
"versionNonce": 1767536111,
|
||||
"isDeleted": false,
|
||||
"id": "8sqnW8in7QxJOaJy5OkQt",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 527.75,
|
||||
"y": -4.875,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#7950f2",
|
||||
"width": 94,
|
||||
"height": 37.00000000000002,
|
||||
"seed": 785504918,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"boundElementIds": [
|
||||
"hC97PmiA9GpSyZPfCGdGv",
|
||||
"3SxvWp5giaQFb8YaHyiTB"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"version": 202,
|
||||
"versionNonce": 1897962497,
|
||||
"isDeleted": false,
|
||||
"id": "-4u6DA6dGnCv6UuQmuSa_",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 536.75,
|
||||
"y": -1.625,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 69,
|
||||
"height": 27,
|
||||
"seed": 1136607690,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"boundElementIds": [
|
||||
"PEkbChJpyoyo7kyU5mOEJ",
|
||||
"uDp2m25cLFz65IObaCZFH",
|
||||
"HgJeBMwls67bGFfkIpmbO",
|
||||
"6VA_aq8-ThvWPAmCT491Z",
|
||||
"0wEPaK9Ydjv8-rscbi7La"
|
||||
],
|
||||
"fontSize": 20,
|
||||
"fontFamily": 1,
|
||||
"text": "pointer",
|
||||
"baseline": 20,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top"
|
||||
},
|
||||
{
|
||||
"type": "arrow",
|
||||
"version": 459,
|
||||
"versionNonce": 1445234287,
|
||||
"isDeleted": false,
|
||||
"id": "HgJeBMwls67bGFfkIpmbO",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": 489.75,
|
||||
"y": -63.625000000000014,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "#fa5252",
|
||||
"width": 48.98127691785427,
|
||||
"height": 74.60905669308931,
|
||||
"seed": 1627182922,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"boundElementIds": [],
|
||||
"startBinding": {
|
||||
"elementId": "_tWQGmwtx0m11a2BVdQ3I",
|
||||
"focus": 0.8845543560970208,
|
||||
"gap": 4.249999999999986
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "-4u6DA6dGnCv6UuQmuSa_",
|
||||
"focus": -0.1623781111499215,
|
||||
"gap": 9.018723082145698
|
||||
},
|
||||
"points": [
|
||||
[
|
||||
1.2453192294635667,
|
||||
0
|
||||
],
|
||||
[
|
||||
-11,
|
||||
70.62633390758259
|
||||
],
|
||||
[
|
||||
37.98127691785427,
|
||||
74.60905669308931
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow"
|
||||
},
|
||||
{
|
||||
"id": "s9oeJ5dFDmf6hA4KoMn9V",
|
||||
"type": "text",
|
||||
"x": 531,
|
||||
"y": -33,
|
||||
"width": 326,
|
||||
"height": 22,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"seed": 833389999,
|
||||
"version": 142,
|
||||
"versionNonce": 1331365423,
|
||||
"isDeleted": false,
|
||||
"boundElementIds": [
|
||||
"HgJeBMwls67bGFfkIpmbO"
|
||||
],
|
||||
"text": "%p* 格式对应的 case 为 FORMAT_TYPE_PTR:",
|
||||
"fontSize": 16,
|
||||
"fontFamily": 1,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"baseline": 16
|
||||
},
|
||||
{
|
||||
"id": "pXcS57X3P7KBcARXuSqkC",
|
||||
"type": "text",
|
||||
"x": 476,
|
||||
"y": -126,
|
||||
"width": 109,
|
||||
"height": 22,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"seed": 2084611503,
|
||||
"version": 241,
|
||||
"versionNonce": 744683585,
|
||||
"isDeleted": false,
|
||||
"boundElementIds": [
|
||||
"HgJeBMwls67bGFfkIpmbO"
|
||||
],
|
||||
"text": "解析格式串 fmt",
|
||||
"fontSize": 16,
|
||||
"fontFamily": 1,
|
||||
"textAlign": "left",
|
||||
"verticalAlign": "top",
|
||||
"baseline": 16
|
||||
},
|
||||
{
|
||||
"id": "uUtqz6iqZjLmujW-TUWwG",
|
||||
"type": "arrow",
|
||||
"x": 435,
|
||||
"y": -155,
|
||||
"width": 41.00004383696145,
|
||||
"height": 76.03127348853828,
|
||||
"angle": 0,
|
||||
"strokeColor": "#000000",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"strokeSharpness": "sharp",
|
||||
"seed": 988281345,
|
||||
"version": 105,
|
||||
"versionNonce": 1240548097,
|
||||
"isDeleted": false,
|
||||
"boundElementIds": null,
|
||||
"points": [
|
||||
[
|
||||
-0.35555165893675955,
|
||||
0
|
||||
],
|
||||
[
|
||||
-4,
|
||||
76.03127348853826
|
||||
],
|
||||
[
|
||||
37.00004383696145,
|
||||
76.03127348853826
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "0Hga3UldDfoZg-zvVzbAY",
|
||||
"focus": 0.7037386910089231,
|
||||
"gap": 7.375
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "_tWQGmwtx0m11a2BVdQ3I",
|
||||
"focus": -0.1782424806324638,
|
||||
"gap": 7.749956163038519
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow"
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": null,
|
||||
"viewBackgroundColor": "#ffffff"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Reference in New Issue
Block a user