<?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/tags/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>Wed, 01 Sep 2021 11:42:02 +0800</lastBuildDate><atom:link href="https://hangyan.github.io/tags/kernel/index.xml" rel="self" type="application/rss+xml"/><item><title>Rebuild Kernel 生成 BTF 文件</title><link>https://hangyan.github.io/post/2021-kernel-btf/</link><pubDate>Wed, 01 Sep 2021 11:42:02 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2021-kernel-btf/</guid><description>&lt;p&gt;在测试 golang + libbpf + ebpf 的时候发现一个问题，load ebpf object时，报错说找不到 BTF 文件。这个很奇怪，我已经 include 了 &lt;code&gt;vmlinux.h&lt;/code&gt;, 按说不应该再依赖于 BTF 文件。看了下 libbpf 的代码,大概出错的地方在:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * Probe few well-known locations for vmlinux kernel image and try to load BTF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * data out of it to use for target BTF.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;btf&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;btf__load_vmlinux_btf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;path_fmt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;raw_btf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* try canonical vmlinux BTF through sysfs first */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/sys/kernel/btf/vmlinux&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* raw BTF */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* fall back to trying to find vmlinux ELF on disk otherwise */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/boot/vmlinux-%1$s&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/lib/modules/%1$s/vmlinux-%1$s&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/lib/modules/%1$s/build/vmlinux&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/usr/lib/modules/%1$s/kernel/vmlinux&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/usr/lib/debug/boot/vmlinux-%1$s&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/usr/lib/debug/boot/vmlinux-%1$s.debug&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/usr/lib/debug/lib/modules/%1$s/vmlinux&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PATH_MAX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;utsname&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;btf&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;btf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;uname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;ARRAY_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;snprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PATH_MAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;path_fmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;R_OK&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;raw_btf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;btf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;btf__parse_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;btf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;btf__parse_elf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;libbpf_get_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;btf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;pr_debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;loading kernel BTF &amp;#39;%s&amp;#39;: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;btf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;pr_warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;failed to find valid kernel BTF&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;libbpf_err_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ESRCH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;猜测是用到了 CO-RE 相关的功能，走到了这块逻辑。奇怪的是我已经通过 &lt;code&gt;ddeb&lt;/code&gt; repo安装了相关的 vmlinux 文件。但还是不行。这个后续还是要查查，比较快的解决方案就是 rebuild kernel 带上 BTF 先跑通。&lt;/p&gt;</description></item><item><title>eBPF系列2 - XDP</title><link>https://hangyan.github.io/post/2020-11-17-ebpf-2-xdp/</link><pubDate>Tue, 17 Nov 2020 23:16:48 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2020-11-17-ebpf-2-xdp/</guid><description>&lt;p&gt;XDP是指 &lt;code&gt;eXpress data path&lt;/code&gt;, 基于 ebpf 技术上的 高性能 data path. 其主要的意图是在网络 packet 处理的早期(网卡驱动处, 在数据包到达RX queue之后, 用hook的方式)，让用户可以编写 ebpf 程序来进行一些决策。 这个hook的位置早于所有的内存分配时期(sk_buffer)，也没有上下文切换,系统调用等开销, 所以对于性能的提升是很明显的。测试数据表明，在普通的硬件上， XDP 可以 dop 大概 2600w packets per cpu.&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://hangyan.github.io/images/ebpf/xdp-1.png"&gt;&lt;/p&gt;
&lt;p&gt;一个网络包的处理流程大致如下:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;网络包到达网卡&lt;/li&gt;
&lt;li&gt;从 NIC queue 拷贝到内存(DMA-backed ring buffer)中&lt;/li&gt;
&lt;li&gt;网卡驱动使用 NAPI look 触发 soft IRQs&lt;/li&gt;
&lt;li&gt;per cpu 特定线程处理网络包&lt;/li&gt;
&lt;li&gt;分配 socket_buffer(sk_buffer), 作为网络包的基本数据结构&lt;/li&gt;
&lt;li&gt;kernel 填充 metadata, clone sk_buffer 并且交给上层网络处理层&lt;/li&gt;
&lt;li&gt;IP layer 做校验, netfilter hook 处理&lt;/li&gt;
&lt;li&gt;如果 netfilter 未 drop 此包,交给更上层网络层处理&lt;/li&gt;
&lt;li&gt;&amp;hellip;.&lt;/li&gt;
&lt;li&gt;最终数据被 copy 到 userspace (recv,read,poll等网络调用获取)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;其中, XDP hook 在数据到达 NIC RX queue 之后即触发(上面第二步之后).而 iptables 等的处理(上面第八步之后)非常靠后, 需要分配大量资源来处理网络包.&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>