<feed xmlns="http://www.w3.org/2005/Atom">
    <generator>Hugo -- gohugo.io</generator>
    <title>
                Posts on
            
        
        maleadt</title>
        <link href="https://blog.maleadt.net/posts/atom.xml" rel="self" type="application/atom&#43;xml" /><link href="https://blog.maleadt.net/posts/"/>
    <updated>2019-06-26T15:42:41+02:00</updated>
    <author>
            <name>Tim Besard</name>
            </author>
    <id>https://blog.maleadt.net/posts/</id>
        
        <entry>
            <title type="html"><![CDATA[Bugs in Julia with AFL and C-Reduce]]></title>
            <link href="https://blog.maleadt.net/2018/11/16/julia_bugs/"/>
            <id>https://blog.maleadt.net/2018/11/16/julia_bugs/</id>
            
            <published>2018-11-16T00:00:00+00:00</published>
            <updated>2018-11-16T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Recently, I&rsquo;ve been looking at some existing tools to efficiently find bugs in
the Julia language implementation: <a href="http://lcamtuf.coredump.cx/afl/">American Fuzzy
Lop</a> (AFL) for fuzzing the compiler, and
<a href="https://embed.cs.utah.edu/creduce/">C-Reduce</a> for reducing test cases. In this
post, I&rsquo;ll detail the set-up and use of these tools. Skip to <a href="#demo">the bottom</a>
of this post for a demonstration.</p>

<h2 id="american-fuzzy-lop">American Fuzzy Lop</h2>

<p>Fuzzing Julia used to be impractical due to the significant start-up time of the
Julia VM, rendering typical fuzzing approaches inefficient and calling for
specialized tools such as
<a href="https://github.com/martinholters/TypeFuzz.jl">TypeFuzz.jl</a>. However, start-up
latency has been improving lately, and AFL now has some features to cope with
slow binaries.</p>

<h3 id="quick-start">Quick start</h3>

<p>Working with AFL 2.52b, the naive approach of using <code>afl-gcc</code> and <code>afl-g++</code> to
compile Julia by setting the <code>CC</code> and <code>CXX</code> build variables, results in a
functioning <code>julia</code> binary. This only instruments those parts of the compiler
that have been written in C/C++; code written in Julia is not covered.</p>

<p>To trap interesting errors, I built with <code>LLVM_ASSERTIONS=1</code> and applied the
following patch to at least detect errors in the Julia parts of the compiler:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/julia/src/gf.c</span>
<span class="gi">+++ b/julia/src/gf.c</span>
<span class="gu">@@ -280,10 +280,11 @@ jl_code_info_t *jl_type_infer(...)</span>
 jl_printf(JL_STDERR, &quot;Internal error: encountered unexpected error in runtime:\n&quot;);
 jl_static_show(JL_STDERR, jl_current_exception());
 jl_printf(JL_STDERR, &quot;\n&quot;);
 jlbacktrace(); // written to STDERR_FILENO
 linfo_src = NULL;
<span class="gi">+abort();</span>
</code></pre></div>

<p>Running the instrumented binary with <code>afl-fuzz</code> crashes the AFL forkserver. This
is due to an incompatibility with the <code>LD_BIND_NOW</code> linker option that AFL uses.
It can be disabled by specifying <code>LD_BIND_LAZY=1</code> before running the fuzzer.
Furthermore, Julia preallocates quite a bit of memory, and interesting
test-cases might take a while due to infer and compile, so I specify <code>-m 2048</code>
to use up to 2G per process and <code>-t 5000</code> to let them run for up to 5 seconds:</p>

<pre><code>$ LD_BIND_LAZY=1 afl-fuzz -i inputs/ -o outputs/
                          -m 2048 -t 5000 -- julia @@
afl-fuzz 2.52b by &lt;lcamtuf@google.com&gt;
[+] You have 16 CPU cores and 2 runnable tasks (utilization: 12%).
[+] Try parallel jobs - see docs/parallel_fuzzing.txt.
[*] Checking CPU core loadout...
[+] Found a free CPU core, binding to #4.
[*] Checking core_pattern...
[*] Checking CPU scaling governor...
[*] Setting up output directories...
[*] Scanning 'inputs'...
[+] No auto-generated dictionary tokens to reuse.
[*] Creating hard links for all input files...
[*] Validating target binary...
[+] Deferred forkserver binary detected.
[*] Attempting dry run with 'id:000000,orig:binary_trees.jl'...
[*] Spinning up the fork server...
[+] All right - fork server is up.
    len = 1324, map size = 12396, exec speed = 249839 us
[+] All test cases processed.
[+] All set and ready to roll!
</code></pre>

<p>Sadly, performance is pretty low: between 0.2 and 2 executions per second,
respectively executions that error (not crash) and succeed.</p>

<p>Let&rsquo;s try and optimize that.</p>

<h3 id="only-instrument-the-compiler">Only instrument the compiler</h3>

<p>A first trivial optimization is to only instrument code that matters.
Specifically, compiling dependencies (such as LLVM and OpenBLAS) with the system
compiler bumps the speed up a notch:</p>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>julia$ make -C deps
julia$ make <span class="nv">CC</span><span class="o">=</span>afl/afl-gcc <span class="nv">CXX</span><span class="o">=</span>afl/afl-g++
</code></pre></div>

<h3 id="fail-hard-and-fast">Fail hard and fast</h3>

<p>Fuzzing code results in lots of invalid sources getting processed by the Julia
compiler. Each of these result in a nice exception,  which relies on expensive
stack unwinding to provide back traces. We can disable this functionality by
building with <code>DISABLE_LIBUNWIND=1</code>.</p>

<p>Another costly element of errors is displaying them, as this code is not part of
the precompiled system image. This functionality, courtesy of the
<code>display_error</code> function in <code>julia/base/client.jl</code>, is easily disabled by
preloading a file that redefines the relevant methods:</p>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>$ cat fuzz.jl
Base.display_error<span class="o">(</span>er, bt<span class="o">)</span> <span class="o">=</span> println<span class="o">(</span><span class="s2">&quot;ERROR&quot;</span><span class="o">)</span>
$ julia -L fuzz.jl -e <span class="s2">&quot;error()&quot;</span>
ERROR
</code></pre></div>

<p>The above also applies to deprecation warnings, but those can be disabled more
easily by passing <code>--depwarn=no</code> to Julia.</p>

<h3 id="deferred-fork-server">Deferred fork server</h3>

<p>Much of the time launching Julia is spent setting-up libraries, initializing
code generation, etc. This recurring cost can be avoided by using a deferred
fork server, where AFL starts the binary at a manually-specified point during
execution. In the case of Julia, this would be right before loading the input
file:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/julia/ui/repl.c</span>
<span class="gi">+++ b/julia/ui/repl.c</span>
<span class="gu">@@ -89,6 +89,10 @@ static NOINLINE int true_main(int argc, char *argv[])</span>
     jl_function_t *start_client = jl_base_module ?
         (jl_function_t*)jl_get_global(jl_base_module, jl_symbol(&quot;_start&quot;)) : NULL;
 
<span class="gi">+#ifdef __AFL_HAVE_MANUAL_CONTROL</span>
<span class="gi">+  __AFL_INIT();</span>
<span class="gi">+#endif</span>
<span class="gi">+</span>
     if (start_client) {
</code></pre></div>

<p>This approach relies on the binary being compiled with AFL&rsquo;s LLVM instrumenter,
available as <code>afl-clang-fast</code> and <code>afl-clang-fast++</code> for compiling respectively
C and C++ code, again specified using the <code>CC</code> and <code>CXX</code> build variables. Note
that this instrumentation seems incompatible with OpenBLAS, so if you were to
instrument dependencies you would need to compile that library using a regular
compiler.</p>

<p>Use of the deferred fork server necessitated several changes. For one, the
symbols AFL defines need to be exported globally:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/julia/src/julia.expmap</span>
<span class="gi">+++ b/julia/src/julia.expmap</span>
<span class="gu">@@ -1,5 +1,6 @@</span>
 {
   global:
<span class="gi">+    __afl*;</span>
</code></pre></div>

<p>Furthermore, despite the <code>__afl_manual_init</code> symbol that enables the deferred
fork server being part of the Julia binary, AFL does not pick it up and defaults
to regular forking. I did not debug this issue, and instead patched AFL to
unconditionally enter deferred mode:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/afl/afl-fuzz.c</span>
<span class="gi">+++ b/afl/afl-fuzz.c</span>
<span class="gu">@@ -6950,7 +6950,7 @@ EXP_ST void check_binary(u8* fname) {</span>
<span class="gd">-  if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {</span>
<span class="gi">+  if (1) {</span>
 
     OKF(cPIN &quot;Deferred forkserver binary detected.&quot;)
</code></pre></div>

<p>You should now see the following in the <code>afl-fuzz</code> output:</p>

<pre><code>[+] Deferred forkserver binary detected.
</code></pre>

<p>Note that the AFL documentation suggests putting the <code>__AFL_INIT</code> call <em>before</em>
the initialization of important threads, as they don&rsquo;t survive the <code>fork</code>. The
patch above does not do that, as threads are spawned by <code>restore_signals</code> as
well as different module initializers. To be safe, I built with
<code>JULIA_THREADS=0</code>, configured LLVM with <code>ENABLE_THREADS</code> unset and executed with
<code>OPENBLAS_NUM_THREADS=1</code> to reduce possible issues. Still, your mileage might
vary and you might have to move the initialization point further upwards.</p>

<h3 id="multithreaded-fuzzing">Multithreaded fuzzing</h3>

<p>With the above fixes, we go from 0.2-2 executions/s to 3-30; still considered
slow but a significant improvement nonetheless. Luckily, AFL scales pretty well
and can be easily executed across all threads of a system. This brings the final
execution speed to around 500 per second.</p>

<p>Now let&rsquo;s focus on improving fuzzing quality.</p>

<h3 id="instrumenting-julia-code">Instrumenting Julia code</h3>

<p>AFL can more accurately measure the impact of changes to inputs if all relevant
code is instrumented. Nowadays, part of the Julia compiler is written in Julia,
and compiled during initial bootstrap of the <code>julia</code> binary. Julia code is
compiled with LLVM, so we can re-use the LLVM-based instrumentation passes that
are part of AFL. However, Julia uses its own (heavily patched) version of LLVM,
so we need to recompile AFL and link against Julia&rsquo;s LLVM library:</p>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>afl/llvm_mode$ <span class="nv">PATH</span><span class="o">=</span>julia/usr/tools:<span class="nv">$PATH</span> make
<span class="c1"># building the tests will fail</span>
</code></pre></div>

<p>In order to use this pass, which is now linked against Julia&rsquo;s LLVM, we need a
compatible build of Clang that can load the instrumentation pass. We can do so
by rebuilding Julia&rsquo;s copy of LLVM with the <code>BUILD_LLVM_CLANG</code> variable set:</p>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>julia$ make -C deps <span class="nv">BUILD_LLVM_CLANG</span><span class="o">=</span><span class="m">1</span>

<span class="c1"># we can now run AFL&#39;s tests</span>
afl/llvm_mode$ <span class="nv">PATH</span><span class="o">=</span>julia/usr/tools:<span class="nv">$PATH</span> make
</code></pre></div>

<p>AFL needs to be modified to expose its instrumentation pass:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/afl/llvm_mode/afl-llvm-pass.so.cc</span>
<span class="gi">+++ b/afl/llvm_mode/afl-llvm-pass.so.cc</span>
<span class="gu">@@ -177,6 +177,10 @@</span>
<span class="gi">+namespace llvm {</span>
<span class="gi">+Pass *createAFLCoveragePass() {</span>
<span class="gi">+  return new AFLCoverage();</span>
<span class="gi">+}</span>
<span class="gi">+};</span>
</code></pre></div>

<p>The following changes make Julia use these instrumentation passes:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/julia/src/Makefile</span>
<span class="gi">+++ b/julia/src/Makefile</span>
<span class="gu">@@ -95,6 +95,8 @@</span>
 endif # USE_LLVM_SHLIB == 1
 endif

<span class="gi">+LLVMLINK += afl/afl-llvm-pass.so</span>
</code></pre></div>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/julia/src/jitlayers.cpp</span>
<span class="gi">+++ b/julia/src/jitlayers.cpp</span>
<span class="gu">@@ -32,6 +32,7 @@</span>
 namespace llvm {
     extern Pass *createLowerSimdLoopPass();
<span class="gi">+    extern Pass *createAFLCoveragePass();</span>
 }

<span class="gu">@@ -230,6 +231,8 @@ void addOptimizationPasses(...)</span>
<span class="gi">+    PM-&gt;add(createAFLCoveragePass());</span>
 }
</code></pre></div>

<p>Now build Julia while pointing AFL to the compatible <code>clang</code> binary:</p>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>julia$ <span class="nb">export</span> <span class="nv">AFL_CC</span><span class="o">=</span>julia/usr/tools/clang
julia$ <span class="nb">export</span> <span class="nv">AFL_CXX</span><span class="o">=</span>julia/usr/tools/clang++
julia$ make <span class="nv">CC</span><span class="o">=</span>afl/afl-clang-fast <span class="nv">CXX</span><span class="o">=</span>afl/afl-clang-fast++
</code></pre></div>

<p>For some reason, compiled Julia code uses AFL&rsquo;s <code>afl_prev_loc</code> TLS variable
differently then how it is defined in the contained binary (instead using
<code>__emutls_v.__afl_prev_loc</code>). I worked around this issue by changing the
definition to a regular variable, since we&rsquo;re not using threads anyway:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/afl/llvm_mode/afl-llvm-rt.o.c</span>
<span class="gi">+++ b/afl/llvm_mode/afl-llvm-rt.o.c</span>
<span class="gu">@@ -52,7 +52,7 @@</span>
<span class="gd">-__thread u32 __afl_prev_loc;</span>
<span class="gi">+u32 __afl_prev_loc;</span>
</code></pre></div>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/afl/llvm_mode/afl-llvm-pass.so.cc</span>
<span class="gi">+++ b/afl/llvm_mode/afl-llvm-pass.so.cc</span>
<span class="gu">@@ -101,8 +101,7 @@ bool AFLCoverage::runOnModule(Module &amp;M) {</span>
 GlobalVariable *AFLPrevLoc = new GlobalVariable(
<span class="gd">-M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, &quot;__afl_prev_loc&quot;,</span>
<span class="gd">-0, GlobalVariable::GeneralDynamicTLSModel, 0, false);</span>
<span class="gi">+M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, &quot;__afl_prev_loc&quot;);</span>
</code></pre></div>

<p>Make sure to rebuild all of Julia after applying this patch.</p>

<p>We can now compare the generated code with and without instrumentation:</p>

<pre><code>--- julia-original     -e &quot;@code_llvm sin(1.)&quot;
+++ julia-instrumented -e &quot;@code_llvm sin(1.)&quot;
 L4:                                               ; preds = %top
 ; Location: special/trig.jl:32
 ; Function &lt;; {
 ; Location: float.jl:452
-  %4 = fcmp uge double %2, 0x3E50000000000000
+  %10 = load i32, i32* @__afl_prev_loc
+  %11 = load i8*, i8** @__afl_area_ptr
+  %12 = xor i32 %10, 56933
+  %13 = getelementptr i8, i8* %11, i32 %12
+  %14 = load i8, i8* %13
+  %15 = add i8 %14, 1
+  store i8 %15, i8* %13
+  store i32 28466, i32* @__afl_prev_loc
+  %16 = fcmp uge double %8, 0x3E50000000000000
 ;}
</code></pre>

<h3 id="dictionary-for-julia-code">Dictionary for Julia code</h3>

<p>A dictionary makes it easier for AFL to explore verbose grammars such as
programming languages. I created a <a href="https://gist.github.com/maleadt/30b07f9ce0ccedbba01477dac52613c1">dictionary for
Julia</a>, with
most keywords, important operators, and common syntax such as values and
definitions. You can use this dictionary by passing <code>-x julia.dict</code> to
<code>afl-fuzz</code>.</p>

<h2 id="test-case-reduction">Test-case reduction</h2>

<p>Although AFL provides a test-case minimizer (<code>afl-tmin</code>), I decided to look into
a independent tool. <a href="https://embed.cs.utah.edu/creduce/">C-Reduce</a> is such a
tool, blindly reducing test cases based on a user-specified condition. As such,
it is more flexible, and independent from the complicated set-up from above.</p>

<p>Using C-Reduce is fairly simple: provide a script whose return code indicates
the state of the current test case, and run it over some files. I&rsquo;ve created
some scripts that improve integration with Julia and its code loading mechanism:
<a href="https://github.com/maleadt/creduce_julia">maleadt/creduce_julia</a>. For more
information, refer to the repository&rsquo;s README, or have a look at <a href="https://discourse.julialang.org/t/ann-automatic-test-case-reduction/17700">this Discourse
thread</a>.</p>

<h2 id="demo">Demo</h2>

<p>After running AFL for about a day on a 16-core machine, <code>afl-whatsup</code> reported
the following:</p>

<pre><code>$ afl-whatsup -s outputs/
status check tool for afl-fuzz by &lt;lcamtuf@google.com&gt;

Summary stats
=============

       Fuzzers alive : 16
      Total run time : 13 days, 9 hours
         Total execs : 3 million
    Cumulative speed : 42 execs/sec
       Pending paths : 2023 faves, 62710 total
  Pending per fuzzer : 126 faves, 3919 total (on average)
       Crashes found : 1 locally unique
</code></pre>

<p>We found a crash! The actual input is written in one of the <code>crashes</code>
subdirectories, and contained the following code:</p>
<div class="highlight"><pre><code class="language-julia" data-lang="julia"><span></span><span class="k">abstract</span> <span class="k">type</span> <span class="n">BTree</span> <span class="k">end</span>

<span class="k">mutable</span> <span class="k">struct</span> <span class="n">Empty</span> <span class="o">&lt;:</span> <span class="n">BTree</span>
<span class="k">end</span>

<span class="k">mutable</span> <span class="k">struct</span> <span class="n">Node</span> <span class="o">&lt;:</span> <span class="n">BTree</span>
  <span class="n">info</span>
  <span class="n">left</span><span class="o">::</span><span class="n">BTree</span>
  <span class="n">right</span><span class="o">::</span><span class="n">BTree</span>
<span class="k">end</span>

<span class="k">function</span> <span class="n">make</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
  <span class="k">if</span> <span class="n">d</span> <span class="o">==</span> <span class="mi">0</span>
    <span class="n">Node</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">Empty</span><span class="p">(),</span> <span class="n">Empty</span><span class="p">())</span>
  <span class="k">else</span>
    <span class="n">nval</span> <span class="o">=</span> <span class="n">val</span> <span class="o">*</span> <span class="mi">2</span>
    <span class="n">Node</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">make</span><span class="p">(</span><span class="n">nval</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">d</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="n">make</span><span class="p">(</span><span class="n">nval</span><span class="p">,</span> <span class="n">d</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="n">check</span><span class="p">(</span><span class="n">t</span><span class="o">::</span><span class="n">Empty</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">check</span><span class="p">(</span><span class="n">t</span><span class="o">::</span><span class="n">Node</span><span class="p">)</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">info</span> <span class="o">+</span> <span class="n">check</span><span class="p">(</span><span class="n">t</span><span class="o">.</span><span class="n">left</span><span class="p">)</span> <span class="o">-</span> <span class="n">check</span><span class="p">(</span><span class="n">t</span><span class="o">.</span><span class="n">right</span><span class="p">)</span>

<span class="k">function</span> <span class="n">loop_depths</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">min_depth</span><span class="p">,</span> <span class="n">max_depth</span><span class="p">)</span>
  <span class="k">for</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">:</span><span class="n">div</span><span class="p">(</span><span class="n">max_depth</span> <span class="o">-</span> <span class="n">d</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
    <span class="n">niter</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">max_depth</span> <span class="o">-</span> <span class="n">d</span> <span class="o">+</span> <span class="n">min_depth</span><span class="p">)</span>
    <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="o">:</span><span class="n">niter</span>
      <span class="n">c</span> <span class="o">+=</span> <span class="n">check</span><span class="p">(</span><span class="n">make</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">d</span><span class="p">))</span> <span class="o">+</span> <span class="n">check</span><span class="p">(</span><span class="n">make</span><span class="p">(</span><span class="o">-</span><span class="n">i</span><span class="p">,</span> <span class="n">d</span><span class="p">))</span>
    <span class="k">end</span><span class="p">,</span><span class="c">#@printf(&quot;%i\t trees of depth %i\t check: %i\n&quot;, 2*niter, d, c)</span>
    <span class="n">d</span> <span class="o">+=</span> <span class="mi">2</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="kd">const</span> <span class="n">N</span><span class="o">=</span><span class="mi">10</span>
<span class="n">min_depth</span> <span class="o">=</span> <span class="mi">4</span>
<span class="n">max_depth</span> <span class="o">=</span> <span class="n">N</span>
<span class="n">stretch_depth</span> <span class="o">=</span> <span class="n">max_depth</span> <span class="o">+</span> <span class="mi">1</span>

<span class="k">let</span> <span class="n">c</span> <span class="o">=</span> <span class="n">check</span><span class="p">(</span><span class="n">make</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">stretch_depth</span><span class="p">))</span>
  <span class="c">#@printf(&quot;stretch tree of depth %i\t check: %i\n&quot;, stretch_depth, c)</span>
<span class="k">end</span>

<span class="n">long_lived_tree</span> <span class="o">=</span> <span class="n">make</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">max_depth</span><span class="p">)</span>

<span class="n">loop_depths</span><span class="p">(</span><span class="n">min_depth</span><span class="p">,</span> <span class="n">min_depth</span><span class="p">,</span> <span class="n">max_depth</span><span class="p">)</span>
</code></pre></div>

<p>As you may notice, I used the BaseBenchmark&rsquo;s <a href="https://github.com/JuliaCI/BaseBenchmarks.jl/tree/master/src/shootout">shootout
benchmarks</a>
as inputs to AFL. Pasting the reduced code in a Julia REPL indeed crashes the
compiler:</p>

<pre><code>Internal error: encountered unexpected error in runtime:
BoundsError(a=Array{Core.Compiler.NewNode, (0,)}[], i=(3,))

signal (4): Illegal instruction
</code></pre>

<p>To reduce this code, I check-out
<a href="https://github.com/maleadt/creduce_julia">maleadt/creduce_julia</a> and use the
crashing code as the initial input. We need to make sure that the <code>run</code> script
successfully catches the error condition; in this case it is sufficient to
<code>grep</code> for <code>encountered unexpected error in runtime</code>:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- a/creduce_julia/run</span>
<span class="gi">+++ b/creduce_julia/run</span>
<span class="gu">@@ -30,4 +30,4 @@ JULIA_LOAD_PATH=$TEMP \</span>
<span class="gd">-julia main.jl |&amp; grep &quot;example error message&quot;</span>
<span class="gi">+julia main.jl |&amp; grep &quot;encountered unexpected error in runtime&quot;</span>
</code></pre></div>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>creduce_julia$ ./run
Internal error: encountered unexpected error in runtime:

creduce_julia$ <span class="nb">echo</span> <span class="nv">$?</span>
<span class="m">0</span>
</code></pre></div>

<p>Finally, we run the <code>reduce</code> script to kick-off the process. It will
automatically work in parallel on all available cores:</p>

<pre><code>creduce_julia$ ./reduce
===&lt; 30926 &gt;===
running 8 interestingness tests in parallel
...
===================== done ====================

pass statistics:
  method pass_balanced :: parens-inside worked 1 times and failed 2 times
  method pass_indent :: final worked 1 times and failed 0 times
  method pass_clex :: rm-toks-3 worked 1 times and failed 61 times
  method pass_lines :: 4 worked 2 times and failed 50 times
  method pass_lines :: 1 worked 2 times and failed 50 times
  method pass_clex :: rename-toks worked 2 times and failed 3 times
  method pass_blank :: 0 worked 2 times and failed 0 times
  method pass_indent :: regular worked 2 times and failed 0 times
  method pass_lines :: 8 worked 2 times and failed 50 times
  method pass_lines :: 10 worked 2 times and failed 50 times
  method pass_lines :: 6 worked 2 times and failed 50 times
  method pass_lines :: 3 worked 2 times and failed 50 times
  method pass_clex :: rm-toks-2 worked 2 times and failed 64 times
  method pass_lines :: 2 worked 2 times and failed 50 times
  method pass_balanced :: parens-to-zero worked 2 times and failed 6 times
  method pass_clex :: rm-toks-4 worked 3 times and failed 49 times
  method pass_clex :: rm-toks-13 worked 3 times and failed 18 times
  method pass_lines :: 0 worked 15 times and failed 78 times
  method pass_clex :: rm-toks-1 worked 16 times and failed 68 times
</code></pre>

<p>The above took about 2 minutes on an 4-core workstation. Doing some manual
clean-up, we end up with the issue as reported in
<a href="https://github.com/JuliaLang/julia/issues/30062">JuliaLang/julia#30062</a>:</p>
<div class="highlight"><pre><code class="language-julia" data-lang="julia"><span></span><span class="k">for</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">end</span><span class="p">,</span> <span class="n">b</span> <span class="o">+=</span> <span class="mi">2</span>
</code></pre></div>

<h2 id="future-work">Future work</h2>

<p>Although a tool like AFL <a href="https://blog.regehr.org/archives/1238">isn&rsquo;t ideal</a>
for fuzzing a compiler as done in this blogpost, the technique and its set-up
can be used to fuzz other libraries and tools that are written in Julia (eg.
HTTP.jl or Images.jl). That would of course require productionisation of this
proof-of-concept and its many workarounds.</p>

<p>A hypothetical AFL.jl package would:</p>

<ul>
<li>build AFL&rsquo;s instrumentation pass against an <a href="https://github.com/staticfloat/LLVMBuilder">LLVMBuilder
toolchain</a></li>
<li>provide native functionality a la
<a href="https://github.com/jwilk/python-afl/">python-afl</a></li>
<li>conditionally instrument code (Julia has some <a href="https://arxiv.org/abs/1712.03112">great
tools</a> for that)</li>
</ul>

<p>Fuzzing the compiler itself could also be improved:</p>

<ul>
<li>deferring the fork server even more: there&rsquo;s significant initialization done
by Julia code, and the manual initialization point could move right before the
input eval loop</li>
<li>persistent fuzzing: having AFL input new test cases without restarting the
process. Although Julia is far from stateless, AFL could be modified to verify
crashes in a fresh process.</li>
</ul>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://blog.maleadt.net/tags/julia" term="julia" label="julia" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[JuliaCon'17]]></title>
            <link href="https://blog.maleadt.net/2017/07/02/juliacon17/"/>
            <id>https://blog.maleadt.net/2017/07/02/juliacon17/</id>
            
            <published>2017-07-02T00:00:00+00:00</published>
            <updated>2017-07-02T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Last week in Berkeley, there was the annual <a href="http://juliacon.org/2017/">JuliaCon</a> where I
gave a couple of talks on the GPU infrastructure I have been working on.</p>

<p>Here&rsquo;s the material from those talks:</p>

<ul>
<li>CUDAnative.jl talk (high-level):
<a href="/juliacon17/talk_cudanative.pdf">slides</a></li>
<li>CUDAnative.jl workshop (hands-on):
<a href="/juliacon17/workshop_cudanative.ipynb">notebook</a>
(<a href="/juliacon17/workshop_cudanative.html">HTML</a>,
<a href="/juliacon17/workshop_cudanative.slides.html">slides</a>)</li>
<li>LLVM.jl lightning talk:
<a href="/juliacon17/lightningtalk_llvm.ipynb">notebook</a>
(<a href="/juliacon17/lightningtalk_llvm.html">HTML</a>,
<a href="/juliacon17/lightningtalk_llvm.slides.html">slides</a>)</li>
</ul>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://blog.maleadt.net/tags/julia" term="julia" label="julia" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Debugging Julia with Address Sanitizer]]></title>
            <link href="https://blog.maleadt.net/2017/02/24/julia-asan/"/>
            <id>https://blog.maleadt.net/2017/02/24/julia-asan/</id>
            
            <published>2017-02-24T00:00:00+00:00</published>
            <updated>2017-02-24T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><a href="https://clang.llvm.org/docs/AddressSanitizer.html">Address sanitizer</a> is a useful tool for
debugging various memory problems, from invalid accesses to mismanagement or leaks. It is
similar to <a href="http://valgrind.org/">Valgrind&rsquo;s</a>
<a href="http://valgrind.org/docs/manual/mc-manual.html">memcheck</a>, but uses compile-time
instrumentation to lower the cost.</p>

<p>In this post I&rsquo;ll explain how to use Clang&rsquo;s address sanitizer (or ASAN) with Julia. This is
somewhat tricky, as the Julia compiler uses LLVM for code generation purposes. Long story
short, this implies that all instances of LLVM (ie. the one Julia is compiled with, and the
one used for code generation) have to match up exactly for the instrumentation to work as
expected.</p>

<h2 id="llvm-toolchain">LLVM toolchain</h2>

<p>We&rsquo;ll start by building a toolchain to compile Julia with. As mentioned before, all LLVM
instances in play have to match up exactly for instrumentation to work, so we&rsquo;ll use Julia&rsquo;s
build infrastructure to generate us an LLVM toolchain.</p>

<p>Start by checking-out Julia, and creating an out-of-tree build directory:</p>
<div class="highlight"><pre><code class="language-shell" data-lang="shell"><span></span>$ git clone https://github.com/JuliaLang/julia
$ <span class="nb">cd</span> julia
$ make <span class="nv">O</span><span class="o">=</span>configure sanitize_toolchain
</code></pre></div>

<p>This build will need to provide <code>clang</code>, so create a <code>Make.user</code> containing
<code>BUILD_LLVM_CLANG=1</code>. In addition, LLVM does not build its sanitizers with autotools, so add
<code>override LLVM_USE_CMAKE=1</code> to that file as well. And because that triggers <a href="https://bugs.llvm.org/show_bug.cgi?id=23649">LLVM bug
#23649</a>, also add <code>USE_LLVM_SHLIB=0</code></p>

<p>Now execute <code>make install-llvm</code> from the <code>deps</code> subfolder. When it
finishes, check if binaries have been written to <code>usr/bin</code> (due to what&rsquo;s probably a bug in
LLVM&rsquo;s build scripts), and move them to <code>usr/tools</code> if they have.</p>

<h2 id="sanitized-julia">Sanitized Julia</h2>

<p>Now that we have a working toolchain, we&rsquo;ll use it to compile a sanitized version of the
Julia compiler and libraries. Start by creating a new out-of-tree build directory using
<code>make O=configure sanitize</code>. But this time, our <code>Make.user</code> will be significantly more
complex:</p>
<div class="highlight"><pre><code class="language-makefile" data-lang="makefile"><span></span><span class="nv">TOOLCHAIN</span><span class="o">=</span><span class="k">$(</span>BUILDROOT<span class="k">)</span>/sanitize_toolchain/usr/tools

<span class="c"># use our new toolchain</span>
<span class="nv">USECLANG</span><span class="o">=</span><span class="m">1</span>
<span class="err">override</span> <span class="nv">CC</span><span class="o">=</span><span class="k">$(</span>TOOLCHAIN<span class="k">)</span>/clang
<span class="err">override</span> <span class="nv">CXX</span><span class="o">=</span><span class="k">$(</span>TOOLCHAIN<span class="k">)</span>/clang++
<span class="k">export </span><span class="nv">ASAN_SYMBOLIZER_PATH</span><span class="o">=</span><span class="k">$(</span>TOOLCHAIN<span class="k">)</span>/llvm-symbolizer

<span class="c"># enable ASAN</span>
<span class="err">override</span> <span class="nv">SANITIZE</span><span class="o">=</span><span class="m">1</span>
<span class="err">override</span> <span class="nv">LLVM_SANITIZE</span><span class="o">=</span><span class="m">1</span>

<span class="c"># autotools doesn&#39;t have a self-sanitize mode</span>
<span class="err">override</span> <span class="nv">LLVM_USE_CMAKE</span><span class="o">=</span><span class="m">1</span>

<span class="c"># make the GC use regular malloc/frees, which are intercepted by ASAN</span>
<span class="err">override</span> <span class="nv">WITH_GC_DEBUG_ENV</span><span class="o">=</span><span class="m">1</span>

<span class="c"># default to a debug build for better line number reporting</span>
<span class="err">override</span> <span class="nv">JULIA_BUILD_MODE</span><span class="o">=</span>debug
</code></pre></div>

<p>Now kick-off the build using <code>make</code> from the <code>sanitize</code> build directory. Barring any memory
issues triggered during system image generation, this should yield a sanitized <code>julia</code>
binary and system image.</p>

<h2 id="running-the-test-suite">Running the test-suite</h2>

<p>The test-suite is a beast, and because ASAN keeps track of <em>a lot</em> of information it easily
takes over 128GiB of memory to run it to completion. Instead, we&rsquo;ll tune ASAN to consume
less memory at the expense of accuracy and report detail.</p>

<p>Julia however already configures <a href="https://github.com/JuliaLang/julia/blob/7ffd7a1a8826abfc702dc3cada8a020413722d02/src/init.c#L49-L56">default ASAN
options</a>,
which we need to copy when specifying a different set. Do so by defining the
<code>ASAN_OPTIONS</code> environment variable and assigning it the value of
<code>detect_leaks=0:allow_user_segv_handler=1:fast_unwind_on_malloc=0:malloc_context_size=2</code>.
This copies aforementioned default values, and caps backtrace collection.</p>

<h2 id="using-cuda-packages">Using CUDA packages</h2>

<p>If you thought all that was convoluted, prepare for some more. ASAN uses so-called <em>shadow memory</em> to store
information about memory allocations. There is a correspondence between regular memory
addresses and their shadow counterpart, and <a href="https://github.com/llvm-mirror/compiler-rt/blob/d595db5515003e046a98eb1616c00f2a08be6002/lib/asan/asan_mapping.h#L127-L143">this mapping is
fixed</a>
in order to <a href="https://bugs.llvm.org//show_bug.cgi?id=25466">keep the instrumentation overhead
low</a>. Sadly, the default shadow memory
location overlaps with fixed memory allocated by CUDA (presumably for its <a href="http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#unified-virtual-address-space">unified virtual
address
space</a>).</p>

<p>Because the shadow memory is fixed, we need to patch both instances of LLVM (easiest to add
a patch to <code>llvm.mk</code>) and have it pick a different shadow offset:</p>
<div class="highlight"><pre><code class="language-diff" data-lang="diff"><span></span><span class="gd">--- lib/Transforms/Instrumentation/AddressSanitizer.cpp</span>
<span class="gi">+++ lib/Transforms/Instrumentation/AddressSanitizer.cpp</span>
<span class="gu">@@ -359,7 +359,7 @@</span>
       if (IsKasan)
         Mapping.Offset = kLinuxKasan_ShadowOffset64;
       else
<span class="gd">-        Mapping.Offset = kSmallX86_64ShadowOffset;</span>
<span class="gi">+        Mapping.Offset = kDefaultShadowOffset64;</span>
     } else if (IsMIPS64)
       Mapping.Offset = kMIPS64_ShadowOffset64;
     else if (IsAArch64)
<span class="gd">--- projects/compiler-rt/lib/asan/asan_mapping.h</span>
<span class="gi">+++ projects/compiler-rt/lib/asan/asan_mapping.h</span>
<span class="gu">@@ -146,7 +146,7 @@</span>
 #  elif SANITIZER_IOS
 #    define SHADOW_OFFSET kIosShadowOffset64
 #  else
<span class="gd">-#   define SHADOW_OFFSET kDefaultShort64bitShadowOffset</span>
<span class="gi">+#   define SHADOW_OFFSET kDefaultShadowOffset64</span>
 #  endif
 # endif
 #endif
</code></pre></div>

<p>Note that you might need to redefine a different macro for your platform.</p>

<h2 id="sanitizing-older-versions-of-julia">Sanitizing older versions of Julia</h2>

<p>If you want to sanitize older versions of Julia, before the <a href="https://github.com/JuliaLang/julia/issues/19123">switch to LLVM
3.9</a>, there&rsquo;s yet other issues: only LLVM
3.9 <a href="https://bugs.llvm.org/show_bug.cgi?id=27310">is compatible</a> with recent versions of
glibc, while the CMake build system of LLVM 3.7 <a href="https://bugs.llvm.org//show_bug.cgi?id=24157">doesn&rsquo;t
export</a> all necessary public symbols. You can
work around these issues by using a sufficiently old system, and overriding the LLVM version
to 3.8 (by specifying <code>override LLVM_VER=3.8.1</code> in the <code>Make.user</code> of <strong>both</strong> build
directories) or preventing it from generating a shared library (by specifying
<code>USE_LLVM_SHLIB=0</code> in the <code>Make.user</code> of the final Julia build).</p>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://blog.maleadt.net/tags/julia" term="julia" label="julia" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Generating bmap information from images]]></title>
            <link href="https://blog.maleadt.net/2015/11/24/bmaptool-scan/"/>
            <id>https://blog.maleadt.net/2015/11/24/bmaptool-scan/</id>
            
            <published>2015-11-24T00:00:00+00:00</published>
            <updated>2015-11-24T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>When dealing with disk images, the <a href="https://source.tizen.org/documentation/reference/bmaptool/bmap-tools-project">bmap-tool
project</a>
is a godsend for writing said images to a physical device. Relying on an
accompanying <code>bmap</code> file, <code>bmaptool</code> skips unused data when copying an image.
Sadly, only few image providers bundle their images with the necessary <code>bmap</code>
information. Even though using <code>bmaptool</code> with plain images still pays off
(writing to devices is notably faster than a regular <code>dd</code>), most of its value is
lost.</p>

<h2 id="bmaptool-create">bmaptool create</h2>

<p>Although <code>bmaptool</code> features a <code>create</code> option, that mode of operation is mostly
useless as it relies on the file sparseness to extract the unused blocks.
However, sparseness has <strong>completely different semantics</strong>! Quoting
<a href="https://en.wikipedia.org/wiki/Sparse_file">Wikipedia</a>:</p>

<blockquote>
<p>When reading sparse files, the file system transparently converts metadata
representing empty blocks into &ldquo;real&rdquo; blocks filled with zero bytes at
runtime.</p>
</blockquote>

<p>When creating a <code>bmap</code> file based on image sparseness and subsequently writing
that image to a device, the previously sparse blocks will be skipped, resulting
in non-zero bytes when reading from those blocks.</p>

<h2 id="bmaptool-scan">bmaptool-scan</h2>

<p>I&rsquo;ve written <a href="https://github.com/maleadt/bmaptool-scan">a small script</a> which
scans for the <strong>actual</strong> unused blocks, i.e., based on the underlying file
system instead of the image sparseness. These blocks are truly unused, which
means we can safely skip writing them when copying an image to a device.</p>

<h3 id="usage">Usage</h3>

<pre><code># modprobe loop
# bmaptool-scan --bmap something.img | tee something.bmap
Found 1 partition(s) in image
- processing 1.7G partition at 1.0M into the image

&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;bmap version=&quot;2.0&quot;&gt;
 ...
&lt;/bmap&gt;
</code></pre>

<p>There&rsquo;s two program modes available: <code>--bmap</code> and <code>--sparse</code>. The former
generates a <code>bmap</code> file, as can be seen above. The <code>--sparse</code> option punches
holes in the input image. This can subsequently be used to generate a <code>bmap</code>
file using <code>bmaptool create</code>, or just to optimize storage of the image.</p>

<p>Note that you need to run the script as root, and you need quite some Perl
packages. See the
<a href="https://github.com/maleadt/bmaptool-scan/blob/master/README.md">README</a> for
more details.</p>

<h3 id="limitations">Limitations</h3>

<p>As the script relies on parsing the image partition table and probing any
partition found using file system specific tools, there are a few limitations:</p>

<ul>
<li>Implementation wise: adding more file systems. Currently only <code>ext4</code> is
supported, which should be trivial to extend to the entire <code>ext</code> family.
Adding support for other file systems means adding code to dump and parse the
unallocated blocks within the partition.</li>
<li>Nonstandard partition layouts (hybrid images, overlapping partitions,
&hellip;): these might break the script, or might even be unsafe to write
selectively. Use at your own risk!</li>
</ul>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Raspberry Pi music server]]></title>
            <link href="https://blog.maleadt.net/2015/07/13/pi-music-server/"/>
            <id>https://blog.maleadt.net/2015/07/13/pi-music-server/</id>
            
            <published>2015-07-13T00:00:00+00:00</published>
            <updated>2015-07-13T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>I&rsquo;ve recently been spending some time on building an enclosure for my Raspberry
Pi-based sound system, replacing the ModMyPi case and micro-USB charger while
upgrading the audio quality by using a dedicated DAC.</p>

<p>I started from <a href="http://www.crazy-audio.com/2014/03/a-standalone-streaming-media-device-based-on-raspberry-pi-and-hifiberry-dac/">a nice-looking
example</a>
I found online, which features an inexpensive aluminum enclosure from eBay and
a compact switching power supply to get rid of the external charger.</p>

<p><img src="/img/pi-music-server/case.jpg" alt="Picture of the final unit" /></p>

<p>I used the same aluminum case and power supply as the aforementioned project,
but rather than using cables to connect the Pi&rsquo;s I/O I milled a piece of MDF<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>
to neatly expose the original connectors, together with the audio jacks and a
reset switch:</p>

<p><img src="/img/pi-music-server/backside.jpg" alt="Detail of the backside I/O shield" /></p>

<p>The reset switch and power rocker are wired to a <a href="https://mausberry-circuits.myshopify.com/">Mausberry shutdown
circuit</a>. This nifty small device
allows for a clean shut-down, by sending a shutdown signal (over GPIO) to the Pi
when the power button is flipped. A <a href="https://github.com/t-richards/mausberry-switch">user-space
daemon</a> monitors the GPIO pin,
and issues a <code>halt</code> command when requested. Finally, when the Pi has shut down
the Mausberry circuit cuts the power, indicated by a LED connected to the Pi&rsquo;s
<code>VCC</code>.</p>

<p><img src="/img/pi-music-server/inside.jpg" alt="A look into the unit" /></p>

<p>Because the case is fully closed (ie. no ventilation holes) I added a DS1820
temperature sensor, wired to one of the remaining GPIO ports. Under normal load
the temperature remains at a comfortable 30°C, and even when stressing the
system it stays below 35°C.</p>

<p>As a final tweak, I added a 1mF capacitor to the output of the power supply.
This turned out to be necessary because of some
<a href="/img/pi-music-server/mains_bounce.png">bouncy</a>
<a href="/img/pi-music-server/mains_bounce_zoomed.png">switches</a> in my house
making the power supply
<a href="/img/pi-music-server/psu_bounce.png">fluctuate by almost 2V</a>,
which in turn caused the Pi to reboot. A higher-quality PSU would probably not
have had this issue&hellip;</p>

<h2 id="bill-of-materials">Bill of Materials</h2>

<table>
  <thead>
    <tr>
      <th>Item</th>
      <th>Price</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <td><b>Total</b></td>
      <td><b>~€110</b></td>
    </tr>
  </tfoot>
  <tbody>
    <tr>
      <td>Raspberry Pi 2</td>
      <td>€39.95</td>
    </tr>
    <tr>
      <td><a href="http://www.ebay.com/itm/-/121213593037">ZJ-B-0905 aluminum enclosure</a></td>
      <td>€8.99</td>
    </tr>
    <tr>
      <td><a href="http://www.ebay.com/itm/-/231044263519">Switching PSU (5V 2A 10W)</a></td>
      <td>$5.88</td>
    </tr>
    <tr>
      <td>Mausberry shutdown circuit</td>
      <td>$12.99</td>
    </tr>
    <tr>
      <td>HiFiBerry DAC+</td>
      <td>€29.90</td>
    </tr>
    <tr>
      <td><a href="http://www.ebay.com/itm/-/321205992371">RCA audio jacks</a></td>
      <td>£3.45</td>
    </tr>
    <tr>
      <td><a href="http://www.ebay.com/itm/-/351136555494">Strain relief bushing</a></td>
      <td>~€1</td>
    </tr>
    <tr>
      <td><a href="http://www.ebay.com/itm/-/390995556763">Reset button</a></td>
      <td>~€1</td>
    </tr>
    <tr>
      <td>microSDHC card (8GB, class 10)</td>
      <td>€6.99</td>
    </tr>
  </tbody>
</table>

<h2 id="software">Software</h2>

<p>I initially looked at ready-to-use distributions such as
<a href="https://volumio.org/">Volumio</a> (or the related
<a href="http://www.runeaudio.com/">RuneAudio</a>), but both are just too damn messy behind
the scenes and did not turn out to be reliable enough for general use. Instead,
I decided to configure a generic Raspbian installation. Having wasted enough
time in the past on getting rid of the useless packages provided by the official
Raspbian, I bootstrapped a minimal version using the <a href="https://github.com/debian-pi/raspbian-ua-netinst">unattended
netinstaller</a>. The end result
is a minimal Raspbian-based <code>jessie</code> which boots in 5 seconds (2s kernel + 3s
userspace).</p>

<p>The audio-part is taken care of by <a href="https://www.mopidy.com/">Mopidy</a>, a
heavyweight but flexible Python-based mpd-like audio server<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. To make it all
user-friendly, I&rsquo;m currently using the
<a href="https://github.com/dirkgroenen/mopidy-mopify">Mopify</a> web client linked to a
premium Spotify account.</p>

<p>Some random notes to close with:</p>

<ul>
<li>The HifiBerry DAC+ isn&rsquo;t detected on the current 3.18.0 kernel in Raspbian
(the HifiBerry test images use 3.18.7), so for the time being you&rsquo;ll need to
run the horror that is <code>rpi-update</code>.</li>
<li>There seems to be <a href="https://github.com/mopidy/mopidy-alsamixer/issues/3">a
mismatch</a> in volume scale
handling between some components used by Mopidy&rsquo;s alsamixer, so you&rsquo;ll need to
use a software mixer to get useful volume control.</li>
<li>The <code>rpi-update</code>d kernel seems to boot significantly faster than its Raspbian
counterpart (presumably because it doesn&rsquo;t use an <code>initrd</code>).</li>
</ul>
<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>I mean to redo this in aluminum, but didn&rsquo;t feel like figuring out the
milling parameters. That said, it looks reasonably pretty in MDF as well!</p>
 <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>

<li id="fn:2"><p>Mopidy runs acceptably smooth on a Pi 2, but on the previous generation
you&rsquo;ll experience a sluggish UI and choppy playback of some file formats.</p>
 <a class="footnote-return" href="#fnref:2"><sup>[return]</sup></a></li>
</ol>
</div>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[sudo — local privilege escalation]]></title>
            <link href="https://blog.maleadt.net/2015/02/25/sudo-escalation/"/>
            <id>https://blog.maleadt.net/2015/02/25/sudo-escalation/</id>
            
            <published>2015-02-25T00:00:00+00:00</published>
            <updated>2015-02-25T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><code>sudo</code> is a popular program for executing commands as a substitute user, most of
the times <code>root</code>. For the purpose of user-friendliness, <code>sudo</code> caches the right
to elevate for several minutes. By hooking user-level library calls using
<code>LD_PRELOAD</code> and waiting until the user unlocks <code>sudo</code>, we can abuse this
caching mechanism and gain elevated access.</p>

<p>For this exploit, I am assuming local user access where you can drop a file and
change environment flags. This is a hefty requirement; many people would argue
local user access means game over already.</p>

<p>That said, the procedure described below is an interesting way of getting to
<code>root</code>, and is undocumented as far as I could find. It also works on all recent
distributions I&rsquo;ve tested, regardless of security features such as SELinux.</p>

<p>But first, some context. <a href="#abusing-the-cache">Skip this</a> if you already know
about <code>LD_PRELOAD</code> and how it can&rsquo;t be used for <code>setuid</code> binaries like <code>sudo</code>.</p>

<h2 id="context">Context</h2>

<p>The famous <code>LD_PRELOAD</code> variable is a powerful yet dangerous way of influencing
how dynamic libraries are loaded on most Linux systems. It instructs the dynamic
linker to load certain libraries before all others, which makes it possible to
override or hook functions. Although many benign use cases exist, the feature
can also be misused: imagine some library hooking the C runtime&rsquo;s <code>read</code>
function and spying on everything you type.</p>

<p>To prevent such shenanigans affecting your entire system, the <code>LD_PRELOAD</code>
environment flag is mostly ignored when executing binaries with the <code>setuid</code> or
<code>setgid</code> bits set. These bits allow an application to change its user identity
to whoever owns the binary being executed. For example:</p>
<div class="highlight"><pre><code class="language-c" data-lang="c"><span></span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">setuid</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;setuid failed&quot;</span><span class="p">);</span>
  <span class="k">else</span>
    <span class="n">system</span><span class="p">(</span><span class="s">&quot;/usr/bin/whoami&quot;</span><span class="p">);</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>

<p>If we compile and run this, the <code>setuid</code> call to switch our user identity to
user 0 (<code>root</code>) is obviously blocked off. However, if we make <code>root</code> own this
binary and toggle the <code>setuid</code> bit, all is allowed:</p>
<div class="highlight"><pre><code class="language-text" data-lang="text"><span></span># chown root test
# chmod 4755 test
$ ./test
root
</code></pre></div>

<p>This mechanism is what powers applications such as <code>sudo</code>. Needless to say, it
would be bad if an attacker could influence the behaviour of said applications
through means of <code>LD_PRELOAD</code>, which is why these and other environment
variables are ignored in such circumstances.</p>

<h2 id="abusing-the-cache">Abusing the cache</h2>

<p>Not to have you enter your password over and over again, <code>sudo</code> comes with a
credential cache which remembers that you&rsquo;ve entered your credentials already.
Quoting the manual:</p>

<blockquote>
<p>Once a user has been authenticated, a record is written containing the uid
that was used to authenticate, the terminal session ID, and a time stamp. The
user may then use sudo without a password for a short period of time.</p>
</blockquote>

<p>By saving the terminal session ID, an attacker cannot hijack your authenticated
<code>sudo</code> session from another terminal. That means if we want to abuse an unlocked
cache, we&rsquo;d need to do it from the very same terminal where <code>sudo</code> is being
used.</p>

<h2 id="waiting-for-a-signal">Waiting for a signal</h2>

<p>Although we cannot use <code>LD_PRELOAD</code> for hijacking library calls within <code>sudo</code>
(as it is a <code>setuid</code> binary), we can hook onto a user-level call and check
whether the cache is unlocked. When the user calls an application in which we&rsquo;ve
hooked a certain library call, and the user has recently used (and unlocked)
<code>sudo</code> within the same terminal session, we can assume control:</p>

<pre><code>$ application
  ├ preload hooked.so
  └ call foobar()
    └ hooked::foobar()
      ├ is sudo unlocked? nope...
      └ call real::foobar()

$ sudo application
  ├ unlocks the credential cache
  ├ call setuid
  └ exec application

$ application
  ├ preload hooked.so
  └ call foobar()
    └ hooked::foobar()
      ├ is sudo unlocked? yes!
      └ game over
</code></pre>

<p>This completely circumvents the existing <code>LD_PRELOAD</code> protections, because it
never attempts to preload when executing a <code>setuid</code> binary, but only targets
regular applications executed afterwards.</p>

<h2 id="implementation">Implementation</h2>

<p>Ideally, checking the credential cache would happen quickly after spawning a new
application. For the demonstration below, I&rsquo;ve picked the <code>open</code> call in <code>libc</code>.
Using <code>dlsym</code> we look up the address of the original function, and wrap the call
before returning:</p>
<div class="highlight"><pre><code class="language-c" data-lang="c"><span></span><span class="k">static</span> <span class="nf">int</span> <span class="p">(</span><span class="o">*</span><span class="n">open_real</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="p">...)</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">open</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="p">...)</span> <span class="p">{</span>
  <span class="c1">// Load the real &#39;open&#39; function</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">open_real</span><span class="p">)</span>
    <span class="n">open_real</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="p">...))</span>
                <span class="n">dlsym</span><span class="p">(</span><span class="n">RTLD_NEXT</span><span class="p">,</span> <span class="s">&quot;open&quot;</span><span class="p">);</span>

  <span class="c1">// TODO: check if sudo is unlocked</span>

  <span class="c1">// Wrap call</span>
  <span class="kt">va_list</span> <span class="n">ap</span><span class="p">;</span>
  <span class="kt">mode_t</span> <span class="n">mode</span><span class="p">;</span>
  <span class="n">va_start</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
  <span class="n">mode</span> <span class="o">=</span> <span class="n">va_arg</span><span class="p">(</span><span class="n">ap</span><span class="p">,</span> <span class="kt">mode_t</span><span class="p">);</span>
  <span class="n">va_end</span><span class="p">(</span><span class="n">ap</span><span class="p">);</span>
  <span class="k">return</span> <span class="n">open_real</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">flags</span><span class="p">,</span> <span class="n">mode</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>

<p>Now for the crucial part: check whether <code>sudo</code> is unlocked. This can be
accomplished by running <code>sudo -n true</code>, which indicates failure when a password
is required. I&rsquo;ve chosen to implement this using a quick <code>fork</code> and <code>exec</code>,
while the main thread waits for its child to finish:</p>
<div class="highlight"><pre><code class="language-c" data-lang="c"><span></span><span class="kt">pid_t</span> <span class="n">child</span> <span class="o">=</span> <span class="n">fork</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">child</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">null</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">&quot;/dev/null&quot;</span><span class="p">,</span> <span class="n">O_WRONLY</span><span class="p">);</span>
  <span class="n">dup2</span><span class="p">(</span><span class="n">null</span><span class="p">,</span> <span class="n">STDERR_FILENO</span><span class="p">);</span>

  <span class="n">execlp</span><span class="p">(</span><span class="s">&quot;sudo&quot;</span><span class="p">,</span> <span class="s">&quot;sudo&quot;</span><span class="p">,</span> <span class="s">&quot;-n&quot;</span><span class="p">,</span> <span class="s">&quot;true&quot;</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>

  <span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">exit_code</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">wait_for</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="mi">10</span> <span class="cm">/*ms*/</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">exit_code</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">exit_code</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">(</span><span class="s">&quot;I am &quot;</span><span class="p">);</span>
      <span class="n">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">);</span>
      <span class="n">execlp</span><span class="p">(</span><span class="s">&quot;sudo&quot;</span><span class="p">,</span> <span class="s">&quot;sudo&quot;</span><span class="p">,</span> <span class="s">&quot;whoami&quot;</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div>

<p>Note that these code fragments are for demonstrative purposes only, and lack
crucial bits of functionality in order to work.</p>

<h2 id="what-this-means">What this means</h2>

<p>As said before, this exploits requires local user access, at which point many
other options exist<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. Still, I think this post describes an interesting path
to <code>root</code>, in particular because it targets a design &lsquo;decision&rsquo; rather than an
ordinary vulnerability.</p>

<p>Because of this, and the fact that <code>LD_PRELOAD</code> is particularly hard to detect
(just have a look <a href="http://haxelion.eu/article/LD_NOT_PRELOADED_FOR_REAL/">@haxelion&rsquo;s recent
blogpost</a>), this
privilege escalation seems hard to mitigate. The safest path forward would be to
either disable <code>LD_PRELOAD</code> or the caching mechanism in <code>sudo</code>, but that might
break certain use-cases.</p>

<p>In the end, it all is a matter of securing your local accounts, because if they
get breached by a determined hacker it is just a matter of time before your
entire system is compromised. This vulnerability might just give him an extra
weapon of choice.</p>
<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>Staying close to this exploit, one could for example hook calls to
  <code>exec*(sudo)</code> and replace them with a familiar looking prompt, getting a
  hold of your password.</p>
 <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>
</ol>
</div>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Bypassing connection tracking for BitTorrent traffic]]></title>
            <link href="https://blog.maleadt.net/2015/02/09/conntrack-torrents/"/>
            <id>https://blog.maleadt.net/2015/02/09/conntrack-torrents/</id>
            
            <published>2015-02-09T00:00:00+00:00</published>
            <updated>2015-02-09T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p><code>iptables</code> doesn&rsquo;t like torrent traffic. More specifically, its connection
tracker (dubbed <code>conntrack</code>) easily gets confused by connections to and from the
swarm. In order to get all traffic through, I decided to bypass connection
tracking for BitTorrent traffic, which has significantly improved my up- and
downloading speeds!</p>

<p>The most common problem with tracking BitTorrent connections is the high volume
of them, causing <a href="http://wl500g.info/archive/index.php/t-10618.html">internal state tables to
overflow</a>. I bumped into
another issue, where certain incoming <code>RST</code>-flagged packets got blocked, much
like how
<a href="http://www.linuxquestions.org/questions/linux-networking-3/why-is-ufw-iptables-blocking-packets-it-shouldn%27t-be-4175500239/">this forum post</a>
details. This thoroughly messed with my torrent client, which got stuck with
many closed connections thinking they were still valid.</p>

<p>I ultimately decided to get rid of connection tracking for BitTorrent traffic
altogether. By marking packages <code>NOTRACK</code> in the respective <code>raw</code> tables, we
instruct <code>iptables</code> not to track these packages. However, this also means losing
some helpful functionality. <code>conntrack</code> and NAT helper will simply not work, and
we&rsquo;ll need to handle ICMP errors ourselves. Luckily, BitTorrent traffic is not
state-full (as opposed to, for example, FTP), so we don&rsquo;t need any helpers.</p>

<p>The following snippet lists the required <code>iptables</code> commands (usable with
<code>ip6tables</code> too):</p>
<div class="highlight"><pre><code class="language-sh" data-lang="sh"><span></span><span class="c1"># BitTorrent &quot;server&quot;</span>
<span class="nv">SERVER</span><span class="o">=</span><span class="s2">&quot;40000&quot;</span>
<span class="k">for</span> PROTO in tcp udp<span class="p">;</span> <span class="k">do</span>
  <span class="c1"># incoming traffic</span>
  iptables -t raw -I PREROUTING -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --dport <span class="si">${</span><span class="nv">SERVER</span><span class="si">}</span> -j NOTRACK
  iptables -I INPUT -i eth0 -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --dport <span class="si">${</span><span class="nv">SERVER</span><span class="si">}</span> -j ACCEPT

  <span class="c1"># outgoing traffic (replies)</span>
  iptables -t raw -I OUTPUT -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --sport <span class="si">${</span><span class="nv">SERVER</span><span class="si">}</span> -j NOTRACK
  iptables -I OUTPUT -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --sport <span class="si">${</span><span class="nv">SERVER</span><span class="si">}</span> -j ACCEPT                               
<span class="k">done</span>

<span class="c1"># BitTorrent &quot;client&quot;</span>
<span class="nv">CLIENT</span><span class="o">=</span><span class="s2">&quot;40001:40999&quot;</span>
<span class="k">for</span> PROTO in tcp udp<span class="p">;</span> <span class="k">do</span>
  <span class="c1"># outgoing traffic</span>
  iptables -t raw -I OUTPUT -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --sport <span class="si">${</span><span class="nv">CLIENT</span><span class="si">}</span> -j NOTRACK
  iptables -I OUTPUT -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --sport <span class="si">${</span><span class="nv">CLIENT</span><span class="si">}</span> -j ACCEPT                               

  <span class="c1"># incoming traffic (replies)</span>
  iptables -t raw -I PREROUTING -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --dport <span class="si">${</span><span class="nv">CLIENT</span><span class="si">}</span> -j NOTRACK
  iptables -I INPUT -i eth0 -p <span class="nv">$PROTO</span> <span class="se">\</span>
           --dport <span class="si">${</span><span class="nv">CLIENT</span><span class="si">}</span> -j ACCEPT
<span class="k">done</span>
</code></pre></div>

<p>Recall that due to marking all packages <code>NOTRACK</code>, <code>iptables</code> will not be able
to tie ICMP replies to the corresponding connection, and as a result treat those
packages as invalid. To resolve this, we should explicitly allow such control
messages:</p>
<div class="highlight"><pre><code class="language-sh" data-lang="sh"><span></span><span class="k">for</span> TYPE in destination-unreachable source-quench <span class="se">\</span>
            ttl-exceeded parameter-problem<span class="p">;</span> <span class="k">do</span>
  iptables -I INPUT -p icmp <span class="se">\</span>
           --icmp-type <span class="nv">$TYPE</span> -j ACCEPT
  iptables -I OUTPUT -p icmp <span class="se">\</span>
           --icmp-type <span class="nv">$TYPE</span> -j ACCEPT
<span class="k">done</span>
<span class="k">for</span> TYPE in destination-unreachable packet-too-big <span class="se">\</span>
            ttl-exceeded parameter-problem<span class="p">;</span> <span class="k">do</span>
  ip6tables -I INPUT -p icmpv6 <span class="se">\</span>
            --icmpv6-type <span class="nv">$TYPE</span> -j ACCEPT
  ip6tables -I OUTPUT -p icmpv6 <span class="se">\</span>
            --icmpv6-type <span class="nv">$TYPE</span> -j ACCEPT
<span class="k">done</span>
</code></pre></div>

<p>If required, you could still tighten these rules up a bit. Some ideas:</p>

<ul>
<li>restrict outgoing traffic with <code>--uid-owner</code></li>
<li>limit the allowed ICMP datagrams based on the original IP payload (for
instance, using the <code>u32</code> extension)</li>
</ul>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Reversing the RCRF-03 clicker]]></title>
            <link href="https://blog.maleadt.net/2015/01/25/clicker/"/>
            <id>https://blog.maleadt.net/2015/01/25/clicker/</id>
            
            <published>2015-01-25T00:00:00+00:00</published>
            <updated>2015-01-25T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Nowadays, classroom performance systems seem to be all the rage. Likewise at my
uni, where I came across the Turning Technologies RCRF-03 clicker. Having read
Travis Goodspeed&rsquo;s <a href="http://travisgoodspeed.blogspot.be/2010/07/reversing-rf-clicker.html">hack of the
RCRF-01</a>,
I decided to have a go at the newer model. The goal of this hack is to extract
and reverse-engineer the executed code, and subsequently sniff or forge votes
(<strong>spoiler</strong>: I failed).</p>

<h2 id="hardware">Hardware</h2>

<p><img src="/img/clicker/pcb-back.jpg" alt="Back-side of the PCB" /></p>

<p>Opening up the clicker, the main chip appears to be a Nordic Semiconductor <code>NRF
24LE1E</code>. Some details about that chip:</p>

<ul>
<li>nRF24LE1 SoC</li>
<li>32-pin 5x5 QFN package</li>
<li>Single package MCU, RF unit &amp; flash memory</li>
</ul>

<p>That last characteristic is already a big difference with the RCRF-01 model,
where the flash memory was stored off-package on an SPI-addressable EEPROM.</p>

<h2 id="wiring">Wiring</h2>

<p>The datasheet<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> of our SoC reveals an SPI programming interface. If we pull
the <code>PROG</code> pin high and pulse <code>RESET</code>, certain pins get reconfigured as an SPI
slave<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.</p>

<p>Conveniently, most of these pins are exposed through large contacts accessible
via the battery compartment. Mapping them using a continuity tester, we can find
out how they are connected, and connect it to some SPI-compatible tool such as
the <a href="http://dangerousprototypes.com/docs/Bus_Pirate">Bus Pirate</a>:</p>

<table>
<thead>
<tr>
<th><strong>Functionality</strong></th>
<th><strong>MCU pin</strong></th>
<th><strong>Test point</strong></th>
<th><strong>Bus Pirate lead</strong></th>
</tr>
</thead>

<tbody>
<tr>
<td>FCSN</td>
<td>P1.1</td>
<td>T7</td>
<td>CS (white)</td>
</tr>

<tr>
<td>FMISO</td>
<td>P1.0</td>
<td>T4</td>
<td>MISO (black)</td>
</tr>

<tr>
<td>FMOSI</td>
<td>P0.7</td>
<td>T6</td>
<td>MOSI (grey)</td>
</tr>

<tr>
<td>FSCK</td>
<td>P0.5</td>
<td>T5</td>
<td>CLK (purple)</td>
</tr>

<tr>
<td>VCC</td>
<td></td>
<td>T1</td>
<td>3.3V (red)</td>
</tr>

<tr>
<td>GND</td>
<td></td>
<td>T2</td>
<td>GND (brown)</td>
</tr>

<tr>
<td></td>
<td>PROG</td>
<td>T3</td>
<td>3.3V (red)</td>
</tr>

<tr>
<td></td>
<td>RESET</td>
<td></td>
<td>AUX (blue)</td>
</tr>
</tbody>
</table>

<p>Only the <code>RESET</code> pin is not exposed (it is hard-wired to <code>VCC</code> using a 4.7kΩ
resistor), but as it turned out you don&rsquo;t really have to pulse this pin as
detailed in the datasheet; rebooting the device while <code>PROG</code> is active suffices.</p>

<p>Connecting the <code>PROG</code> pin directly to the power supply permanently pulls it
high; this is fine for programming purposes.</p>

<p>As the SoC works between 1.9V and 3.6V (by default the clicker is equipped with
3V CR2032 batteries), and has a low power consumption, I wired it directly to
the Bus Pirate&rsquo;s integrated power supply (remember to enable that peripheral).</p>

<p>Lastly, I also connected the blue <code>AUX</code> connector to the <code>RESET</code> pin of the MCU
so I could accurately pulse it, but as explained before that wasn&rsquo;t really
necessary.</p>

<!-- after some careful soldering... -->

<p><img src="/img/clicker/pcb-wires.jpg" alt="PCB with wires soldered" /></p>

<h2 id="software">Software</h2>

<p>SPI is a simple interface, but allows for different modes selecting clock
polarity and phase. By default, the nRF24LE1&rsquo;s SPI slave starts in mode 0<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>. I
used the following settings for the Bus Pirate:</p>

<ul>
<li>speed: 125 KHz</li>
<li>clock polarity: idle low</li>
<li>output clock edge: active to idle</li>
<li>input sample phase: middle</li>
<li>chip select: active low</li>
<li>output type: normal (high bit = 3.3V)</li>
</ul>

<p>As an exercise to get to know the Bus Pirate better, I decided to use the
<a href="http://dangerousprototypes.com/docs/Bitbang">binary interface</a> and script
everything up. However, as soon as I got some code running, I discovered that
the <code>RDISMB</code> (Read DISable Main Block) bit in the Flash Status Register is set.
As the name suggests, this prevents reading from main memory through an external
interface such as SPI:</p>

<blockquote>
<p>Disable flash main block access from external interfaces:</p>

<ul>
<li><p>0xFF: Flash main block accessible from external interfaces</p></li>

<li><p>Other value: No read/erase/write of flash main block from external
interfaces. Only read of info page</p></li>
</ul>

<p>Can only be changed once by SPI command <code>RDISMB</code>. Can only be reset by SPI
command <code>ERASE ALL</code></p>
</blockquote>

<p>And the relevant entry at address 0x23 in the Info Page:</p>

<pre>
0x00000000 (00000)   005a4330 54383231 02173e4f 775f6092
0x00000010 (00016)   26b14f0d 0affffff ff82ffff ffff0000
0x00000020 (00032)   ffffff<b><font color="red">00</font></b> ffffffff ffffffff ffffffff
</pre>

<p>I haven&rsquo;t found a way around this protective bit. It is obviously impossible to
change its setting in the FSR, just as writing the underlying Info Page entry
doesn&rsquo;t do anything. The only apparent way to clear this bit is to issue the
<code>ERASE ALL</code> command, but that kinda defeats the purpose&hellip;</p>

<p>As a last resort, I tried passively sniffing the SPI bus when executing the
code, but the internal SPI bus doesn&rsquo;t seem to be exposed when operating
normally.</p>

<h2 id="wrapping-up">Wrapping up</h2>

<p>In conclusion, it seems like Nordic has upped their game and protected their
code better. Circumventing the <code>RDISMB</code> restriction doesn&rsquo;t seem very easy. For
example, <a href="http://www.bunniestudios.com/blog/?page_id=40">Bunnie&rsquo;s UV hack</a>
wouldn&rsquo;t apply because the info page is stored in the main flash. Racing to
access memory before the FSR is initialized can&rsquo;t work because <code>RDISMB</code> is
enabled by default.</p>

<p>A possible path forward would be to gain access to the firmware upgrade code
path, if that even exists (I assume so because of the exposed SPI connectors).
Or trigger unintended behaviour by altering values in the writeable part of the
Info Page. A more far fetched alternative is to try to glitch the processor when
issuing an <code>ERASE ALL</code> command. But that&rsquo;s taking it to a whole new level&hellip;</p>

<p>I&rsquo;ve put <a href="https://gist.github.com/maleadt/ef26a7d567b8a9d27534">the code</a> I&rsquo;ve
developed on Github. It&rsquo;s a comprehensive example of how to use the Bus Pirate&rsquo;s
binary SPI mode, and how to contact the nRF24LE1. Although it&rsquo;s a non-modular
piece of code, it is pretty well documented and easy to read (even though it&rsquo;s
written in Perl &ndash; don&rsquo;t let that scare you!).</p>
<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>I consulted <a href="http://www.nordicsemi.com/eng/nordic/content_download/2443/29442/file/nRF24LE1_Product_Specification_rev1_6.pdf">version 1.6</a>
of the datasheet.</p>
 <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>
<li id="fn:2">See page 77, section 6.3.5.1.
 <a class="footnote-return" href="#fnref:2"><sup>[return]</sup></a></li>
<li id="fn:3">See page 150, section 18.3.2.
 <a class="footnote-return" href="#fnref:3"><sup>[return]</sup></a></li>
</ol>
</div>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Compiling Julia for NVIDIA GPUs]]></title>
            <link href="https://blog.maleadt.net/2015/01/15/julia-cuda/"/>
            <id>https://blog.maleadt.net/2015/01/15/julia-cuda/</id>
            
            <published>2015-01-15T00:00:00+00:00</published>
            <updated>2015-01-15T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>For the few last months, I have been working on CUDA support for the <a href="http://julialang.org/">Julia
language</a>. It is now possible to write kernels in Julia
and without much hassle execute them on a NVIDIA GPU, but there are still many
limitations.</p>

<blockquote>
<p><strong>Note from 2018</strong>: Much has happened since 2015, and as a result this
blog post has become pretty stale. Check-out
<a href="https://github.com/JuliaGPU/CUDAnative.jl">CUDAnative.jl</a> for more details
about the current state of affairs.</p>
</blockquote>

<p>My work allows for code such as:</p>
<div class="highlight"><pre><code class="language-julia" data-lang="julia"><span></span><span class="k">using</span> <span class="n">CUDA</span>

<span class="c"># define a kernel</span>
<span class="nd">@target</span> <span class="n">ptx</span> <span class="k">function</span> <span class="n">kernel_vadd</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
    <span class="n">i</span> <span class="o">=</span> <span class="n">blockId_x</span><span class="p">()</span> <span class="o">+</span> <span class="p">(</span><span class="n">threadId_x</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">numBlocks_x</span><span class="p">()</span>
    <span class="n">c</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">b</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>

    <span class="k">return</span> <span class="nb">nothing</span>
<span class="k">end</span>

<span class="c"># set-up</span>
<span class="n">dev</span> <span class="o">=</span> <span class="n">CuDevice</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">ctx</span> <span class="o">=</span> <span class="n">CuContext</span><span class="p">(</span><span class="n">dev</span><span class="p">)</span>
<span class="n">cgctx</span> <span class="o">=</span> <span class="n">CuCodegenContext</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">dev</span><span class="p">)</span>

<span class="c"># create some data</span>
<span class="n">dims</span> <span class="o">=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">round</span><span class="p">(</span><span class="n">rand</span><span class="p">(</span><span class="kt">Float32</span><span class="p">,</span> <span class="n">dims</span><span class="p">)</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">round</span><span class="p">(</span><span class="n">rand</span><span class="p">(</span><span class="kt">Float32</span><span class="p">,</span> <span class="n">dims</span><span class="p">)</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="kt">Array</span><span class="p">(</span><span class="kt">Float32</span><span class="p">,</span> <span class="n">dims</span><span class="p">)</span>

<span class="c"># execute!</span>
<span class="n">len</span> <span class="o">=</span> <span class="n">prod</span><span class="p">(</span><span class="n">dims</span><span class="p">)</span>
<span class="nd">@cuda</span> <span class="p">(</span><span class="n">len</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="n">kernel_vadd</span><span class="p">(</span><span class="n">CuIn</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="n">CuIn</span><span class="p">(</span><span class="n">b</span><span class="p">),</span> <span class="n">CuOut</span><span class="p">(</span><span class="n">c</span><span class="p">))</span>

<span class="c"># verify</span>
<span class="nd">@show</span> <span class="n">a</span><span class="o">+</span><span class="n">b</span> <span class="o">==</span> <span class="n">c</span>

<span class="c"># tear-down</span>
<span class="n">destroy</span><span class="p">(</span><span class="n">cgctx</span><span class="p">)</span>
<span class="n">destroy</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
</code></pre></div>

<p>which is pretty neat I think :-)</p>

<p>I&rsquo;ll start by giving a quick description of the modifications. Jump to the
<a href="#usage">bottom of this post</a> for usage instructions.</p>

<h2 id="overview">Overview</h2>

<p>Compiling Julia for GPUs requires support at multiple levels. I&rsquo;ve tried to
avoid touching too much of core compiler; as a consequence most functionality is
part of the CUDA.jl package. This should make it easier to maintain and
eventually merge the code.</p>

<p>All of the relevant repositories are hosted at my
<a href="https://github.com/maleadt">Github</a> page, and contain <code>README</code> and <code>TODO</code>
files. If you have any questions though, feel free to contact me.</p>

<h3 id="julia-compiler">Julia compiler</h3>

<p>Using the NVPTX back-end of LLVM, I have
<a href="https://github.com/maleadt/julia">modified</a> the Julia compiler so that it can
generate PTX assembly. A non-exhaustive list of modifications:</p>

<ul>
<li><code>@target</code> macro for annotating functions with target information</li>
<li>per-target compiler state (module, pass manager, etc)</li>
<li>diverse small changes to generate suitable IR</li>
<li>exported functions for accessing the PTX code</li>
</ul>

<p>Most of the code churn comes from using an address-preserving bitcast, which is
<a href="https://github.com/JuliaLang/julia/pull/9423">already being upstreamed</a> thanks
to Valentin Churavy.</p>

<h3 id="cuda-jl-support-package">CUDA.jl support package</h3>

<p>Generating PTX assembly is only one part of the puzzle: hardware needs to be
configured, code needs to be uploaded, etc. This functionality is exposed
through the CUDA runtime driver, which already was conveniently wrapped in the
CUDA.jl package.</p>

<p>I have <a href="https://github.com/maleadt/CUDA.jl">extended</a> this package with
functionality required for GPU code generation, and developed user-friendly
wrappers which should make it easier to interact with PTX code:</p>

<ul>
<li><code>@cuda</code> macro for invoking GPU kernels</li>
<li>automatic argument management</li>
<li>lightweight on-device arrays</li>
<li>improved API consistency</li>
<li>many new features</li>
</ul>

<p>The significant part is obviously the <code>@cuda</code> macro, allowing for seamless
execution of kernel functions on your GPU. The macro compiles the kernel you&rsquo;re
calling to PTX assembly, and generates code for interacting with the driver
(creating a module, uploading code, managing arguments, etc).</p>

<p>The argument management is also pretty interesting. In function of the argument
type, it generates type conversions and/or memory operations in order to
mimic Julia&rsquo;s pass-by-sharing convention. For example, if you pass an array to a
kernel, <code>@cuda</code> will automatically up- and download it when required<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>.</p>

<p>Most functionality of <code>@cuda</code> is built using staged functions, and thus only
executes once without a recurring runtime cost. This means that it should be
possible to reach the same average performance of a traditional, precompiled
CUDA application
:-)</p>

<h3 id="gpu-ocelot-emulator">GPU Ocelot emulator</h3>

<p>I have also <a href="https://github.com/maleadt/gpuocelot">forked</a> the GPU Ocelot
project, which is a research project providing a dynamic compilation framework
(read: emulator) for CUDA hardware. By extending API support calls and fixing
certain bugs, you can use this as a drop-in replacement for <code>libcuda.so</code>, fully
compatible with CUDA.jl.</p>

<p>In practice, I used this emulator for everyday development on a system without
an NVIDIA GPU, while testing happened on real hardware.</p>

<h2 id="limitations">Limitations</h2>

<p>The code is far from production ready: it is not cross-platform (Linux only),
several changes should be discussed with upstream, and only a restricted subset
of the language is supported. Most notable shortcomings:</p>

<ul>
<li>cannot <code>alloc</code> in PTX mode (which breaks most of the language)</li>
<li>can only pass <code>bitstypes</code>, arrays or pointers</li>
<li>standard library functionality is unavailable, because it lives in another
LLVM module</li>
</ul>

<p><strong>In short</strong>: unless you&rsquo;re only using relatively simple kernels with
non-complex data interactions, this code is not yet usable for you.</p>

<h2 id="usage">Usage</h2>

<p>Even though all code is pretty functional and well-maintained, you need some
basic development skills to put the pieces together. Don&rsquo;t expect a polished
product!</p>

<h3 id="julia-compiler-1">Julia compiler</h3>

<p>Compile the modified compiler from source, using LLVM 3.5:</p>

<pre><code>$ git clone https://github.com/maleadt/julia.git
$ cd julia
$ make LLVM_VER=3.5.0
</code></pre>

<p>Optionally, make sure Julia is not broken (this does not include GPU tests):</p>

<pre><code>$ make LLVM_VER=3.5.0 testall
</code></pre>

<p><strong>Note</strong>: the compiler will require <code>libdevice</code> to link kernel binaries. This
library is only part of recent CUDA toolkits (version 5.5 or greater). If you
use an older CUDA release, you <em>will</em> need to get a hold of <a href="https://packages.debian.org/search?mode=filename&amp;suite=jessie&amp;searchon=contents&amp;keywords=libdevice.compute">these
files</a>.
Afterwards, you can point Julia to them using the <code>NVVMIR_LIBRARY_DIR</code>
environment variable.</p>

<h3 id="gpu-ocelot-emulator-1">GPU Ocelot emulator</h3>

<p>If you don&rsquo;t have any suitable CUDA hardware, you can use GPU Ocelot:</p>

<pre><code>$ git clone --recursive https://github.com/maleadt/gpuocelot.git
$ cd gpuocelot
$ $PAGER README.md
$ CUDA_BIN_PATH=/opt/cuda-5.0/bin \
  CUDA_LIB_PATH=/opt/cuda-5.0/lib \
  CUDA_INC_PATH=/opt/cuda-5.0/include \
  python2 build.py --install -p $(realpath ../julia/usr)
</code></pre>

<p><strong>Note</strong>: this probably will not build flawlessly. You&rsquo;ll need at least the CUDA
toolkit<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> (headers and tools, not the driver), gcc 4.6, scons, LLVM 3.5 and
Boost. Check the <code>README</code>!</p>

<p>Now if you load CUDA.jl and it doesn&rsquo;t find <code>libcuda.so</code>, it will look for
<code>libocelot.so</code> instead:</p>

<pre><code>$ ./julia
  &gt; using CUDA
  &gt; CUDA_VENDOR
    &quot;Ocelot&quot;
</code></pre>

<h3 id="cuda-jl-support-package-1">CUDA.jl support package</h3>

<p>Installing packages is easy<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup> (just make sure you use the correct <code>julia</code>
binary):</p>

<pre><code>$ ./julia
  &gt; Pkg.clone(&quot;https://github.com/maleadt/CUDA.jl.git&quot;)
</code></pre>

<p>Optionally, but recommended, test GPU support:</p>

<pre><code>$ ./julia
  &gt; Pkg.test(&quot;CUDA&quot;)
</code></pre>

<h2 id="what-now">What now?</h2>

<p>You tell me! I think this work can be a good start for future GPU endeavours in
Julia land, even without most code being directly re-usable. For me at least it
has been a very interesting project, but it&rsquo;s in the hands of the community now.</p>
<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>You can influence this behaviour using the <code>CuIn</code>, <code>CuOut</code>, and <code>CuInOut</code>
wrapper types.</p>
 <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>

<li id="fn:2"><p>GPU Ocelot is only compatible with CUDA 5.0 or older.
This means you&rsquo;ll need to get <code>libdevice</code> separately.</p>
 <a class="footnote-return" href="#fnref:2"><sup>[return]</sup></a></li>

<li id="fn:3"><p>If you don&rsquo;t want to pollute your main package directory with this
experimental stuff, redefine the <code>JULIA_PKGDIR</code> environment variable.</p>
 <a class="footnote-return" href="#fnref:3"><sup>[return]</sup></a></li>
</ol>
</div>]]></content>
            
                 
                    
                         
                        
                            
                             
                                <category scheme="https://blog.maleadt.net/tags/julia" term="julia" label="julia" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Knocking ports from your browser]]></title>
            <link href="https://blog.maleadt.net/2015/01/03/php-port-knocker/"/>
            <id>https://blog.maleadt.net/2015/01/03/php-port-knocker/</id>
            
            <published>2015-01-03T00:00:00+00:00</published>
            <updated>2015-01-03T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>After switching my SSH server over from some random high port to <code>tcp/22</code>, I
have been seeing loads of brute-force activity trying to gain access. Even
though those attempts are futile, I don&rsquo;t like the attention. Besides, who knows
what vulnerabilities may crop up yet.</p>

<p>In search for a good protection measure, I decided to avoid exposure of critical
services through a layer of <a href="https://en.wikipedia.org/wiki/Port_knocking">port
knocking</a>. Traditionally, one
relies on special network traffic (sequence of connection attempts, specific
packet with encrypted payload, &hellip;) to temporarily open up additional ports.
However, generating such traffic is not user friendly (ie. requires some tool or
script) and it can be hard getting it through strict firewalls.</p>

<p>I wanted to knock ports using some protocol or traffic, which is:</p>

<ul>
<li><strong>Secure</strong>: it should be hard to discover or sniff the knocking sequence;</li>
<li><strong>User-friendly</strong>: not relying on auxiliary tools;</li>
<li><strong>Firewall-friendly</strong>.</li>
</ul>

<p>My solution to this is <strong>a simple HTML/PHP form</strong>, served over <strong>password-
protected HTTPS</strong>. No firewall would block such traffic, and it is both
extremely user-friendly and very secure.</p>

<h2 id="implementation">Implementation</h2>

<p>The bottom part of the system is the firewall, allowing for certain ports to be
opened upon an external signal. I&rsquo;m using <a href="http://firehol.org/">FireHOL</a>, a
lightweight iptables-based firewall with a user-friendly syntax:</p>

<pre><code>interface eth0 internet not &quot;${UNROUTABLE_IPS}&quot;
    policy drop
    protection strong 10/sec 10

    server ssh accept with knock admin
</code></pre>

<p>The important part here is <code>with knock $NAME</code>, which will build a special chain
called <code>knock_$NAME</code>. Adding rules to this chain will allow access to the <code>ssh</code>
service, deleting them will revoke access (keeping established connections
intact).</p>

<p>Next up is some HTML form allowing the user to select a set of services to
unlock. The forms also provides an IP field, which can be useful when unlocking
from a different address (for example, your phone).</p>
<div class="highlight"><pre><code class="language-html+php" data-lang="html+php"><span></span><span class="p">&lt;</span><span class="nt">form</span> <span class="na">action</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">&lt;?</span><span class="o">=</span><span class="nb">htmlentities</span><span class="p">(</span><span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">&#39;PHP_SELF&#39;</span><span class="p">]);</span> <span class="cp">?&gt;</span><span class="s">&quot;</span>
      <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span>
  <span class="p">&lt;</span><span class="nt">table</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#39;service[]&#39;</span><span class="p">&gt;</span>Service:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">select</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;service&quot;</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">option</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;admin&quot;</span><span class="p">&gt;</span>administrative<span class="p">&lt;/</span><span class="nt">option</span><span class="p">&gt;</span>
      <span class="p">&lt;/</span><span class="nt">select</span><span class="p">&gt;&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>

    <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#39;source&#39;</span><span class="p">&gt;</span>Source IP:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;source&quot;</span>
                 <span class="na">value</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">&lt;?</span><span class="o">=</span><span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;source&#39;</span><span class="p">])</span>
                            <span class="o">?</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;source&#39;</span><span class="p">]</span>
                            <span class="o">:</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">&#39;REMOTE_ADDR&#39;</span><span class="p">])</span><span class="cp">?&gt;</span><span class="s">&quot;</span><span class="p">&gt;</span>
      <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>

    <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#39;duration&#39;</span><span class="p">&gt;</span>Duration:<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;duration&quot;</span>
                 <span class="na">value</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">&lt;?</span><span class="o">=</span><span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;duration&#39;</span><span class="p">])</span>
                            <span class="o">?</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;duration&#39;</span><span class="p">]</span>
                            <span class="o">:</span> <span class="mi">15</span><span class="p">)</span><span class="cp">?&gt;</span><span class="s">&quot;</span><span class="p">&gt;</span>
      <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>

    <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
      <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;knock&quot;</span>
                 <span class="na">value</span><span class="o">=</span><span class="s">&quot;Knock&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
  <span class="p">&lt;/</span><span class="nt">table</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</code></pre></div>

<p>In my browser, this form looks like this:
{% image php-port-knocker/form.png alt:&ldquo;Screenshot of form&rdquo; title:&ldquo;State-of-the-art UI design&rdquo; %}</p>

<p>Within the same PHP file, we process the data submitted by the user:</p>
<div class="highlight"><pre><code class="language-php" data-lang="php"><span></span><span class="cp">&lt;?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;knock&#39;</span><span class="p">]))</span> <span class="p">{</span>
  <span class="c1">// Build command line</span>
  <span class="nv">$error</span> <span class="o">=</span> <span class="k">NULL</span><span class="p">;</span>
  <span class="nv">$command</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;/usr/bin/sudo&quot;</span><span class="p">,</span> <span class="s2">&quot;/usr/local/sbin/knock&quot;</span><span class="p">];</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;source&#39;</span><span class="p">]))</span>
    <span class="nv">$command</span> <span class="o">=</span> 
      <span class="nb">array_merge</span><span class="p">(</span><span class="nv">$command</span><span class="p">,</span>
                  <span class="p">[</span><span class="s2">&quot;-s&quot;</span><span class="p">,</span> <span class="nb">escapeshellarg</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;source&#39;</span><span class="p">])]);</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;duration&#39;</span><span class="p">]))</span>
    <span class="nv">$command</span> <span class="o">=</span>
      <span class="nb">array_merge</span><span class="p">(</span><span class="nv">$command</span><span class="p">,</span>
                  <span class="p">[</span><span class="s2">&quot;-d&quot;</span><span class="p">,</span> <span class="nb">escapeshellarg</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;duration&#39;</span><span class="p">])]);</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;service&#39;</span><span class="p">]))</span>
    <span class="nb">array_push</span><span class="p">(</span><span class="nv">$command</span><span class="p">,</span>
               <span class="nb">escapeshellarg</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;service&#39;</span><span class="p">]));</span>
  <span class="k">else</span>
    <span class="nv">$error</span> <span class="o">=</span> <span class="s2">&quot;Missing service...&quot;</span><span class="p">;</span>

  <span class="c1">// Perform call</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$error</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$output</span> <span class="o">=</span> <span class="p">[];</span>
    <span class="nv">$rv</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="nb">exec</span><span class="p">(</span><span class="nb">join</span><span class="p">(</span><span class="s2">&quot; &quot;</span><span class="p">,</span> <span class="nv">$command</span><span class="p">),</span> <span class="nv">$output</span><span class="p">,</span> <span class="nv">$rv</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="nv">$rv</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
      <span class="nv">$error</span> <span class="o">=</span> <span class="nb">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="nv">$output</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="p">(</span><span class="nv">$error</span><span class="p">)</span>
    <span class="k">echo</span><span class="p">(</span><span class="s2">&quot;&lt;p&gt;Error: &quot;</span> <span class="o">.</span> <span class="nb">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="nv">$output</span><span class="p">)</span> <span class="o">.</span> <span class="s2">&quot;.&lt;/p&gt;&quot;</span><span class="p">);</span>
  <span class="k">else</span>
    <span class="k">echo</span><span class="p">(</span><span class="s2">&quot;&lt;p&gt;Service knock completed successfully.&lt;/p&gt;&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?&gt;</span><span class="x"></span>
</code></pre></div>

<p>Even though the form is only privately accessible, password protected and served
strictly over HTTPS, we still take some basic security precautions by checking
and escaping all user inputs.</p>

<p>As another layer of security, I do not allow the PHP script to invoke <code>iptables</code>
directly. Instead, I have written an auxiliary <code>knock</code> Perl script which takes
care of adding and removing rules to <code>iptables</code>:</p>
<div class="highlight"><pre><code class="language-perl" data-lang="perl"><span></span><span class="k">use</span> <span class="nn">strict</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">warnings</span><span class="p">;</span>

<span class="k">use</span> <span class="nn">POSIX</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">Getopt::Std</span><span class="p">;</span>

<span class="c1"># Parse user-input</span>
<span class="k">my</span> <span class="nv">$usage</span> <span class="o">=</span> <span class="s">&quot;Usage: $0 [-s SOURCE] [-d DELAY] SERVICE\n&quot;</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">%options</span><span class="p">;</span>
<span class="n">getopts</span><span class="p">(</span><span class="s">&quot;s:d:&quot;</span><span class="p">,</span><span class="o">\</span><span class="nv">%options</span><span class="p">)</span> <span class="o">||</span> <span class="nb">die</span> <span class="nv">$usage</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$service</span> <span class="o">=</span> <span class="nb">shift</span> <span class="o">||</span> <span class="nb">die</span> <span class="s">&quot;Missing service.\n$usage&quot;</span><span class="p">;</span>
<span class="nb">die</span> <span class="s">&quot;Invalid service.\n&quot;</span> <span class="k">unless</span> <span class="p">(</span><span class="nv">$service</span> <span class="o">=~</span> <span class="sr">m/^[a-zA-Z]+$/</span><span class="p">);</span>
<span class="k">my</span> <span class="nv">$delay</span> <span class="o">=</span> <span class="nv">$options</span><span class="p">{</span><span class="n">d</span><span class="p">}</span> <span class="o">||</span> <span class="mi">15</span><span class="p">;</span>
<span class="nb">die</span> <span class="s">&quot;Invalid delay.\n&quot;</span> <span class="k">unless</span> <span class="p">(</span><span class="nv">$delay</span> <span class="o">=~</span> <span class="sr">m/^[0-9]+$/</span><span class="p">);</span>

<span class="k">my</span> <span class="nv">@flags</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">defined</span> <span class="nv">$options</span><span class="p">{</span><span class="n">s</span><span class="p">})</span> <span class="p">{</span>
        <span class="nb">push</span><span class="p">(</span><span class="nv">@flags</span><span class="p">,</span> <span class="p">(</span><span class="s">&quot;-s&quot;</span><span class="p">,</span> <span class="nv">$options</span><span class="p">{</span><span class="n">s</span><span class="p">}));</span>
<span class="p">}</span>
<span class="nb">push</span><span class="p">(</span><span class="nv">@flags</span><span class="p">,</span> <span class="p">(</span><span class="s">&quot;-j&quot;</span><span class="p">,</span> <span class="s">&quot;ACCEPT&quot;</span><span class="p">));</span>

<span class="nb">defined</span> <span class="p">(</span><span class="k">my</span> <span class="nv">$kid</span> <span class="o">=</span> <span class="nb">fork</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">die</span> <span class="s">&quot;Cannot fork: $!\n&quot;</span><span class="p">;</span>
<span class="k">my</span> <span class="nv">$mode</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$kid</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$mode</span> <span class="o">=</span> <span class="s">&quot;-A&quot;</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="n">daemonize</span><span class="p">();</span>
    <span class="nb">sleep</span><span class="p">(</span><span class="nv">$delay</span><span class="p">);</span>
    <span class="nv">$mode</span> <span class="o">=</span> <span class="s">&quot;-D&quot;</span><span class="p">;</span>
<span class="p">}</span>

<span class="nb">system</span><span class="p">(</span><span class="s">&quot;/sbin/iptables&quot;</span><span class="p">,</span> <span class="nv">$mode</span><span class="p">,</span> <span class="s">&quot;knock_$service&quot;</span><span class="p">,</span> <span class="nv">@flags</span><span class="p">);</span>
<span class="nb">exit</span> <span class="mi">0</span><span class="p">;</span>

<span class="k">sub</span> <span class="nf">daemonize</span> <span class="p">{</span>
    <span class="nn">POSIX::</span><span class="n">setsid</span> <span class="ow">or</span> <span class="nb">die</span> <span class="s">&quot;setsid: $!&quot;</span><span class="p">;</span>
    <span class="nb">chdir</span> <span class="s">&quot;/&quot;</span><span class="p">;</span>
    <span class="nb">umask</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">foreach</span> <span class="p">(</span><span class="mi">0</span> <span class="o">..</span> <span class="p">(</span><span class="nn">POSIX::</span><span class="n">sysconf</span> <span class="p">(</span><span class="o">&amp;</span><span class="nn">POSIX::</span><span class="n">_SC_OPEN_MAX</span><span class="p">)</span> <span class="o">||</span> <span class="mi">1024</span><span class="p">))</span> <span class="p">{</span>
        <span class="nn">POSIX::</span><span class="nb">close</span> <span class="nv">$_</span>
    <span class="p">}</span>
    <span class="nb">open</span><span class="p">(</span><span class="bp">STDIN</span><span class="p">,</span> <span class="s">&quot;&lt;/dev/null&quot;</span><span class="p">);</span>
    <span class="nb">open</span><span class="p">(</span><span class="bp">STDOUT</span><span class="p">,</span> <span class="s">&quot;&gt;/dev/null&quot;</span><span class="p">);</span>
    <span class="nb">open</span><span class="p">(</span><span class="bp">STDERR</span><span class="p">,</span> <span class="s">&quot;&gt;&amp;STDOUT&quot;</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>

<p>By using such a script, a hypothetical malicious user can only control a limited
subset of <code>iptables</code> commands, restricted to <code>knock_*</code> chains. Note that we use
the list-form of Perl&rsquo;s <code>system()</code> to prevent command injection, and take care
of sanitizing user input yet again.</p>

<p>Lastly, the webserver needs to be able to call this script with elevated
permissions. Adding <code>www-data</code> to the <code>sudo</code> group (or equivalent) would not be
wise, as that would allow an attacker to gain root through the webserver user.
Instead, we still use <code>sudo</code>, but put a very specific rule in
<code>/etc/sudoers.d/knock</code> allowing the webserver to use <code>sudo</code> for our script but
nothing else:</p>

<pre><code>www-data    ALL=NOPASSWD: /usr/local/sbin/knock
</code></pre>

<h2 id="conclusion">Conclusion</h2>

<p>Port knocking is a powerful tool for hiding services, and combined with some
simple scripts it is easy to use from an ordinary browser. Security is tricky
though, so it is best to hide the interface from public access.</p>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[System-wide SSH login notifications with Pushbullet]]></title>
            <link href="https://blog.maleadt.net/2014/12/21/ssh-pushbullet/"/>
            <id>https://blog.maleadt.net/2014/12/21/ssh-pushbullet/</id>
            
            <published>2014-12-21T00:00:00+00:00</published>
            <updated>2014-12-21T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>I recently found about <a href="https://www.pushbullet.com/">Pushbullet</a>, a service and
set of applications which allows you to share notifications and other text
messages between your devices. They also provide a convenient API, making it
easy to send notifications from scripts or other programs.</p>

<p>In a quest to secure my personal server, I wanted to get a notification for each
SSH login. I found <a href="#references">some solutions</a> online, but they weren&rsquo;t
waterproof (relying on per-user <code>.profile</code> modifications) or were a bit too
hackish for my taste (actively <code>tail</code>ing <code>auth.log</code>).</p>

<h2 id="solution">Solution</h2>

<p>It&rsquo;s essential that any user logging in cannot externally prevent the
notification from being sent. The best solution I found is to modify the SSH
server configuration, and force execution of a wrapper script which will
generate the notification. The <strong>ForceCommand</strong> option does exactly that:</p>

<blockquote>
<p>Forces the execution of the command specified by ForceCommand, ignoring any
command supplied by the client and ~/.ssh/rc if present.</p>
</blockquote>

<p>Within the wrapper script, we can use the (relatively undocumented)
<code>SSH_CONNECTION</code> environment variable to get a hold of some details about the
current connection. We will use that to make our notification a bit more
interesting. Finally, we hand control back to the user, spawning the command
asked for (saved in <code>SSH_ORIGINAL_COMMAND</code>), or the user&rsquo;s default shell:</p>
<div class="highlight"><pre><code class="language-sh" data-lang="sh"><span></span><span class="ch">#!/bin/sh</span>

<span class="nv">SHELL</span><span class="o">=</span><span class="k">$(</span>getent passwd <span class="nv">$USER</span> <span class="p">|</span> cut -d: -f7<span class="k">)</span>
<span class="nv">IP</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span> <span class="nv">$SSH_CONNECTION</span> <span class="p">|</span> cut -d <span class="s2">&quot; &quot;</span> -f <span class="m">1</span><span class="k">)</span>
<span class="nv">HOSTNAME</span><span class="o">=</span><span class="k">$(</span>dig -x <span class="nv">$IP</span> +short<span class="k">)</span>
<span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;</span><span class="si">${</span><span class="nv">HOSTNAME</span><span class="si">}</span><span class="s2">&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
        <span class="nv">HOSTNAME</span><span class="o">=</span><span class="nv">$IP</span>
<span class="k">fi</span>
<span class="nv">LOCALHOST</span><span class="o">=</span><span class="k">$(</span>hostname<span class="k">)</span>

/usr/local/bin/pushmessage <span class="se">\</span>
        <span class="s2">&quot;SSH login on </span><span class="nv">$LOCALHOST</span><span class="s2">&quot;</span> <span class="se">\</span>
        <span class="s2">&quot;User </span><span class="si">${</span><span class="nv">USER</span><span class="si">}</span><span class="s2"> has logged in from </span><span class="si">${</span><span class="nv">HOSTNAME</span><span class="si">}</span><span class="s2">&quot;</span>

<span class="si">${</span><span class="nv">SSH_ORIGINAL_COMMAND</span><span class="p">-</span><span class="nv">$SHELL</span><span class="si">}</span>
</code></pre></div>

<p>I saved this script in <code>/usr/local/sbin/ssh-wrapper</code>, made it executable, and
activated it by adding <code>ForceCommand /usr/local/sbin/ssh-wrapper</code> to
<code>/etc/ssh/sshd_config</code>.</p>

<p>Note that my wrapper script makes use of <code>pushmessage</code>, a small script which
delivers the actual notification:</p>
<div class="highlight"><pre><code class="language-sh" data-lang="sh"><span></span><span class="ch">#!/bin/sh</span>

<span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;</span><span class="nv">$#</span><span class="s2">&quot;</span> !<span class="o">=</span> <span class="m">2</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
    <span class="nb">echo</span> <span class="s2">&quot;Usage: </span><span class="nv">$0</span><span class="s2"> TITLE MESSAGE&quot;</span> &gt;<span class="p">&amp;</span><span class="m">2</span>
    <span class="nb">exit</span> <span class="m">1</span>
<span class="k">fi</span>

<span class="nv">APIKEY</span><span class="o">=</span><span class="s2">&quot;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&quot;</span>
<span class="nv">IDEN</span><span class="o">=</span><span class="s2">&quot;XXXXXXXXXXXXXXXXXXXXXX&quot;</span>

curl https://api.pushbullet.com/api/pushes -u <span class="si">${</span><span class="nv">APIKEY</span><span class="si">}</span>: <span class="se">\</span>
    --output /dev/null --silent --max-time <span class="m">5</span> <span class="se">\</span>
    -X POST -d <span class="nv">device_iden</span><span class="o">=</span><span class="si">${</span><span class="nv">IDEN</span><span class="si">}</span> <span class="se">\</span>
    -d <span class="nv">type</span><span class="o">=</span>note -d <span class="nv">title</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span> <span class="se">\</span>
    -d <span class="nv">body</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$2</span><span class="s2">&quot;</span>
</code></pre></div>

<p>The <code>APIKEY</code> and <code>IDEN</code> variables are personalised, and contain respectively
your Pushbullet access token and the device identification. The former you can
find on your <a href="https://www.pushbullet.com/account">Pushbullet account page</a>, and
in order to get a suitable device identifier you&rsquo;ll need to inquire the API:</p>
<div class="highlight"><pre><code class="language-sh" data-lang="sh"><span></span>$ curl --silent -u <span class="si">${</span><span class="nv">APIKEY</span><span class="si">}</span>: <span class="se">\</span>
  https://api.pushbullet.com/api/devices <span class="p">|</span> python -m json.tool
<span class="o">{</span>
    <span class="s2">&quot;devices&quot;</span>: <span class="o">[</span>
        <span class="o">{</span>
            ...,
            <span class="s2">&quot;iden&quot;</span>: <span class="s2">&quot;XXXXXXXXXXXXXXXXXXXXXX&quot;</span>
        <span class="o">}</span>
    <span class="o">]</span>,
    <span class="s2">&quot;shared_devices&quot;</span>: <span class="o">[]</span>
<span class="o">}</span>
</code></pre></div>

<h2 id="limitations">Limitations</h2>

<ul>
<li>Slowdown: on a normal day, a <code>pushmessage</code> invocation takes about 500 ms. This
is a significant slowdown of the — already pretty slow — SSH login.
Backgrounding the API call solves this, but can get you spammed.</li>
<li>Too many invocations: the wrapper script is called on each login, even if the
SSH connection was already established (ie. when multiplexing connections
using <code>ControlMaster</code>). This is especially noticeable when using tab
completion for the <code>scp</code> command: every <code>&lt;TAB&gt;</code> will trigger a notification.</li>
<li>Cluttered process tree: the <code>ssh-wrapper</code> script keeps on existing in the
process hierarchy because it spawns the user shell. It should be possible to
avoid this (eg. by <code>execve</code>ing the shell instead).</li>
</ul>

<h2 id="references-a-name-references">References <a name="references" /></h2>

<ol>
<li><a href="http://www.jamesleighton.com/2014/11/ssh-login-notifications-using-pushbullet.html">SSH Login Notifications using Pushbullet</a></li>
<li><a href="http://www.forum-cubieboard.de/Thread-ssh-login-meldung-aufs-handy-per-pushbullet">SSH Login Meldung aufs Handy per Pushbullet</a></li>
<li><a href="http://jankarres.de/2014/03/raspberry-pi-push-benachrichtigung-bei-ssh-anmeldung/">Raspberry Pi: Push Benachrichtigung bei SSH Anmeldung</a></li>
<li><a href="http://blog.wenzlaff.de/?p=3032">Wie wird eine Pushover Benachrichtigung auf dem Raspberry Pi bei Zugriff per SSH versendet um Einbrüche zu erkennen?</a></li>
</ol>]]></content>
            
                 
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Static is the new dynamic]]></title>
            <link href="https://blog.maleadt.net/2014/12/15/new-blog/"/>
            <id>https://blog.maleadt.net/2014/12/15/new-blog/</id>
            
            <published>2014-12-15T00:00:00+00:00</published>
            <updated>2014-12-15T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<p>Once again, I decided to move my blog over to a new home. Making use of the
opportunity, I&rsquo;ve switched technologies to what all the cool kids seem to be
using: <a href="http://jekyllrb.com/">Jekyll</a>, a Ruby application for generating static
HTML sites.</p>

<p>By forking an existing theme, all the boilerplate was already taken care of. I
picked <a href="http://lanyon.getpoole.com/">Lanyon</a> for its looks and simplicity, and
managed to get a basic blog up and running in minutes &ndash; almost as advertised.</p>

<p>The resulting set-up is surprisingly functional! Using the built-in web server,
launched using the command <code>jekyll serve</code>, you can easily preview local changes.
If you want to launch your browser as soon as Jekyll has launched, you can use
the following GNU Make rules (or extract the blob between <code>define EXPECT_SERVE</code>
and <code>endef</code>, substituting double <code>$</code>&rsquo;s with single ones):</p>

<!-- Pygments doesn't properly handle the GNU Make `define` -->
<div class="highlight"><pre><code class="language-text" data-lang="text"><span></span>SHELL := /bin/bash

define EXPECT_SERVE
set timeout 5
spawn jekyll serve
expect {
    -re {Server address:\s+(.+)$$} {
        set address $$expect_out(1,string)
    }
}
expect &quot;Server running...&quot;
catch {
    exec xdg-open $$address
}
interact
endef
export EXPECT_SERVE

.PHONY: serve
serve:
    expect &lt;( echo &quot;$$EXPECT_SERVE&quot; )
</code></pre></div>]]></content>
            
                 
                    
                
            
        </entry>
    
</feed>
