<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Kernel on 涯余的博客</title><link>https://hangyan.github.io/categories/kernel/</link><description>Recent content in Kernel on 涯余的博客</description><generator>Hugo</generator><language>zh</language><managingEditor>hang.yan@hotmail.com (涯余)</managingEditor><webMaster>hang.yan@hotmail.com (涯余)</webMaster><lastBuildDate>Fri, 27 Nov 2020 11:18:00 +0800</lastBuildDate><atom:link href="https://hangyan.github.io/categories/kernel/index.xml" rel="self" type="application/rss+xml"/><item><title>io_uring 介绍</title><link>https://hangyan.github.io/post/2020-11-27-io_uring/</link><pubDate>Fri, 27 Nov 2020 11:18:00 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2020-11-27-io_uring/</guid><description>&lt;p&gt;这几年内核带来了很多革命性的新特性。一个是 ebpf, 现在主要被广泛应用于网络处理，性能分析等领域。另一个是 io_uring, 带来了真正的全异步IO。本文将对 io_uring 做简要介绍。&lt;/p&gt;
&lt;h2 id="总览"&gt;总览&lt;/h2&gt;
&lt;p&gt;在 io_uring 之前，只有 aio 这个异步框架。为什么要重新弄一套，是因为 aio 自身限制比较多，比如:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只支持 &lt;code&gt;direct_io&lt;/code&gt;.而O_DIRECT要求bypass缓存和size对齐等，直接影响了很多场景的使用。而对buffered IO，其表现为同步。&lt;/li&gt;
&lt;li&gt;即使满足了所有异步IO的约束，有时候还是可能会被阻塞，例如，等待元数据IO，或者存储设备的请求槽位都正在使用等等。&lt;/li&gt;
&lt;li&gt;存在额外的开销，每个IO提交需要拷贝64+8字节，每个IO完成需要拷贝32字节，这在某些场景下影响很可观。在使用完成event的时候需要非常小心，否则容易丢事件。IO总是需要至少2个系统调用（submit + wait-for-completion)，在spectre/meltdown开启下性能下降非常严重。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;aio本身扩展性也很差，很多基于aio的开发也经常需要用dirty hack的方式来满足自己的需求。Linux 自己对它的评价也不好:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;So I think this is ridiculously ugly.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;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”.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>ARM指针的一些安全功能</title><link>https://hangyan.github.io/post/arm-pointer/</link><pubDate>Mon, 19 Oct 2020 13:12:59 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/arm-pointer/</guid><description>&lt;p&gt;伴随着 ARM 平台的越来越普及，Linux 内核对其的支持也逐渐丰富。而且 ARM 的设计也有很多独特的优点，本文将介绍在 ARM 平台关于指针操作的一些安全方面的设计。&lt;/p&gt;
&lt;h2 id="pointer-authentication"&gt;Pointer Authentication&lt;/h2&gt;
&lt;p&gt;很多攻击都是通过骇客设计的不安全指针进行的。比如 &lt;code&gt;buffer-overflow&lt;/code&gt; 和 &lt;code&gt;return-oriented programming&lt;/code&gt;, 都是通过在返回地址放置一个指针来进行的。内核已经针对这个问题做了很多改善，ARM 提供了 &lt;code&gt;pointer authentication&lt;/code&gt; 来检测和拒绝这种插入的非法指针。&lt;/p&gt;
&lt;p&gt;简单来说，就是在指针上附加一个签名，要想使用一个指针，先得签名验证通过。如果是外部的攻击者，它没法伪造这种签名，那么自己就不能制造指针来进行攻击了。&lt;/p&gt;
&lt;p&gt;目前一般指针都是64位，但一般都不是所有bit都是用了。ARM64的系统，如果是三级页表，那么只有低位的40bit用来存放地址，那么其他的bit就可以用来干其他事情。 签名一般是通过以下几个参数确定:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pointer 本身&lt;/li&gt;
&lt;li&gt;process context 里的一个 secret key, kernel生成 这个肯定是攻击者无法获取到的&lt;/li&gt;
&lt;li&gt;current stack pointer。防止签名过的pointer泄露被复用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用的话，需要先重新计算一下签名，确保二者对的上，然后把签名部署的数据清理掉，这时候就是一个正常的指针了。不然的话，就认为其非法。&lt;/p&gt;
&lt;h2 id="memory-tagging"&gt;Memory Tagging&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Memory Tagging&lt;/code&gt;的做法与&lt;code&gt;Pointer Authentication&lt;/code&gt;类似，都是利用指针里未利用的 bits 去存储一些信息。&lt;code&gt;Memory Tagging&lt;/code&gt; 是利用 4bit 的信息存储了一个 key, 同时在 pointer 指向的内存地址里也存储了同样的 key. 当对指针进行解引用操作时，需要对比 pointer 里的 key 与实际内存地址里的 key 是否一致。如果不一致将会报错。这个功能有以下用处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;被释放的内存可以修改其 key, 防止被二次引用&lt;/li&gt;
&lt;li&gt;每个 stack frame 分配一个 key, 越界访问也会报错&lt;/li&gt;
&lt;li&gt;野指针也能检测到&lt;/li&gt;
&lt;li&gt;&amp;hellip;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些 keys 可以用应用层来管理，也可以用 CPU 来随机生成。当用应用层来管理的时候，可以提前检测出内存方便的 bug.&lt;/p&gt;</description></item><item><title>KARL, ASLR, KASLR</title><link>https://hangyan.github.io/post/2019-08-27-karl-aslr/</link><pubDate>Tue, 27 Aug 2019 11:11:23 +0000</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2019-08-27-karl-aslr/</guid><description>&lt;!-- toc --&gt;
&lt;p&gt;前段时间在零星地看一些关于 unikerel 的文章。里面提到的一些安全相关的技术非常有趣，就又开始转向 kernel 安全这部分。本文主要探讨的是 KARL, KASLR 以及 ASLR 相关的技术。&lt;/p&gt;
&lt;p&gt;安全相关的实现技术很多，但想了想，大体的分类可以归为以下几类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RWX 权限检查&lt;/li&gt;
&lt;li&gt;随机化: 尽量不用确定性的内存地址&lt;/li&gt;
&lt;li&gt;暴露最少的信息: 日志，输出里尽量不暴露相关信息&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;KARL, KASLR 以及 ASLR 都属于第二类。尽量让应用程序以及内核在内存中的地址随机化，这样攻击者就难以猜出相关的地址。&lt;/p&gt;
&lt;p&gt;简单来讲， ASLR(Address-space layout randomization) 主要是指内存中用户层的地址随机化，KASLR 是指内存中内核的地址随机化， 而 KARL(kernel adress randomized link)是指内核本身的地址随机化。ASLR出现的时间更早一些，更成熟一些。&lt;/p&gt;
&lt;p&gt;注意有一个区别， 三者中都有一个 &lt;code&gt;L&lt;/code&gt;，但意义不一样。 ASLR/KASLR 中的 &lt;code&gt;L&lt;/code&gt; 是指 &lt;code&gt;layout&lt;/code&gt;，是说内存中的布局。你不可能要求大量的应用程序自己去考虑随机化，而是在应用程序无感知的情况下，由内核来选择一个随机的位置来运行应用程序。而 KARL 中的 &lt;code&gt;L&lt;/code&gt; 是指 &lt;code&gt;link&lt;/code&gt; ，是在链接阶段就做好了地址的随机化处理，这样就不需要再内存中在做了。&lt;/p&gt;
&lt;h2 id="aslr"&gt;ASLR&lt;/h2&gt;
&lt;p&gt;ASLR 理解起来相对更为简单，本身不需要再重复介绍。&lt;/p&gt;
&lt;h3 id="rng"&gt;RNG&lt;/h3&gt;
&lt;p&gt;不管是 KARL / ASLR / KASLR，其核心都是一个&lt;code&gt;随机&lt;/code&gt;的概念。明显它依赖于随机数的生成算法。当然随机程度越高越安全，但是又要考内核的性能。这个平衡很难掌握，选择哪个 RNG(random number generation) 也经过了很多讨论。&lt;/p&gt;
&lt;p&gt;一开始用的是 &lt;code&gt;get_random_int()&lt;/code&gt;,一个性能比较好但安全性不够好的方法，后来有人提出用 &lt;code&gt;get_random_bytes()&lt;/code&gt;,安全性大大提高，但是性能下降也比较多。再后来 Linux 自己对&lt;code&gt;get_random_int()&lt;/code&gt;做了一些改进, 增加了一些噪音进去，在不影响性能的情况下改进了随机性。这也是目前在用的方法。&lt;/p&gt;</description></item></channel></rss>