io_uring 介绍

这几年内核带来了很多革命性的新特性。一个是 ebpf, 现在主要被广泛应用于网络处理,性能分析等领域。另一个是 io_uring, 带来了真正的全异步IO。本文将对 io_uring 做简要介绍。 总览 在 io_uring 之前,只有 aio 这个异步框架。为什么要重新弄一套,是因为 aio 自身限制比较多,比如: 只支持 direct_io.而O_DIRECT要求bypass缓存和size对齐等,直接影响了很多场景的使用。而对buffered IO,其表现为同步。 即使满足了所有异步IO的约束,有时候还是可能会被阻塞,例如,等待元数据IO,或者存储设备的请求槽位都正在使用等等。 存在额外的开销,每个IO提交需要拷贝64+8字节,每个IO完成需要拷贝32字节,这在某些场景下影响很可观。在使用完成event的时候需要非常小心,否则容易丢事件。IO总是需要至少2个系统调用(submit + wait-for-completion),在spectre/meltdown开启下性能下降非常严重。 aio本身扩展性也很差,很多基于aio的开发也经常需要用dirty hack的方式来满足自己的需求。Linux 自己对它的评价也不好: So I think this is ridiculously ugly. AIO is a horrible ad-hoc design, with the main excuse being “other, less gifted people, made that design, and we are implementing it for compatibility because database people — who seldom have any shred of taste — actually use it”. ...

2020-11-27 · 4 分钟 · 693 字 · 涯余

ARM指针的一些安全功能

伴随着 ARM 平台的越来越普及,Linux 内核对其的支持也逐渐丰富。而且 ARM 的设计也有很多独特的优点,本文将介绍在 ARM 平台关于指针操作的一些安全方面的设计。 Pointer Authentication 很多攻击都是通过骇客设计的不安全指针进行的。比如 buffer-overflow 和 return-oriented programming, 都是通过在返回地址放置一个指针来进行的。内核已经针对这个问题做了很多改善,ARM 提供了 pointer authentication 来检测和拒绝这种插入的非法指针。 简单来说,就是在指针上附加一个签名,要想使用一个指针,先得签名验证通过。如果是外部的攻击者,它没法伪造这种签名,那么自己就不能制造指针来进行攻击了。 目前一般指针都是64位,但一般都不是所有bit都是用了。ARM64的系统,如果是三级页表,那么只有低位的40bit用来存放地址,那么其他的bit就可以用来干其他事情。 签名一般是通过以下几个参数确定: pointer 本身 process context 里的一个 secret key, kernel生成 这个肯定是攻击者无法获取到的 current stack pointer。防止签名过的pointer泄露被复用 使用的话,需要先重新计算一下签名,确保二者对的上,然后把签名部署的数据清理掉,这时候就是一个正常的指针了。不然的话,就认为其非法。 Memory Tagging Memory Tagging的做法与Pointer Authentication类似,都是利用指针里未利用的 bits 去存储一些信息。Memory Tagging 是利用 4bit 的信息存储了一个 key, 同时在 pointer 指向的内存地址里也存储了同样的 key. 当对指针进行解引用操作时,需要对比 pointer 里的 key 与实际内存地址里的 key 是否一致。如果不一致将会报错。这个功能有以下用处: 被释放的内存可以修改其 key, 防止被二次引用 每个 stack frame 分配一个 key, 越界访问也会报错 野指针也能检测到 …. 这些 keys 可以用应用层来管理,也可以用 CPU 来随机生成。当用应用层来管理的时候,可以提前检测出内存方便的 bug. ...

2020-10-19 · 1 分钟 · 103 字 · 涯余

KARL, ASLR, KASLR

前段时间在零星地看一些关于 unikerel 的文章。里面提到的一些安全相关的技术非常有趣,就又开始转向 kernel 安全这部分。本文主要探讨的是 KARL, KASLR 以及 ASLR 相关的技术。 安全相关的实现技术很多,但想了想,大体的分类可以归为以下几类: RWX 权限检查 随机化: 尽量不用确定性的内存地址 暴露最少的信息: 日志,输出里尽量不暴露相关信息 KARL, KASLR 以及 ASLR 都属于第二类。尽量让应用程序以及内核在内存中的地址随机化,这样攻击者就难以猜出相关的地址。 简单来讲, ASLR(Address-space layout randomization) 主要是指内存中用户层的地址随机化,KASLR 是指内存中内核的地址随机化, 而 KARL(kernel adress randomized link)是指内核本身的地址随机化。ASLR出现的时间更早一些,更成熟一些。 注意有一个区别, 三者中都有一个 L,但意义不一样。 ASLR/KASLR 中的 L 是指 layout,是说内存中的布局。你不可能要求大量的应用程序自己去考虑随机化,而是在应用程序无感知的情况下,由内核来选择一个随机的位置来运行应用程序。而 KARL 中的 L 是指 link ,是在链接阶段就做好了地址的随机化处理,这样就不需要再内存中在做了。 ASLR ASLR 理解起来相对更为简单,本身不需要再重复介绍。 RNG 不管是 KARL / ASLR / KASLR,其核心都是一个随机的概念。明显它依赖于随机数的生成算法。当然随机程度越高越安全,但是又要考内核的性能。这个平衡很难掌握,选择哪个 RNG(random number generation) 也经过了很多讨论。 一开始用的是 get_random_int(),一个性能比较好但安全性不够好的方法,后来有人提出用 get_random_bytes(),安全性大大提高,但是性能下降也比较多。再后来 Linux 自己对get_random_int()做了一些改进, 增加了一些噪音进去,在不影响性能的情况下改进了随机性。这也是目前在用的方法。 ...

2019-08-27 · 1 分钟 · 171 字 · 涯余