
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Sat, 04 Apr 2026 14:09:39 GMT</lastBuildDate>
        <item>
            <title><![CDATA[How we found a bug in Go's arm64 compiler]]></title>
            <link>https://blog.cloudflare.com/how-we-found-a-bug-in-gos-arm64-compiler/</link>
            <pubDate>Wed, 08 Oct 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ 84 million requests a second means even rare bugs appear often. We'll reveal how we discovered a race condition in the Go arm64 compiler and got it fixed. ]]></description>
            <content:encoded><![CDATA[ <p>Every second, 84 million HTTP requests are hitting Cloudflare across our fleet of data centers in 330 cities. It means that even the rarest of bugs can show up frequently. In fact, it was our scale that recently led us to discover a bug in Go's arm64 compiler which causes a race condition in the generated code.</p><p>This post breaks down how we first encountered the bug, investigated it, and ultimately drove to the root cause.</p>
    <div>
      <h2>Investigating a strange panic</h2>
      <a href="#investigating-a-strange-panic">
        
      </a>
    </div>
    <p>We run a service in our network which configures the kernel to handle traffic for some products like <a href="https://www.cloudflare.com/network-services/products/magic-transit/"><u>Magic Transit</u></a> and <a href="https://www.cloudflare.com/network-services/products/magic-wan/"><u>Magic WAN</u></a>. Our monitoring watches this closely, and it started to observe very sporadic panics on arm64 machines.</p><p>We first saw one with a fatal error stating that <a href="https://github.com/golang/go/blob/c0ee2fd4e309ef0b8f4ab6f4860e2626c8e00802/src/runtime/traceback.go#L566"><u>traceback did not unwind completely</u></a>. That error suggests that invariants were violated when traversing the stack, likely because of stack corruption. After a brief investigation we decided that it was probably rare stack memory corruption. This was a largely idle control plane service where unplanned restarts have negligible impact, and so we felt that following up was not a priority unless it kept happening.</p><p>And then it kept happening. </p>
    <div>
      <h4>Coredumps per hour</h4>
      <a href="#coredumps-per-hour">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7ohMD2ph3I9l7lbZQWZ4xl/243e679d8293565fc6a55a670c9f3583/BLOG-2906_2.png" />
          </figure><p>When we first saw this bug we saw that the fatal errors correlated with recovered panics. These were caused by some old code which used panic/recover as error handling. </p><p>At this point, our theory was: </p><ol><li><p>All of the fatal panics happen within stack unwinding.</p></li><li><p>We correlated an increased volume of recovered panics with these fatal panics.</p></li><li><p>Recovering a panic unwinds goroutine stacks to call deferred functions.</p></li><li><p>A related <a href="https://github.com/golang/go/issues/73259"><u>Go issue (#73259)</u></a> reported an arm64 stack unwinding crash.</p></li><li><p>Let’s stop using panic/recover for error handling and wait out the upstream fix?</p></li></ol><p>So we did that and watched as fatal panics stopped occurring as the release rolled out. Fatal panics gone, our theoretical mitigation seemed to work, and this was no longer our problem. We subscribed to the upstream issue so we could update when it was resolved and put it out of our minds.</p><p>But, this turned out to be a much stranger bug than expected. Putting it out of our minds was premature as the same class of fatal panics came back at a much higher rate. A month later, we were seeing up to 30 daily fatal panics with no real discernible cause; while that might account for only one machine a day in less than 10% of our data centers, we found it concerning that we didn’t understand the cause. The first thing we checked was the number of recovered panics, to match our previous pattern, but there were none. More interestingly, we could not correlate this increased rate of fatal panics with anything. A release? Infrastructure changes? The position of Mars? </p><p>At this point we felt like we needed to dive deeper to better understand the root cause. Pattern matching and hoping was clearly insufficient. </p><p>We saw two classes of this bug -- a crash while accessing invalid memory and an explicitly checked fatal error. </p>
    <div>
      <h4>Fatal Error</h4>
      <a href="#fatal-error">
        
      </a>
    </div>
    
            <pre><code>goroutine 153 gp=0x4000105340 m=324 mp=0x400639ea08 [GC worker (active)]:
/usr/local/go/src/runtime/asm_arm64.s:244 +0x6c fp=0x7ff97fffe870 sp=0x7ff97fffe860 pc=0x55558d4098fc
runtime.systemstack(0x0)
       /usr/local/go/src/runtime/mgc.go:1508 +0x68 fp=0x7ff97fffe860 sp=0x7ff97fffe810 pc=0x55558d3a9408
runtime.gcBgMarkWorker.func2()
       /usr/local/go/src/runtime/mgcmark.go:1102
runtime.gcDrainMarkWorkerIdle(...)
       /usr/local/go/src/runtime/mgcmark.go:1188 +0x434 fp=0x7ff97fffe810 sp=0x7ff97fffe7a0 pc=0x55558d3ad514
runtime.gcDrain(0x400005bc50, 0x7)
       /usr/local/go/src/runtime/mgcmark.go:212 +0x1c8 fp=0x7ff97fffe7a0 sp=0x7ff97fffe6f0 pc=0x55558d3ab248
runtime.markroot(0x400005bc50, 0x17e6, 0x1)
       /usr/local/go/src/runtime/mgcmark.go:238 +0xa8 fp=0x7ff97fffe6f0 sp=0x7ff97fffe6a0 pc=0x55558d3ab578
runtime.markroot.func1()
       /usr/local/go/src/runtime/mgcmark.go:887 +0x290 fp=0x7ff97fffe6a0 sp=0x7ff97fffe560 pc=0x55558d3acaa0
runtime.scanstack(0x4014494380, 0x400005bc50)
       /usr/local/go/src/runtime/traceback.go:447 +0x2ac fp=0x7ff97fffe560 sp=0x7ff97fffe4d0 pc=0x55558d3eeb7c
runtime.(*unwinder).next(0x7ff97fffe5b0?)
       /usr/local/go/src/runtime/traceback.go:566 +0x110 fp=0x7ff97fffe4d0 sp=0x7ff97fffe490 pc=0x55558d3eed40
runtime.(*unwinder).finishInternal(0x7ff97fffe4f8?)
       /usr/local/go/src/runtime/panic.go:1073 +0x38 fp=0x7ff97fffe490 sp=0x7ff97fffe460 pc=0x55558d403388
runtime.throw({0x55558de6aa27?, 0x7ff97fffe638?})
runtime stack:
fatal error: traceback did not unwind completely
       stack=[0x4015d6a000-0x4015d8a000
runtime: g8221077: frame.sp=0x4015d784c0 top=0x4015d89fd0</code></pre>
            <p></p>
    <div>
      <h4>Segmentation fault</h4>
      <a href="#segmentation-fault">
        
      </a>
    </div>
    
            <pre><code>goroutine 187 gp=0x40003aea80 m=13 mp=0x40003ca008 [GC worker (active)]:
       /usr/local/go/src/runtime/asm_arm64.s:244 +0x6c fp=0x7fff2afde870 sp=0x7fff2afde860 pc=0x55557e2d98fc
runtime.systemstack(0x0)
       /usr/local/go/src/runtime/mgc.go:1489 +0x94 fp=0x7fff2afde860 sp=0x7fff2afde810 pc=0x55557e279434
runtime.gcBgMarkWorker.func2()
       /usr/local/go/src/runtime/mgcmark.go:1112
runtime.gcDrainMarkWorkerDedicated(...)
       /usr/local/go/src/runtime/mgcmark.go:1188 +0x434 fp=0x7fff2afde810 sp=0x7fff2afde7a0 pc=0x55557e27d514
runtime.gcDrain(0x4000059750, 0x3)
       /usr/local/go/src/runtime/mgcmark.go:212 +0x1c8 fp=0x7fff2afde7a0 sp=0x7fff2afde6f0 pc=0x55557e27b248
runtime.markroot(0x4000059750, 0xb8, 0x1)
       /usr/local/go/src/runtime/mgcmark.go:238 +0xa8 fp=0x7fff2afde6f0 sp=0x7fff2afde6a0 pc=0x55557e27b578
runtime.markroot.func1()
       /usr/local/go/src/runtime/mgcmark.go:887 +0x290 fp=0x7fff2afde6a0 sp=0x7fff2afde560 pc=0x55557e27caa0
runtime.scanstack(0x40042cc000, 0x4000059750)
       /usr/local/go/src/runtime/traceback.go:458 +0x188 fp=0x7fff2afde560 sp=0x7fff2afde4d0 pc=0x55557e2bea58
runtime.(*unwinder).next(0x7fff2afde5b0)
goroutine 0 gp=0x40003af880 m=13 mp=0x40003ca008 [idle]:
PC=0x55557e2bea58 m=13 sigcode=1 addr=0x118
SIGSEGV: segmentation violation</code></pre>
            <p></p><p></p><p>Now we could observe some clear patterns. Both errors occur when unwinding the stack in <code>(*unwinder).next</code>. In one case we saw an intentional<a href="https://github.com/golang/go/blob/b3251514531123d7fd007682389bce7428d159a0/src/runtime/traceback.go#L566"> <u>fatal error</u></a> as the runtime identified that unwinding could not complete and the stack was in a bad state. In the other case there was a direct memory access error that happened while trying to unwind the stack. The segfault was discussed in the <a href="https://github.com/golang/go/issues/73259#issuecomment-2786818812"><u>GitHub issue</u></a> and a Go engineer identified it as dereference of a go scheduler struct, <a href="https://github.com/golang/go/blob/924fe98902cdebf20825ab5d1e4edfc0fed2966f/src/runtime/runtime2.go#L536"><u>m</u></a>, when<a href="https://github.com/golang/go/blob/b3251514531123d7fd007682389bce7428d159a0/src/runtime/traceback.go#L458"> <u>unwinding</u></a>.   </p>
    <div>
      <h3>A review of Go scheduler structs</h3>
      <a href="#a-review-of-go-scheduler-structs">
        
      </a>
    </div>
    <p>Go uses a lightweight userspace scheduler to manage concurrency. Many goroutines are scheduled on a smaller number of kernel threads – this is often referred to as M:N scheduling. Any individual goroutine can be scheduled on any kernel thread. The scheduler has three core types – <a href="https://github.com/golang/go/blob/924fe98902cdebf20825ab5d1e4edfc0fed2966f/src/runtime/runtime2.go#L394"><code><u>g</u></code></a>  (the goroutine), <a href="https://github.com/golang/go/blob/924fe98902cdebf20825ab5d1e4edfc0fed2966f/src/runtime/runtime2.go#L536"><code><u>m</u></code></a> (the kernel thread, or “machine”), and <a href="https://github.com/golang/go/blob/924fe98902cdebf20825ab5d1e4edfc0fed2966f/src/runtime/runtime2.go#L644"><code><u>p</u></code></a> (the physical execution context, or  “processor”). For a goroutine to be scheduled a free <code>m</code> must acquire a free <code>p</code>, which will execute a g. Each <code>g</code> contains a field for its m if it is currently running, otherwise it will be <b>nil</b>. This is all the context needed for this post but the <a href="https://github.com/golang/go/blob/master/src/runtime/HACKING.md#gs-ms-ps"><u>go runtime docs</u></a> explore this more comprehensively. </p><p>At this point we can start to make inferences on what’s happening: the program crashes because we try to unwind a goroutine stack which is invalid. In the first backtrace, if a <a href="https://github.com/golang/go/blob/b3251514531123d7fd007682389bce7428d159a0/src/runtime/traceback.go#L446"><u>return address is null, we call </u><code><u>finishInternal</u></code><u> and abort because the stack was not fully unwound</u></a>. The segmentation fault case in the second backtrace is a bit more interesting: if instead the return address is non-zero but not a function then the unwinder code assumes that the goroutine is currently running. It'll then dereference m and fault by accessing <code>m.incgo</code> (the offset of <code>incgo</code> into <code>struct m</code> is 0x118, the faulting memory access). </p><p>What, then, is causing this corruption? The traces were difficult to get anything useful from – our service has hundreds if not thousands of active goroutines. It was fairly clear from the beginning that the panic was remote from the actual bug. The crashes were all observed while unwinding the stack and if this were an issue any time the stack was unwound on arm64 we would be seeing it in many more services. We felt pretty confident that the stack unwinding was happening correctly but on an invalid stack. </p><p>Our investigation stalled for a while at this point – making guesses, testing guesses, trying to infer if the panic rate went up or down, or if nothing changed. There was <a href="https://github.com/golang/go/issues/73259"><u>a known issue</u></a> on Go’s GitHub issue tracker which matched our symptoms almost exactly, but what they discussed was mostly what we already knew. At some point when looking through the linked stack traces we realized that their crash referenced an old version of a library that we were also using – Go Netlink.</p>
            <pre><code>goroutine 1267 gp=0x4002a8ea80 m=nil [runnable (scan)]:
runtime.asyncPreempt2()
        /usr/local/go/src/runtime/preempt.go:308 +0x3c fp=0x4004cec4c0 sp=0x4004cec4a0 pc=0x46353c
runtime.asyncPreempt()
        /usr/local/go/src/runtime/preempt_arm64.s:47 +0x9c fp=0x4004cec6b0 sp=0x4004cec4c0 pc=0x4a6a8c
github.com/vishvananda/netlink/nl.(*NetlinkSocket).Receive(0x14360300000000?)
        /go/pkg/mod/github.com/!data!dog/netlink@v1.0.1-0.20240223195320-c7a4f832a3d1/nl/nl_linux.go:803 +0x130 fp=0x4004cfc710 sp=0x4004cec6c0 pc=0xf95de0
</code></pre>
            <p></p><p>We spot-checked a few stack traces and confirmed the presence of this Netlink library. Querying our logs showed that not only did we share a library – every single segmentation fault we observed had happened while preempting<a href="https://github.com/vishvananda/netlink/blob/e1e260214862392fb28ff72c9b11adc84df73e2c/nl/nl_linux.go#L880"> <code><u>NetlinkSocket.Receive</u></code></a>.</p>
    <div>
      <h3>What’s (async) preemption?</h3>
      <a href="#whats-async-preemption">
        
      </a>
    </div>
    <p>In the prehistoric era of Go (&lt;=1.13) the runtime was cooperatively scheduled. A goroutine would run until it decided it was ready to yield to the scheduler – usually due to explicit calls to <code>runtime.Gosched()</code> or injected yield points at function calls/IO operations. Since<a href="https://go.dev/doc/go1.14#runtime"> <u>Go 1.14</u></a> the runtime instead does async preemption. The Go runtime has a thread <code>sysmon</code> which tracks the runtime of goroutines and will preempt any that run for longer than 10ms (at time of writing). It does this by sending <code>SIGURG</code> to the OS thread and in the signal handler will modify the program counter and stack to mimic a call to <code>asyncPreempt</code>.</p><p>At this point we had two broad theories:</p><ul><li><p>This is a Go Netlink bug – likely due to <code>unsafe.Pointer</code> usage which invoked undefined behavior but is only actually broken on arm64</p></li><li><p>This is a Go runtime bug and we're only triggering it in <code>NetlinkSocket.Receive</code> for some reason</p></li></ul><p>After finding the same bug publicly reported upstream, we were feeling confident this was caused by a Go runtime bug. However, upon seeing that both issues implicated the same function, we felt more skeptical – notably the Go Netlink library uses unsafe.Pointer so memory corruption was a plausible explanation even if we didn't understand why.</p><p>After an unsuccessful code audit we had hit a wall. The crashes were rare and remote from the root cause. Maybe these crashes were caused by a runtime bug, maybe they were caused by a Go Netlink bug. It seemed clear that there was something wrong with this area of the code, but code auditing wasn’t going anywhere. </p>
    <div>
      <h2>Breakthrough</h2>
      <a href="#breakthrough">
        
      </a>
    </div>
    <p>At this point we had a fairly good understanding of what was crashing but very little understanding of <b>why</b> it was happening. It was clear that the root cause of the stack unwinder crashing was remote from the actual crash, and that it had to do with <code>(*NetlinkSocket).Receive</code>, but why? We were able to capture a <b>coredump</b> of a production crash and view it in a debugger. The backtrace confirmed what we already knew – that there was a segmentation fault when unwinding a stack. The crux of the issue revealed itself when we looked at the goroutine which had been preempted while calling <code>(*NetlinkSocket).Receive</code>.     </p>
            <pre><code>(dlv) bt
0  0x0000555577579dec in runtime.asyncPreempt2
   at /usr/local/go/src/runtime/preempt.go:306
1  0x00005555775bc94c in runtime.asyncPreempt
   at /usr/local/go/src/runtime/preempt_arm64.s:47
2  0x0000555577cb2880 in github.com/vishvananda/netlink/nl.(*NetlinkSocket).Receive
   at
/vendor/github.com/vishvananda/netlink/nl/nl_linux.go:779
3  0x0000555577cb19a8 in github.com/vishvananda/netlink/nl.(*NetlinkRequest).Execute
   at 
/vendor/github.com/vishvananda/netlink/nl/nl_linux.go:532
4  0x0000555577551124 in runtime.heapSetType
   at /usr/local/go/src/runtime/mbitmap.go:714
5  0x0000555577551124 in runtime.heapSetType
   at /usr/local/go/src/runtime/mbitmap.go:714
...
(dlv) disass -a 0x555577cb2878 0x555577cb2888
TEXT github.com/vishvananda/netlink/nl.(*NetlinkSocket).Receive(SB) /vendor/github.com/vishvananda/netlink/nl/nl_linux.go
        nl_linux.go:779 0x555577cb2878  fdfb7fa9        LDP -8(RSP), (R29, R30)
        nl_linux.go:779 0x555577cb287c  ff430191        ADD $80, RSP, RSP
        nl_linux.go:779 0x555577cb2880  ff434091        ADD $(16&lt;&lt;12), RSP, RSP
        nl_linux.go:779 0x555577cb2884  c0035fd6        RET
</code></pre>
            <p></p><p>The goroutine was paused between two opcodes in the function epilogue. Since the process of unwinding a stack relies on the stack frame being in a consistent state, it felt immediately suspicious that we preempted in the middle of adjusting the stack pointer. The goroutine had been paused at 0x555577cb2880, between<code> ADD $80, RSP, RSP and ADD $(16&lt;&lt;12), RSP, RSP</code>. </p><p>We queried the service logs to confirm our theory. This wasn’t isolated – the majority of stack traces showed that this same opcode was preempted. This was no longer a weird production crash we couldn’t reproduce. A crash happened when the Go runtime preempted between these two stack pointer adjustments. We had our smoking gun. </p>
    <div>
      <h2>Building a minimal reproducer</h2>
      <a href="#building-a-minimal-reproducer">
        
      </a>
    </div>
    <p>At this point we felt pretty confident that this was actually just a runtime bug and it should be reproducible in an isolated environment without any dependencies. The theory at this point was:</p><ol><li><p>Stack unwinding is triggered by garbage collection</p></li><li><p>Async preemption between a split stack pointer adjustment causes a crash</p></li><li><p>What if we make a function which splits the adjustment and then call it in a loop?</p></li></ol>
            <pre><code>package main

import (
	"runtime"
)

//go:noinline
func big_stack(val int) int {
	var big_buffer = make([]byte, 1 &lt;&lt; 16)

	sum := 0
	// prevent the compiler from optimizing out the stack
	for i := 0; i &lt; (1&lt;&lt;16); i++ {
		big_buffer[i] = byte(val)
	}
	for i := 0; i &lt; (1&lt;&lt;16); i++ {
		sum ^= int(big_buffer[i])
	}
	return sum
}

func main() {
	go func() {
		for {
			runtime.GC()
		}
	}()
	for {
		_ = big_stack(1000)
	}
}
</code></pre>
            <p></p><p>This function ends up with a stack frame slightly larger than can be represented in 16 bits, and so on arm64 the Go compiler will split the stack pointer adjustment into two opcodes. If the runtime preempts between these opcodes then the stack unwinder will read an invalid stack pointer and crash. </p>
            <pre><code>; epilogue for main.big_stack
ADD $8, RSP, R29
ADD $(16&lt;&lt;12), R29, R29
ADD $16, RSP, RSP
; preemption is problematic between these opcodes
ADD $(16&lt;&lt;12), RSP, RSP
RET
</code></pre>
            <p></p><p>After running this for a few minutes the program panicked as expected!</p>
            <pre><code>SIGSEGV: segmentation violation
PC=0x60598 m=8 sigcode=1 addr=0x118

goroutine 0 gp=0x400019c540 m=8 mp=0x4000198708 [idle]:
runtime.(*unwinder).next(0x400030fd10)
        /home/thea/sdk/go1.23.4/src/runtime/traceback.go:458 +0x188 fp=0x400030fcc0 sp=0x400030fc30 pc=0x60598
runtime.scanstack(0x40000021c0, 0x400002f750)
        /home/thea/sdk/go1.23.4/src/runtime/mgcmark.go:887 +0x290 

[...]

goroutine 1 gp=0x40000021c0 m=nil [runnable (scan)]:
runtime.asyncPreempt2()
        /home/thea/sdk/go1.23.4/src/runtime/preempt.go:308 +0x3c fp=0x40003bfcf0 sp=0x40003bfcd0 pc=0x400cc
runtime.asyncPreempt()
        /home/thea/sdk/go1.23.4/src/runtime/preempt_arm64.s:47 +0x9c fp=0x40003bfee0 sp=0x40003bfcf0 pc=0x75aec
main.big_stack(0x40003cff38?)
        /home/thea/dev/stack_corruption_reproducer/main.go:29 +0x94 fp=0x40003cff00 sp=0x40003bfef0 pc=0x77c04
Segmentation fault (core dumped)

real    1m29.165s
user    4m4.987s
sys     0m43.212s</code></pre>
            <p></p><p>A reproducible crash with standard library only? This felt like conclusive evidence that our problem was a runtime bug.</p><p>This was an extremely particular reproducer! Even now with a good understanding of the bug and its fix, some of the behavior is still puzzling. It's a one-instruction race condition, so it’s unsurprising that small changes could have large impact. For example, this reproducer was originally written and tested on Go 1.23.4, but did not crash when compiled with 1.23.9 (the version in production), even though we could objdump the binary and see the split ADD still present! We don’t have a definite explanation for this behavior – even with the bug present there remain a few unknown variables which affect the likelihood of hitting the race condition. </p>
    <div>
      <h2>A single-instruction race condition window</h2>
      <a href="#a-single-instruction-race-condition-window">
        
      </a>
    </div>
    <p>arm64 is a fixed-length 4-byte instruction set architecture. This has a lot of implications on codegen but most relevant to this bug is the fact that immediate length is limited.<a href="https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/ADD--immediate---Add--immediate--"> <code><u>add</u></code></a> gets a 12-bit immediate,<a href="https://developer.arm.com/documentation/dui0802/a/A64-General-Instructions/MOV--wide-immediate-"> <code><u>mov</u></code></a> gets a 16-bit immediate, etc. How does the architecture handle this when the operands don't fit? It depends – <code>ADD</code> in particular reserves a bit for "shift left by 12" so any 24 bit addition can be decomposed into two opcodes. Other instructions are decomposed similarly, or just require loading an immediate into a register first. </p><p>The very last step of the Go compiler before emitting machine code involves transforming the program into <code>obj.Prog</code> structs. It's a very low level intermediate representation (IR) that mostly serves to be translated into machine code. </p>
            <pre><code>//https://github.com/golang/go/blob/fa2bb342d7b0024440d996c2d6d6778b7a5e0247/src/cmd/internal/obj/arm64/obj7.go#L856

// Pop stack frame.
// ADD $framesize, RSP, RSP
p = obj.Appendp(p, c.newprog)
p.As = AADD
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(c.autosize)
p.To.Type = obj.TYPE_REG
p.To.Reg = REGSP
p.Spadj = -c.autosize
</code></pre>
            <p></p><p>Notably, this IR is not aware of immediate length limitations. Instead, this happens in<a href="https://github.com/golang/go/blob/2f653a5a9e9112ff64f1392ff6e1d404aaf23e8c/src/cmd/internal/obj/arm64/asm7.go"> <u>asm7.go</u></a> when Go's internal intermediate representation is translated into arm64 machine code. The assembler will classify an immediate in <a href="https://github.com/golang/go/blob/2f653a5a9e9112ff64f1392ff6e1d404aaf23e8c/src/cmd/internal/obj/arm64/asm7.go#L1905"><u>conclass</u></a> based on bit size and then use that when emitting instructions – extra if needed.</p><p>The Go assembler uses a combination of (<code>mov, add</code>) opcodes for some adds that fit in 16-bit immediates, and prefers (<code>add, add + lsl 12</code>) opcodes for 16-bit+ immediates.   </p><p>Compare a stack of (slightly larger than) <code>1&lt;&lt;15</code>:</p>
            <pre><code>; //go:noinline
; func big_stack() byte {
; 	var big_stack = make([]byte, 1&lt;&lt;15)
; 	return big_stack[0]
; }
MOVD $32776, R27
ADD R27, RSP, R29
MOVD $32784, R27
ADD R27, RSP, RSP
RET
</code></pre>
            <p></p><p>With a stack of <code>1&lt;&lt;16</code>:</p>
            <pre><code>; //go:noinline
; func big_stack() byte {
; 	var big_stack = make([]byte, 1&lt;&lt;16)
; 	return big_stack[0]
; } 
ADD $8, RSP, R29
ADD $(16&lt;&lt;12), R29, R29
ADD $16, RSP, RSP
ADD $(16&lt;&lt;12), RSP, RSP
RET
</code></pre>
            <p>In the larger stack case, there is a point between <code>ADD x, RSP, RSP</code> opcodes where the stack pointer is not pointing to the tip of a stack frame. We thought at first that this was a matter of memory corruption – that in handling async preemption the runtime would push a function call on the stack and corrupt the middle of the stack. However, this goroutine is already in the function epilogue – any data we corrupt is actively in the process of being thrown away. What's the issue then?  </p><p>The Go runtime often needs to <b>unwind</b> the stack, which means walking backwards through the chain of function calls. For example: garbage collection uses it to find live references on the stack, panicking relies on it to evaluate <code>defer</code> functions, and generating stack traces needs to print the call stack. For this to work the stack pointer <b>must be accurate during unwinding</b> because of how golang dereferences sp to determine the calling function. If the stack pointer is partially modified, the unwinder will look for the calling function in the middle of the stack. The underlying data is meaningless when interpreted as directions to a parent stack frame and then the runtime will likely crash. </p>
            <pre><code>//https://github.com/golang/go/blob/66536242fce34787230c42078a7bbd373ef8dcb0/src/runtime/traceback.go#L373

if innermost &amp;&amp; frame.sp &lt; frame.fp || frame.lr == 0 {
    lrPtr = frame.sp
    frame.lr = *(*uintptr)(unsafe.Pointer(lrPtr))
}
</code></pre>
            <p></p><p>When async preemption happens it will push a function call onto the stack but the parent stack frame is no longer correct because sp was only partially adjusted when the preemption happened. The crash flow looks something like this:  </p><ol><li><p>Async preemption happens between the two opcodes that <code>add x, rsp</code> expands to</p></li><li><p>Garbage collection triggers stack unwinding (to check for heap object liveness)</p></li><li><p>The unwinder starts traversing the stack of the problematic goroutine and correctly unwinds up to the problematic function</p></li><li><p>The unwinder dereferences <code>sp</code> to determine the parent function</p></li><li><p>Almost certainly the data behind <code>sp</code> is not a function</p></li><li><p>Crash</p></li></ol>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5LKOBC6lQzuKvwy0vyEfk2/054c9aaedc14d155294a682f7de3a610/BLOG-2906_3.png" />
          </figure><p>We saw earlier a faulting stack trace which ended in <code>(*NetlinkSocket).Receive</code> – in this case stack unwinding faulted while it was trying to determine the parent frame.    </p>
            <pre><code>goroutine 90 gp=0x40042cc000 m=nil [preempted (scan)]:
runtime.asyncPreempt2()
/usr/local/go/src/runtime/preempt.go:306 +0x2c fp=0x40060a25d0 sp=0x40060a25b0 pc=0x55557e299dec
runtime.asyncPreempt()
/usr/local/go/src/runtime/preempt_arm64.s:47 +0x9c fp=0x40060a27c0 sp=0x40060a25d0 pc=0x55557e2dc94c
github.com/vishvananda/netlink/nl.(*NetlinkSocket).Receive(0xff48ce6e060b2848?)
/vendor/github.com/vishvananda/netlink/nl/nl_linux.go:779 +0x130 fp=0x40060b2820 sp=0x40060a27d0 pc=0x55557e9d2880
</code></pre>
            <p></p><p>Once we discovered the root cause we reported it with a reproducer and the bug was quickly fixed. This bug is fixed in <a href="https://github.com/golang/go/commit/e8794e650e05fad07a33fb6e3266a9e677d13fa8"><u>go1.23.12</u></a>, <a href="https://github.com/golang/go/commit/6e1c4529e4e00ab58572deceab74cc4057e6f0b6"><u>go1.24.6</u></a>, and <a href="https://github.com/golang/go/commit/f7cc61e7d7f77521e073137c6045ba73f66ef902"><u>go1.25.0</u></a>. Previously, the go compiler emitted a single <code>add x, rsp</code> instruction and relied on the assembler to split immediates into multiple opcodes as necessary. After this change, stacks larger than 1&lt;&lt;12 will build the offset in a temporary register and then add that to <code>rsp</code> in a single, indivisible opcode. A goroutine can be preempted before or after the stack pointer modification, but never during. This means that the stack pointer is always valid and there is no race condition.</p>
            <pre><code>LDP -8(RSP), (R29, R30)
MOVD $32, R27
MOVK $(1&lt;&lt;16), R27
ADD R27, RSP, RSP
RET</code></pre>
            <p></p><p>This was a very fun problem to debug. We don’t often see bugs where you can accurately blame the compiler. Debugging it took weeks and we had to learn about areas of the Go runtime that people don’t usually need to think about. It’s a nice example of a rare race condition, the sort of bug that can only really be quantified at a large scale.</p><p>We’re always looking for people who enjoy this kind of detective work. <a href="https://www.cloudflare.com/careers/jobs/?department=Engineering"><u>Our engineering teams are hiring</u></a>.   </p> ]]></content:encoded>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">12E3V053vhNrZrU5I2AAV1</guid>
            <dc:creator>Thea Heinen</dc:creator>
        </item>
        <item>
            <title><![CDATA[QUIC restarts, slow problems: udpgrm to the rescue]]></title>
            <link>https://blog.cloudflare.com/quic-restarts-slow-problems-udpgrm-to-the-rescue/</link>
            <pubDate>Wed, 07 May 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ udpgrm is a lightweight daemon for graceful restarts of UDP servers. It leverages SO_REUSEPORT and eBPF to route new and existing flows to the correct server instance. ]]></description>
            <content:encoded><![CDATA[ <p>At Cloudflare, we do everything we can to avoid interruption to our services. We frequently deploy new versions of the code that delivers the services, so we need to be able to restart the server processes to upgrade them without missing a beat. In particular, performing graceful restarts (also known as "zero downtime") for UDP servers has proven to be surprisingly difficult.</p><p>We've <a href="https://blog.cloudflare.com/graceful-upgrades-in-go/"><u>previously</u></a> <a href="https://blog.cloudflare.com/oxy-the-journey-of-graceful-restarts/"><u>written</u></a> about graceful restarts in the context of TCP, which is much easier to handle. We didn't have a strong reason to deal with UDP until recently — when protocols like HTTP3/QUIC became critical. This blog post introduces <b><i>udpgrm</i></b>, a lightweight daemon that helps us to upgrade UDP servers without dropping a single packet.</p><p><a href="https://github.com/cloudflare/udpgrm/blob/main/README.md"><u>Here's the </u><i><u>udpgrm</u></i><u> GitHub repo</u></a>.</p>
    <div>
      <h2>Historical context</h2>
      <a href="#historical-context">
        
      </a>
    </div>
    <p>In the early days of the Internet, UDP was used for stateless request/response communication with protocols like DNS or NTP. Restarts of a server process are not a problem in that context, because it does not have to retain state across multiple requests. However, modern protocols like QUIC, WireGuard, and SIP, as well as online games, use stateful flows. So what happens to the state associated with a flow when a server process is restarted? Typically, old connections are just dropped during a server restart. Migrating the flow state from the old instance to the new instance is possible, but it is complicated and notoriously hard to get right.</p><p>The same problem occurs for TCP connections, but there a common approach is to keep the old instance of the server process running alongside the new instance for a while, routing new connections to the new instance while letting existing ones drain on the old. Once all connections finish or a timeout is reached, the old instance can be safely shut down. The same approach works for UDP, but it requires more involvement from the server process than for TCP.</p><p>In the past, we <a href="https://blog.cloudflare.com/everything-you-ever-wanted-to-know-about-udp-sockets-but-were-afraid-to-ask-part-1/"><u>described</u></a> the <i>established-over-unconnected</i> method. It offers one way to implement flow handoff, but it comes with significant drawbacks: it’s prone to race conditions in protocols with multi-packet handshakes, and it suffers from a scalability issue. Specifically, the kernel hash table used for dispatching packets is keyed only by the local IP:port tuple, which can lead to bucket overfill when dealing with many inbound UDP sockets.</p><p>Now we have found a better method, leveraging Linux’s <code>SO_REUSEPORT</code> API. By placing both old and new sockets into the same REUSEPORT group and using an eBPF program for flow tracking, we can route packets to the correct instance and preserve flow stickiness. This is how <i>udpgrm</i> works.</p>
    <div>
      <h2>REUSEPORT group</h2>
      <a href="#reuseport-group">
        
      </a>
    </div>
    <p>Before diving deeper, let's quickly review the basics. Linux provides the <code>SO_REUSEPORT</code> socket option, typically set after <code>socket()</code> but before <code>bind()</code>. Please note that this has a separate purpose from the better known <code>SO_REUSEADDR</code> socket option.</p><p><code>SO_REUSEPORT</code> allows multiple sockets to bind to the same IP:port tuple. This feature is primarily used for load balancing, letting servers spread traffic efficiently across multiple CPU cores. You can think of it as a way for an IP:port to be associated with multiple packet queues. In the kernel, sockets sharing an IP:port this way are organized into a <i>reuseport group </i>— a term we'll refer to frequently throughout this post.</p>
            <pre><code>┌───────────────────────────────────────────┐
│ reuseport group 192.0.2.0:443             │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ socket #1 │ │ socket #2 │ │ socket #3 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└───────────────────────────────────────────┘
</code></pre>
            <p>Linux supports several methods for distributing inbound packets across a reuseport group. By default, the kernel uses a hash of the packet's 4-tuple to select a target socket. Another method is <code>SO_INCOMING_CPU</code>, which, when enabled, tries to steer packets to sockets running on the same CPU that received the packet. This approach works but has limited flexibility.</p><p>To provide more control, Linux introduced the <code>SO_ATTACH_REUSEPORT_CBPF</code> option, allowing server processes to attach a classic BPF (cBPF) program to make socket selection decisions. This was later extended with <code>SO_ATTACH_REUSEPORT_EBPF</code>, enabling the use of modern eBPF programs. With <a href="https://blog.cloudflare.com/cloudflare-architecture-and-how-bpf-eats-the-world/"><u>eBPF</u></a>, developers can implement arbitrary custom logic. A boilerplate program would look like this:</p>
            <pre><code>SEC("sk_reuseport")
int udpgrm_reuseport_prog(struct sk_reuseport_md *md)
{
    uint64_t socket_identifier = xxxx;
    bpf_sk_select_reuseport(md, &amp;sockhash, &amp;socket_identifier, 0);
    return SK_PASS;
}</code></pre>
            <p>To select a specific socket, the eBPF program calls <code>bpf_sk_select_reuseport</code>, using a reference to a map with sockets (<code>SOCKHASH</code>, <code>SOCKMAP</code>, or the older, mostly obsolete <code>SOCKARRAY</code>), along with a key or index. For example, a declaration of a <code>SOCKHASH</code> might look like this:</p>
            <pre><code>struct {
	__uint(type, BPF_MAP_TYPE_SOCKHASH);
	__uint(max_entries, MAX_SOCKETS);
	__uint(key_size, sizeof(uint64_t));
	__uint(value_size, sizeof(uint64_t));
} sockhash SEC(".maps");</code></pre>
            <p>This <code>SOCKHASH</code> is a hash map that holds references to sockets, even though the value size looks like a scalar 8-byte value. In our case it's indexed by an <code>uint64_t</code> key. This is pretty neat, as it allows for a simple number-to-socket mapping!</p><p>However, there's a catch: <b>the </b><code><b>SOCKHASH</b></code><b> must be populated and maintained from user space (or a separate control plane), outside the eBPF program itself</b>. Keeping this socket map accurate and in sync with the server process state is surprisingly difficult to get right — especially under dynamic conditions like restarts, crashes, or scaling events. The point of <i>udpgrm</i> is to take care of this stuff, so that server processes don’t have to.</p>
    <div>
      <h2>Socket generation and working generation</h2>
      <a href="#socket-generation-and-working-generation">
        
      </a>
    </div>
    <p>Let’s look at how graceful restarts for UDP flows are achieved in <i>udpgrm</i>. To reason about this setup, we’ll need a bit of terminology: A <b>socket generation</b> is a set of sockets within a reuseport group that belong to the same logical application instance:</p>
            <pre><code>┌───────────────────────────────────────────────────┐
│ reuseport group 192.0.2.0:443                     │
│  ┌─────────────────────────────────────────────┐  │
│  │ socket generation 0                         │  │
│  │  ┌───────────┐ ┌───────────┐ ┌───────────┐  │  │
│  │  │ socket #1 │ │ socket #2 │ │ socket #3 │  │  │
│  │  └───────────┘ └───────────┘ └───────────┘  │  │
│  └─────────────────────────────────────────────┘  │
│  ┌─────────────────────────────────────────────┐  │
│  │ socket generation 1                         │  │
│  │  ┌───────────┐ ┌───────────┐ ┌───────────┐  │  │
│  │  │ socket #4 │ │ socket #5 │ │ socket #6 │  │  │
│  │  └───────────┘ └───────────┘ └───────────┘  │  │
│  └─────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────┘</code></pre>
            <p>When a server process needs to be restarted, the new version creates a new socket generation for its sockets. The old version keeps running alongside the new one, using sockets from the previous socket generation.</p><p>Reuseport eBPF routing boils down to two problems:</p><ul><li><p>For new flows, we should choose a socket from the socket generation that belongs to the active server instance.</p></li><li><p>For already established flows, we should choose the appropriate socket — possibly from an older socket generation — to keep the flows sticky. The flows will eventually drain away, allowing the old server instance to shut down.</p></li></ul><p>Easy, right?</p><p>Of course not! The devil is in the details. Let's take it one step at a time.</p><p>Routing new flows is relatively easy. <i>udpgrm</i> simply maintains a reference to the socket generation that should handle new connections. We call this reference the <b>working generation</b>. Whenever a new flow arrives, the eBPF program consults the working generation pointer and selects a socket from that generation.</p>
            <pre><code>┌──────────────────────────────────────────────┐
│ reuseport group 192.0.2.0:443                │
│   ...                                        │
│   Working generation ────┐                   │
│                          V                   │
│           ┌───────────────────────────────┐  │
│           │ socket generation 1           │  │
│           │  ┌───────────┐ ┌──────────┐   │  │
│           │  │ socket #4 │ │ ...      │   │  │
│           │  └───────────┘ └──────────┘   │  │
│           └───────────────────────────────┘  │
│   ...                                        │
└──────────────────────────────────────────────┘</code></pre>
            <p>For this to work, we first need to be able to differentiate packets belonging to new connections from packets belonging to old connections. This is very tricky and highly dependent on the specific UDP protocol. For example, QUIC has an <a href="https://datatracker.ietf.org/doc/html/rfc9000#name-initial-packet"><i><u>initial packet</u></i></a> concept, similar to a TCP SYN, but other protocols might not.</p><p>There needs to be some flexibility in this and <i>udpgrm</i> makes this configurable. Each reuseport group sets a specific <b>flow dissector</b>.</p><p>Flow dissector has two tasks:</p><ul><li><p>It distinguishes new packets from packets belonging to old, already established flows.</p></li><li><p>For recognized flows, it tells <i>udpgrm</i> which specific socket the flow belongs to.</p></li></ul><p>These concepts are closely related and depend on the specific server. Different UDP protocols define flows differently. For example, a naive UDP server might use a typical 5-tuple to define flows, while QUIC uses a "connection ID" field in the QUIC packet header to survive <a href="https://www.rfc-editor.org/rfc/rfc9308.html#section-3.2"><u>NAT rebinding</u></a>.</p><p><i>udpgrm</i> supports three flow dissectors out of the box and is highly configurable to support any UDP protocol. More on this later.</p>
    <div>
      <h2>Welcome udpgrm!</h2>
      <a href="#welcome-udpgrm">
        
      </a>
    </div>
    <p>Now that we covered the theory, we're ready for the business: please welcome <b>udpgrm</b> — UDP Graceful Restart Marshal! <i>udpgrm</i> is a stateful daemon that handles all the complexities of the graceful restart process for UDP. It installs the appropriate eBPF REUSEPORT program, maintains flow state, communicates with the server process during restarts, and reports useful metrics for easier debugging.</p><p>We can describe <i>udpgrm</i> from two perspectives: for administrators and for programmers.</p>
    <div>
      <h2>udpgrm daemon for the system administrator</h2>
      <a href="#udpgrm-daemon-for-the-system-administrator">
        
      </a>
    </div>
    <p><i>udpgrm</i> is a stateful daemon, to run it:</p>
            <pre><code>$ sudo udpgrm --daemon
[ ] Loading BPF code
[ ] Pinning bpf programs to /sys/fs/bpf/udpgrm
[*] Tailing message ring buffer  map_id 936146</code></pre>
            <p>This sets up the basic functionality, prints rudimentary logs, and should be deployed as a dedicated systemd service — loaded after networking. However, this is not enough to fully use <i>udpgrm</i>. <i>udpgrm</i> needs to hook into <code>getsockopt</code>, <code>setsockopt</code>, <code>bind</code>, and <code>sendmsg</code> syscalls, which are scoped to a cgroup. To install the <i>udpgrm</i> hooks, you can install it like this:</p>
            <pre><code>$ sudo udpgrm --install=/sys/fs/cgroup/system.slice</code></pre>
            <p>But a more common pattern is to install it within the <i>current</i> cgroup:</p>
            <pre><code>$ sudo udpgrm --install --self</code></pre>
            <p>Better yet, use it as part of the systemd "service" config:</p>
            <pre><code>[Service]
...
ExecStartPre=/usr/local/bin/udpgrm --install --self</code></pre>
            <p>Once <i>udpgrm</i> is running, the administrator can use the CLI to list reuseport groups, sockets, and metrics, like this:</p>
            <pre><code>$ sudo udpgrm list
[ ] Retrievieng BPF progs from /sys/fs/bpf/udpgrm
192.0.2.0:4433
	netns 0x1  dissector bespoke  digest 0xdead
	socket generations:
		gen  3  0x17a0da  &lt;=  app 0  gen 3
	metrics:
		rx_processed_total 13777528077
...</code></pre>
            <p>Now, with both the <i>udpgrm</i> daemon running, and cgroup hooks set up, we can focus on the server part.</p>
    <div>
      <h2>udpgrm for the programmer</h2>
      <a href="#udpgrm-for-the-programmer">
        
      </a>
    </div>
    <p>We expect the server to create the appropriate UDP sockets by itself. We depend on <code>SO_REUSEPORT</code>, so that each server instance can have a dedicated socket or a set of sockets:</p>
            <pre><code>sd = socket.socket(AF_INET, SOCK_DGRAM, 0)
sd.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
sd.bind(("192.0.2.1", 5201))</code></pre>
            <p>With a socket descriptor handy, we can pursue the <i>udpgrm</i> magic dance. The server communicates with the <i>udpgrm</i> daemon using <code>setsockopt</code> calls. Behind the scenes, udpgrm provides eBPF <code>setsockopt</code> and <code>getsockopt</code> hooks and hijacks specific calls. It's not easy to set up on the kernel side, but when it works, it’s truly awesome. A typical socket setup looks like this:</p>
            <pre><code>try:
    work_gen = sd.getsockopt(IPPROTO_UDP, UDP_GRM_WORKING_GEN)
except OSError:
    raise OSError('Is udpgrm daemon loaded? Try "udpgrm --self --install"')
    
sd.setsockopt(IPPROTO_UDP, UDP_GRM_SOCKET_GEN, work_gen + 1)
for i in range(10):
    v = sd.getsockopt(IPPROTO_UDP, UDP_GRM_SOCKET_GEN, 8);
    sk_gen, sk_idx = struct.unpack('II', v)
    if sk_idx != 0xffffffff:
        break
    time.sleep(0.01 * (2 ** i))
else:
    raise OSError("Communicating with udpgrm daemon failed.")

sd.setsockopt(IPPROTO_UDP, UDP_GRM_WORKING_GEN, work_gen + 1)</code></pre>
            <p>You can see three blocks here:</p><ul><li><p>First, we retrieve the working generation number and, by doing so, check for <i>udpgrm</i> presence. Typically, <i>udpgrm</i> absence is fine for non-production workloads.</p></li><li><p>Then we register the socket to an arbitrary socket generation. We choose <code>work_gen + 1</code> as the value and verify that the registration went through correctly.</p></li><li><p>Finally, we bump the working generation pointer.</p></li></ul><p>That's it! Hopefully, the API presented here is clear and reasonable. Under the hood, the <i>udpgrm</i> daemon installs the REUSEPORT eBPF program, sets up internal data structures, collects metrics, and manages the sockets in a <code>SOCKHASH</code>.</p>
    <div>
      <h2>Advanced socket creation with udpgrm_activate.py</h2>
      <a href="#advanced-socket-creation-with-udpgrm_activate-py">
        
      </a>
    </div>
    <p>In practice, we often need sockets bound to low ports like <code>:443</code>, which requires elevated privileges like <code>CAP_NET_BIND_SERVICE</code>. It's usually better to configure listening sockets outside the server itself. A typical pattern is to pass the listening sockets using <a href="https://0pointer.de/blog/projects/socket-activation.html"><u>socket activation</u></a>.</p><p>Sadly, systemd cannot create a new set of UDP <code>SO_REUSEPORT</code> sockets for each server instance. To overcome this limitation, <i>udpgrm</i> provides a script called <code>udpgrm_activate.py</code>, which can be used like this:</p>
            <pre><code>[Service]
Type=notify                 # Enable access to fd store
NotifyAccess=all            # Allow access to fd store from ExecStartPre
FileDescriptorStoreMax=128  # Limit of stored sockets must be set

ExecStartPre=/usr/local/bin/udpgrm_activate.py test-port 0.0.0.0:5201</code></pre>
            <p>Here, <code>udpgrm_activate.py</code> binds to <code>0.0.0.0:5201</code> and stores the created socket in the systemd FD store under the name <code>test-port</code>. The server <code>echoserver.py</code> will inherit this socket and receive the appropriate <code>FD_LISTEN</code> environment variables, following the typical systemd socket activation pattern.</p>
    <div>
      <h2>Systemd service lifetime</h2>
      <a href="#systemd-service-lifetime">
        
      </a>
    </div>
    <p>Systemd typically can't handle more than one server instance running at the same time. It prefers to kill the old instance quickly. It supports the "at most one" server instance model, not the "at least one" model that we want. To work around this, <i>udpgrm</i> provides a <b>decoy</b> script that will exit when systemd asks it to, while the actual old instance of the server can stay active in the background.</p>
            <pre><code>[Service]
...
ExecStart=/usr/local/bin/mmdecoy examples/echoserver.py

Restart=always             # if pid dies, restart it.
KillMode=process           # Kill only decoy, keep children after stop.
KillSignal=SIGTERM         # Make signals explicit</code></pre>
            <p>At this point, we showed a full template for a <i>udpgrm</i> enabled server that contains all three elements: <code>udpgrm --install --self</code> for cgroup hooks, <code>udpgrm_activate.py</code> for socket creation, and <code>mmdecoy</code> for fooling systemd service lifetime checks.</p>
            <pre><code>[Service]
Type=notify                 # Enable access to fd store
NotifyAccess=all            # Allow access to fd store from ExecStartPre
FileDescriptorStoreMax=128  # Limit of stored sockets must be set

ExecStartPre=/usr/local/bin/udpgrm --install --self
ExecStartPre=/usr/local/bin/udpgrm_activate.py --no-register test-port 0.0.0.0:5201
ExecStart=/usr/local/bin/mmdecoy PWD/examples/echoserver.py

Restart=always             # if pid dies, restart it.
KillMode=process           # Kill only decoy, keep children after stop. 
KillSignal=SIGTERM         # Make signals explicit</code></pre>
            
    <div>
      <h2>Dissector modes</h2>
      <a href="#dissector-modes">
        
      </a>
    </div>
    <p>We've discussed the <i>udpgrm</i> daemon, the <i>udpgrm</i> setsockopt API, and systemd integration, but we haven't yet covered the details of routing logic for old flows. To handle arbitrary protocols, <i>udpgrm</i> supports three <b>dissector modes</b> out of the box:</p><p><b>DISSECTOR_FLOW</b>: <i>udpgrm</i> maintains a flow table indexed by a flow hash computed from a typical 4-tuple. It stores a target socket identifier for each flow. The flow table size is fixed, so there is a limit to the number of concurrent flows supported by this mode. To mark a flow as "assured," <i>udpgrm</i> hooks into the <code>sendmsg</code> syscall and saves the flow in the table only when a message is sent.</p><p><b>DISSECTOR_CBPF</b>: A cookie-based model where the target socket identifier — called a udpgrm cookie — is encoded in each incoming UDP packet. For example, in QUIC, this identifier can be stored as part of the connection ID. The dissection logic is expressed as cBPF code. This model does not require a flow table in <i>udpgrm</i> but is harder to integrate because it needs protocol and server support.</p><p><b>DISSECTOR_NOOP</b>: A no-op mode with no state tracking at all. It is useful for traditional UDP services like DNS, where we want to avoid losing even a single packet during an upgrade.</p><p>Finally, <i>udpgrm</i> provides a template for a more advanced dissector called <b>DISSECTOR_BESPOKE</b>. Currently, it includes a QUIC dissector that can decode the QUIC TLS SNI and direct specific TLS hostnames to specific socket generations.</p><p>For more details, <a href="https://github.com/cloudflare/udpgrm/blob/main/README.md"><u>please consult the </u><i><u>udpgrm</u></i><u> README</u></a>. In short: the FLOW dissector is the simplest one, useful for old protocols. CBPF dissector is good for experimentation when the protocol allows storing a custom connection id (cookie) — we used it to develop our own QUIC Connection ID schema (also named DCID) — but it's slow, because it interprets cBPF inside eBPF (yes really!). NOOP is useful, but only for very specific niche servers. The real magic is in the BESPOKE type, where users can create arbitrary, fast, and powerful dissector logic.</p>
    <div>
      <h2>Summary</h2>
      <a href="#summary">
        
      </a>
    </div>
    <p>The adoption of QUIC and other UDP-based protocols means that gracefully restarting UDP servers is becoming an increasingly important problem. To our knowledge, a reusable, configurable and easy to use solution didn't exist yet. The <i>udpgrm</i> project brings together several novel ideas: a clean API using <code>setsockopt()</code>, careful socket-stealing logic hidden under the hood, powerful and expressive configurable dissectors, and well-thought-out integration with systemd.</p><p>While <i>udpgrm</i> is intended to be easy to use, it hides a lot of complexity and solves a genuinely hard problem. The core issue is that the Linux Sockets API has not kept up with the modern needs of UDP.</p><p>Ideally, most of this should really be a feature of systemd. That includes supporting the "at least one" server instance mode, UDP <code>SO_REUSEPORT</code> socket creation, installing a <code>REUSEPORT_EBPF</code> program, and managing the "working generation" pointer. We hope that <i>udpgrm</i> helps create the space and vocabulary for these long-term improvements.</p> ]]></content:encoded>
            <category><![CDATA[UDP]]></category>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">2baeaA3qbgFISPMjlZ74a4</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
        <item>
            <title><![CDATA[How to execute an object file: part 4, AArch64 edition]]></title>
            <link>https://blog.cloudflare.com/how-to-execute-an-object-file-part-4/</link>
            <pubDate>Fri, 17 Nov 2023 14:00:35 GMT</pubDate>
            <description><![CDATA[ The initial posts are dedicated to the x86 architecture. Since then, the fleet of our working machines has expanded to include a large and growing number of ARM CPUs. This time we’ll repeat this exercise for the aarch64 architecture. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5Ih4pvbZshdUy2ihfodYAU/7800842ad2c0270609b36a8a99d0ceb4/image1-1.png" />
            
            </figure><p>Translating source code written in a high-level programming language into an executable binary typically involves a series of steps, namely compiling and assembling the code into object files, and then linking those object files into the final executable. However, there are certain scenarios where it can be useful to apply an alternate approach that involves executing object files directly, bypassing the linker. For example, we might use it for malware analysis or when part of the code requires an incompatible compiler. We’ll be focusing on the latter scenario: when one of our libraries needed to be compiled differently from the rest of the code. Learning how to execute an object file directly will give you a much better sense of how code is compiled and linked together.</p><p>To demonstrate how this was done, we have previously published a series of posts on executing an object file:</p><ul><li><p><a href="/how-to-execute-an-object-file-part-1/">How to execute an object file: Part 1</a></p></li><li><p><a href="/how-to-execute-an-object-file-part-2/">How to execute an object file: Part 2</a></p></li><li><p><a href="/how-to-execute-an-object-file-part-3/">How to execute an object file: Part 3</a></p></li></ul><p>The initial posts are dedicated to the x86 architecture. Since then the fleet of our working machines has expanded to include a large and growing number of ARM CPUs. This time we’ll repeat this exercise for the aarch64 architecture. You can pause here to read the previous blog posts before proceeding with this one, or read through the brief summary below and reference the earlier posts for more detail. We might reiterate some theory as working with ELF files can be daunting, if it’s not your day-to-day routine. Also, please be mindful that for simplicity, these examples omit bounds and integrity checks. Let the journey begin!</p>
    <div>
      <h2>Introduction</h2>
      <a href="#introduction">
        
      </a>
    </div>
    <p>In order to obtain an object file or an executable binary from a high-level compiled programming language the code needs to be processed by three components: compiler, assembler and linker. The compiler generates an assembly listing. This assembly listing is picked up by the assembler and translated into an object file. All source files, if a program contains multiple, go through these two steps generating an object file for each source file. At the final step the linker unites all object files into one binary, additionally resolving references to the shared libraries (i.e. we don’t implement the <code>printf</code> function each time, rather we take it from a system library). Even though the approach is platform independent, the compiler output varies by platform as the assembly listing is closely tied to the CPU architecture.</p><p>GCC (GNU Compiler Collection) can run each step: compiler, assembler and linker separately for us:</p><p>main.c:</p>
            <pre><code>#include &lt;stdio.h&gt;

int main(void)
{
	puts("Hello, world!");
	return 0;
}</code></pre>
            <p>Compiler (output <code>main.s</code> - assembly listing):</p>
            <pre><code>$ gcc -S main.c
$ ls
main.c  main.s</code></pre>
            <p>Assembler (output <code>main.o</code> - an object file):</p>
            <pre><code>$ gcc -c main.s -o main.o
$ ls
main.c  main.o  main.s</code></pre>
            <p>Linker (<code>main</code> - an object file):</p>
            <pre><code>$ gcc main.o -o main
$ ls
main  main.c  main.o  main.s
$ ./main
Hello, world!</code></pre>
            <p>All the examples assume gcc is running on a native aarch64 architecture or include a cross compilation flag for those who want to reproduce and have no aarch64.</p><p>We have two object files in the output above: <code>main.o</code> and <code>main</code>. Object files are files encoded with the <a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">ELF (Executable and Linkable Format)</a> standard. Although, <code>main.o</code> is an ELF file, it doesn’t contain all the information to be fully executable.</p>
            <pre><code>$ file main.o
main.o: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), not stripped

$ file main
main: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically
linked, interpreter /lib/ld-linux-aarch64.so.1,
BuildID[sha1]=d3ecd2f8ac3b2dec11ed4cc424f15b3e1f130dd4, for GNU/Linux 3.7.0, not stripped</code></pre>
            
    <div>
      <h2>The ELF File</h2>
      <a href="#the-elf-file">
        
      </a>
    </div>
    <p>The central idea of this series of blog posts is to understand how to resolve dependencies from object files without directly involving the linker. For illustrative purposes we generated an object file based on some C-code and used it as a library for our main program. Before switching to the code, we need to understand the basics of the ELF structure.</p><p>Each ELF file is made up of one <i>ELF header</i>, followed by file data. The data can include: a <i>program header</i> table, a <i>section header</i> table, and the data which is referred to by the program or section header tables.</p>
    <div>
      <h3>The ELF Header</h3>
      <a href="#the-elf-header">
        
      </a>
    </div>
    <p>The ELF header provides some basic information about the file: what architecture the file is compiled for, the program entry point and the references to other tables.</p><p>The ELF Header:</p>
            <pre><code>$ readelf -h main
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x640
  Start of program headers:          64 (bytes into file)
  Start of section headers:          68576 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28</code></pre>
            
    <div>
      <h3>The ELF Program Header</h3>
      <a href="#the-elf-program-header">
        
      </a>
    </div>
    <p>The execution process of almost every program starts from an auxiliary program, called loader, which arranges the memory and calls the program’s entry point. In the following output the loader is marked with a line <code>“Requesting program interpreter: /lib/ld-linux-aarch64.so.1”</code>. The whole program memory is split into different segments with associated size, permissions and type (which instructs the loader on how to interpret this block of memory). Because the execution process should be performed in the shortest possible time, the <i>sections</i> with the same characteristics and located nearby are grouped into bigger blocks — <i>segments</i> — and placed in the <i>program header</i>. We can say that the <i>program header</i> summarizes the types of data that appear in the <i>section header</i>.</p><p>The ELF Program Header:</p>
            <pre><code>$ readelf -Wl main

Elf file type is DYN (Position-Independent Executable file)
Entry point 0x640
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R   0x8
  INTERP         0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R   0x1
      [Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x00088c 0x00088c R E 0x10000
  LOAD           0x00fdc8 0x000000000001fdc8 0x000000000001fdc8 0x000270 0x000278 RW  0x10000
  DYNAMIC        0x00fdd8 0x000000000001fdd8 0x000000000001fdd8 0x0001e0 0x0001e0 RW  0x8
  NOTE           0x000254 0x0000000000000254 0x0000000000000254 0x000044 0x000044 R   0x4
  GNU_EH_FRAME   0x0007a0 0x00000000000007a0 0x00000000000007a0 0x00003c 0x00003c R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x00fdc8 0x000000000001fdc8 0x000000000001fdc8 0x000238 0x000238 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .init_array .fini_array .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.gnu.build-id .note.ABI-tag 
   06     .eh_frame_hdr 
   07     
   08     .init_array .fini_array .dynamic .got </code></pre>
            
    <div>
      <h3>The ELF Section Header</h3>
      <a href="#the-elf-section-header">
        
      </a>
    </div>
    <p>In the source code of high-level languages, variables, functions, and constants are mixed together. However, in assembly you might see that the data and instructions are separated into different blocks. The ELF file content is divided in an even more granular way. For example, variables with initial values are placed into different sections than the uninitialized ones. This approach optimizes for space, otherwise the values for uninitialized variables would be filled with zeros. Along with the space efficiency, there are security reasons for stratification — executable instructions can’t have writable permissions, while memory containing variables can't be executable. The section header describes each of these sections.</p><p>The ELF Section Header:</p>
            <pre><code>$ readelf -SW main
There are 29 section headers, starting at offset 0x10be0:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000000238 000238 00001b 00   A  0   0  1
  [ 2] .note.gnu.build-id NOTE            0000000000000254 000254 000024 00   A  0   0  4
  [ 3] .note.ABI-tag     NOTE            0000000000000278 000278 000020 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0000000000000298 000298 00001c 00   A  5   0  8
  [ 5] .dynsym           DYNSYM          00000000000002b8 0002b8 0000f0 18   A  6   3  8
  [ 6] .dynstr           STRTAB          00000000000003a8 0003a8 000092 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          000000000000043a 00043a 000014 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         0000000000000450 000450 000030 00   A  6   1  8
  [ 9] .rela.dyn         RELA            0000000000000480 000480 0000c0 18   A  5   0  8
  [10] .rela.plt         RELA            0000000000000540 000540 000078 18  AI  5  22  8
  [11] .init             PROGBITS        00000000000005b8 0005b8 000018 00  AX  0   0  4
  [12] .plt              PROGBITS        00000000000005d0 0005d0 000070 00  AX  0   0 16
  [13] .text             PROGBITS        0000000000000640 000640 000134 00  AX  0   0 64
  [14] .fini             PROGBITS        0000000000000774 000774 000014 00  AX  0   0  4
  [15] .rodata           PROGBITS        0000000000000788 000788 000016 00   A  0   0  8
  [16] .eh_frame_hdr     PROGBITS        00000000000007a0 0007a0 00003c 00   A  0   0  4
  [17] .eh_frame         PROGBITS        00000000000007e0 0007e0 0000ac 00   A  0   0  8
  [18] .init_array       INIT_ARRAY      000000000001fdc8 00fdc8 000008 08  WA  0   0  8
  [19] .fini_array       FINI_ARRAY      000000000001fdd0 00fdd0 000008 08  WA  0   0  8
  [20] .dynamic          DYNAMIC         000000000001fdd8 00fdd8 0001e0 10  WA  6   0  8
  [21] .got              PROGBITS        000000000001ffb8 00ffb8 000030 08  WA  0   0  8
  [22] .got.plt          PROGBITS        000000000001ffe8 00ffe8 000040 08  WA  0   0  8
  [23] .data             PROGBITS        0000000000020028 010028 000010 00  WA  0   0  8
  [24] .bss              NOBITS          0000000000020038 010038 000008 00  WA  0   0  1
  [25] .comment          PROGBITS        0000000000000000 010038 00001f 01  MS  0   0  1
  [26] .symtab           SYMTAB          0000000000000000 010058 000858 18     27  66  8
  [27] .strtab           STRTAB          0000000000000000 0108b0 00022c 00      0   0  1
  [28] .shstrtab         STRTAB          0000000000000000 010adc 000103 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), p (processor specific)</code></pre>
            
    <div>
      <h2>Executing example from Part 1 on aarch64</h2>
      <a href="#executing-example-from-part-1-on-aarch64">
        
      </a>
    </div>
    <p>Actually, our <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/1">initial code</a> from <a href="/how-to-execute-an-object-file-part-1/">Part 1</a> works on aarch64 as is!</p><p>Let’s have a quick summary about what was done in the code:</p><ol><li><p>We need to find the code of two functions (<code>add5</code> and <code>add10</code>) in the <code>.text</code> section of our object file (<code>obj.o</code>)</p></li><li><p>Load the functions in the executable memory</p></li><li><p>Return the memory locations of the functions to the main program</p></li></ol><p>There is one nuance: even though all the sections are in the section header, neither of them have a string name. Without the names we can’t identify them. However, having an additional character field for each section in the ELF structure would be inefficient for the space — it must be limited by some maximum length and those names which are shorter would leave the space unfilled. Instead, ELF provides an additional section, <code>.shstrtab</code>. This string table concatenates all the names where each name ends with a null terminated byte. We can iterate over the names and match with an offset held by other sections to reference their name. But how do we find <code>.shstrtab</code> itself if we don’t have a name? To solve this chicken and egg problem, the ELF program header provides a direct pointer to <code>.shstrtab</code>. The similar approach is applied to two other sections: <code>.symtab</code> and <code>.strtab</code>. Where <code>.symtab</code> contains all information about the symbols and <code>.strtab</code> holds the list of symbol names. In the code we work with these tables to resolve all their dependencies and find our functions.</p>
    <div>
      <h2>Executing example from Part 2 on aarch64</h2>
      <a href="#executing-example-from-part-2-on-aarch64">
        
      </a>
    </div>
    <p>At the beginning of the second blog post on <a href="/how-to-execute-an-object-file-part-2/">how to execute an object file</a> we made the function <code>add10</code> depend on <code>add5</code> instead of being self-contained. This is the first time when we faced relocations. <i>Relocations</i> is the process of loading symbols defined outside the current scope. The relocated symbols can present global or thread-local variables, constant, functions, etc. We’ll start from checking assembly instructions which trigger relocations and uncovering how the ELF format handles them in a more general way.</p><p>After making <code>add10</code> depend on <code>add5</code> our aarch64 version stopped working as well, similarly to the x86. Let’s take a look at assembly listing:</p>
            <pre><code>$ objdump --disassemble --section=.text obj.o

obj.o:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000000000 &lt;add5&gt;:
   0:	d10043ff 	sub	sp, sp, #0x10
   4:	b9000fe0 	str	w0, [sp, #12]
   8:	b9400fe0 	ldr	w0, [sp, #12]
   c:	11001400 	add	w0, w0, #0x5
  10:	910043ff 	add	sp, sp, #0x10
  14:	d65f03c0 	ret

0000000000000018 &lt;add10&gt;:
  18:	a9be7bfd 	stp	x29, x30, [sp, #-32]!
  1c:	910003fd 	mov	x29, sp
  20:	b9001fe0 	str	w0, [sp, #28]
  24:	b9401fe0 	ldr	w0, [sp, #28]
  28:	94000000 	bl	0 &lt;add5&gt;
  2c:	b9001fe0 	str	w0, [sp, #28]
  30:	b9401fe0 	ldr	w0, [sp, #28]
  34:	94000000 	bl	0 &lt;add5&gt;
  38:	a8c27bfd 	ldp	x29, x30, [sp], #32
  3c:	d65f03c0 	ret</code></pre>
            <p>Have you noticed that all the hex values in the second column are exactly the same length, in contrast with the instructions lengths seen for x86 in Part 2 of our series? This is because all Armv8-A instructions are presented in 32 bits. Since it is impossible to encode every immediate value into less than 32 bits, some operations require more than one instruction, as we’ll see later. For now, we’re interested in one instruction <code>- bl</code> (<a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/BL--Branch-with-Link-?lang=en">branch with link</a>) on rows <code>28</code> and <code>34</code>. The <code>bl</code> is a “jump” instruction, but before the jump it preserves the next instruction after the current one in the link register (<code>lr</code>). When the callee finishes execution the caller address is recovered from <code>lr</code>. Usually, the aarch64 instructions reserve the last 6 bits [31:26] for opcode and some auxiliary fields such as running architecture (32 or 64 bits), condition flag and others. Remaining bits are shared between arguments like source register, destination register and immediate value. Since the <code>bl</code> instruction does not require a source or destination register, the full 26 bits can be used to encode the immediate offset instead. However, 26 bits can only encode a small range (+/-32 MB), but because the jump can only target a beginning of an instruction, it must always be aligned to 4 bytes, which increases the effective range of the encoded immediate fourfold, to +/-128 MB.</p><p>Similarly to what we did in <a href="/how-to-execute-an-object-file-part-2/">Part 2</a> we’re going to resolve our relocations - first by manually calculating the correct addresses and then by using an approach similar to what the linker does. The current value of our <code>bl</code> instruction is <code>94000000</code> or in binary representation <code>100101**00000000000000000000000000**</code>. All 26 bits are zeros, so we don't jump anywhere. The address is calculated by an offset from the current <i>program counter</i> (<code>pc</code>), which can be positive or negative. In our case we expect it to be <code>-0x28</code> and <code>-0x34</code>. As described above, it should be divided by 4 and taken as <a href="https://en.wikipedia.org/wiki/Two%27s_complement">two's complements</a>: <code>-0x28 / 4 = -0xA == 0xFFFFFFF6</code> and <code>-0x34 / 4 = -0xD == 0xFFFFFFF3</code>. From these values we need to take the lower 26 bits and concatenate them with the initial 6 bits to get the final instruction. So, the final ones will be: <code>100101**11111111111111111111110110** == 0x97FFFFF6</code> and <code>100101**11111111111111111111110011** == 0x97FFFFF3</code>. Have you noticed that all the distance calculations are done relative to the <code>bl</code> (or current <code>pc</code>), not the next instruction as in x86?</p><p>Let’s add to the code and execute:</p>
            <pre><code>... 

static void parse_obj(void)
{
	...
	/* copy the contents of `.text` section from the ELF file */
	memcpy(text_runtime_base, obj.base + text_hdr-&gt;sh_offset, text_hdr-&gt;sh_size);

	*((uint32_t *)(text_runtime_base + 0x28)) = 0x97FFFFF6;
	*((uint32_t *)(text_runtime_base + 0x34)) = 0x97FFFFF3;

	/* make the `.text` copy readonly and executable */
	if (mprotect(text_runtime_base, page_align(text_hdr-&gt;sh_size), PROT_READ | PROT_EXEC)) {
	...</code></pre>
            <p>Compile and run:</p>
            <pre><code>$ gcc -o loader loader.c
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52</code></pre>
            <p>It works! But this is not how the linker handles the relocations. The linker resolves relocation based on the type and formula assigned to this type. In our <a href="/how-to-execute-an-object-file-part-2/">Part 2</a> we investigated it quite well. Here again we need to find the type and check the formula for this type:</p>
            <pre><code>$ readelf --relocs obj.o

Relocation section '.rela.text' at offset 0x228 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000028  000a0000011b R_AARCH64_CALL26  0000000000000000 add5 + 0
000000000034  000a0000011b R_AARCH64_CALL26  0000000000000000 add5 + 0

Relocation section '.rela.eh_frame' at offset 0x258 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000001c  000200000105 R_AARCH64_PREL32  0000000000000000 .text + 0
000000000034  000200000105 R_AARCH64_PREL32  0000000000000000 .text + 18</code></pre>
            <p>Our Type is R_AARCH64_CALL26 and the <a href="https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#5733relocation-operations">formula</a> for it is:</p><table>
	<tbody>
		<tr>
			<td>
			<p><span><span><span><b>ELF64 Code</b></span></span></span></p>
			</td>
			<td>
			<p><span><span><span><b>Name</b></span></span></span></p>
			</td>
			<td>
			<p><span><span><span><b>Operation</b></span></span></span></p>
			</td>
		</tr>
		<tr>
			<td>
			<p><span><span><span>283</span></span></span></p>
			</td>
			<td>
			<p><span><span><span>R_&lt;CLS&gt;_CALL26</span></span></span></p>
			</td>
			<td>
			<p><span><span><span>S + A - P</span></span></span></p>
			</td>
		</tr>
	</tbody>
</table><p>where:</p><ul><li><p><code>S</code> (when used on its own) is the address of the symbol</p></li><li><p><code>A</code> is the addend for the relocation</p></li><li><p><code>P</code> is the address of the place being relocated (derived from <code>r_offset</code>)</p></li></ul><p>Here are the relevant changes to loader.c:</p>
            <pre><code>/* Replace `#define R_X86_64_PLT32 4` with our Type */
#define R_AARCH64_CALL26 283
...

static void do_text_relocations(void)
{
	...
	uint32_t val;

	switch (type)
	{
	case R_AARCH64_CALL26:
		/* The mask separates opcode (6 bits) and the immediate value */
		uint32_t mask_bl = (0xffffffff &lt;&lt; 26);
		/* S+A-P, divided by 4 */
		val = (symbol_address + relocations[i].r_addend - patch_offset) &gt;&gt; 2;
		/* Concatenate opcode and value to get final instruction */
		*((uint32_t *)patch_offset) &amp;= mask_bl;
		val &amp;= ~mask_bl;
		*((uint32_t *)patch_offset) |= val;
		break;
	}
	...
}</code></pre>
            <p>Compile and run:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader
Calculated relocation: 0x97fffff6
Calculated relocation: 0x97fffff3
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52</code></pre>
            <p>So far so good. The next challenge is to <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/2/obj.c#L16-L31">add constant data and global variables</a> to our object file and check relocations again:</p>
            <pre><code>$ readelf --relocs --wide obj.o

Relocation section '.rela.text' at offset 0x388 contains 8 entries:
    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
0000000000000000  0000000500000113 R_AARCH64_ADR_PREL_PG_HI21 0000000000000000 .rodata + 0
0000000000000004  0000000500000115 R_AARCH64_ADD_ABS_LO12_NC 0000000000000000 .rodata + 0
000000000000000c  0000000300000113 R_AARCH64_ADR_PREL_PG_HI21 0000000000000000 .data + 0
0000000000000010  0000000300000115 R_AARCH64_ADD_ABS_LO12_NC 0000000000000000 .data + 0
0000000000000024  0000000300000113 R_AARCH64_ADR_PREL_PG_HI21 0000000000000000 .data + 0
0000000000000028  0000000300000115 R_AARCH64_ADD_ABS_LO12_NC 0000000000000000 .data + 0
0000000000000068  000000110000011b R_AARCH64_CALL26       0000000000000040 add5 + 0
0000000000000074  000000110000011b R_AARCH64_CALL26       0000000000000040 add5 + 0
...</code></pre>
            <p>We have even two new relocations: <code>R_AARCH64_ADD_ABS_LO12_NC</code> and <code>R_AARCH64_ADR_PREL_PG_HI21</code>. Their formulas are:</p><table>
	<tbody>
		<tr>
			<td>
			<p><span><span><span><b>ELF64 Code</b></span></span></span></p>
			</td>
			<td>
			<p><span><span><span><b>Name</b></span></span></span></p>
			</td>
			<td>
			<p><span><span><span><b>Operation</b></span></span></span></p>
			</td>
		</tr>
		<tr>
			<td>
			<p><span><span><span><span>275</span></span></span></span></p>
			</td>
			<td>
			<p><span><span><span><span>R_&lt;CLS&gt;_ ADR_PREL_PG_HI21</span></span></span></span></p>
			</td>
			<td>
			<p><span><span><span><span>Page(S+A) - Page(P)</span></span></span></span></p>
			</td>
		</tr>
		<tr>
			<td>
			<p><span><span><span>277</span></span></span></p>
			</td>
			<td>
			<p><span><span><span>R_&lt;CLS&gt;_ ADD_ABS_LO12_NC</span></span></span></p>
			</td>
			<td>
			<p><span><span><span>S + A</span></span></span></p>
			</td>
		</tr>
	</tbody>
</table><p>where:</p><p><code>Page(expr)</code> is the page address of the expression expr, defined as <code>(expr &amp; ~0xFFF)</code>. (This applies even if the machine page size supported by the platform has a different value.)</p><p>It’s a bit unclear why we have two new types, while in x86 we had only one. Let’s investigate the assembly code:</p>
            <pre><code>$ objdump --disassemble --section=.text obj.o

obj.o:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000000000 &lt;get_hello&gt;:
   0:	90000000 	adrp	x0, 0 &lt;get_hello&gt;
   4:	91000000 	add	x0, x0, #0x0
   8:	d65f03c0 	ret

000000000000000c &lt;get_var&gt;:
   c:	90000000 	adrp	x0, 0 &lt;get_hello&gt;
  10:	91000000 	add	x0, x0, #0x0
  14:	b9400000 	ldr	w0, [x0]
  18:	d65f03c0 	ret

000000000000001c &lt;set_var&gt;:
  1c:	d10043ff 	sub	sp, sp, #0x10
  20:	b9000fe0 	str	w0, [sp, #12]
  24:	90000000 	adrp	x0, 0 &lt;get_hello&gt;
  28:	91000000 	add	x0, x0, #0x0
  2c:	b9400fe1 	ldr	w1, [sp, #12]
  30:	b9000001 	str	w1, [x0]
  34:	d503201f 	nop
  38:	910043ff 	add	sp, sp, #0x10
  3c:	d65f03c0 	ret</code></pre>
            <p>We see that all <code>adrp</code> instructions are followed by <code>add</code> instructions. The <code>[add](https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADD--immediate---Add--immediate--?lang=en)</code> instruction adds an immediate value to the source register and writes the result to the destination register. The source and destination registers can be the same, the immediate value is 12 bits. The <code>[adrp](https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADRP--Form-PC-relative-address-to-4KB-page-?lang=en)</code> instruction generates a <code>pc</code>-relative (program counter) address and writes the result to the destination register. It takes <code>pc</code> of the instruction itself and adds a 21-bit immediate value shifted left by 12 bits. If the immediate value weren’t shifted it would lie in a range of +/-1 MB memory, which isn’t enough. The left shift increases the range up to +/-1 GB. However, because the 12 bits are masked out with the shift, we need to store them somewhere and restore later. That’s why we see add instruction following <code>adrp</code> and two types instead of one. Also, it’s a bit tricky to encode <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADRP--Form-PC-relative-address-to-4KB-page-?lang=en"><code>adrp</code></a>: 2 low bits of immediate value are placed in the position 30:29 and the rest in the position 23:5. Due to size limitations, the aarch64 instructions try to make the most out of 32 bits.</p><p>In the code we are going to use the formulas to calculate the values and description of <code>adrp</code> and <code>add</code> instructions to obtain the final opcode:</p>
            <pre><code>#define R_AARCH64_CALL26 283
#define R_AARCH64_ADD_ABS_LO12_NC 277
#define R_AARCH64_ADR_PREL_PG_HI21 275
...

{
case R_AARCH64_CALL26:
	/* The mask separates opcode (6 bits) and the immediate value */
	uint32_t mask_bl = (0xffffffff &lt;&lt; 26);
	/* S+A-P, divided by 4 */
	val = (symbol_address + relocations[i].r_addend - patch_offset) &gt;&gt; 2;
	/* Concatenate opcode and value to get final instruction */
	*((uint32_t *)patch_offset) &amp;= mask_bl;
	val &amp;= ~mask_bl;
	*((uint32_t *)patch_offset) |= val;
	break;
case R_AARCH64_ADD_ABS_LO12_NC:
	/* The mask of `add` instruction to separate 
	* opcode, registers and calculated value 
	*/
	uint32_t mask_add = 0b11111111110000000000001111111111;
	/* S + A */
	uint32_t val = *(symbol_address + relocations[i].r_addend);
	val &amp;= ~mask_add;
	*((uint32_t *)patch_offset) &amp;= mask_add;
	/* Final instruction */
	*((uint32_t *)patch_offset) |= val;
case R_AARCH64_ADR_PREL_PG_HI21:
	/* Page(S+A)-Page(P), Page(expr) is defined as (expr &amp; ~0xFFF) */
	val = (((uint64_t)(symbol_address + relocations[i].r_addend)) &amp; ~0xFFF) - (((uint64_t)patch_offset) &amp; ~0xFFF);
	/* Shift right the calculated value by 12 bits.
	 * During decoding it will be shifted left as described above, 
	 * so we do the opposite.
	*/
	val &gt;&gt;= 12;
	/* Separate the lower and upper bits to place them in different positions */ 
	uint32_t immlo = (val &amp; (0xf &gt;&gt; 2)) &lt;&lt; 29 ;
	uint32_t immhi = (val &amp; ((0xffffff &gt;&gt; 13) &lt;&lt; 2)) &lt;&lt; 22;
	*((uint32_t *)patch_offset) |= immlo;
	*((uint32_t *)patch_offset) |= immhi;
	break;
}</code></pre>
            <p>Compile and run:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52
Executing get_hello...
get_hello() = Hello, world!
Executing get_var...
get_var() = 5
Executing set_var(42)...
Executing get_var again...
get_var() = 42</code></pre>
            <p>It works! The final code is <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/4/2">here</a>.</p>
    <div>
      <h2>Executing example from Part 3 on aarch64</h2>
      <a href="#executing-example-from-part-3-on-aarch64">
        
      </a>
    </div>
    <p>Our <a href="/how-to-execute-an-object-file-part-3/">Part 3</a> is about resolving external dependencies. When we write code we don’t think much about how to allocate memory or print debug information to the console. Instead, we involve functions from the system libraries. But the code of system libraries needs to be passed through to our programs somehow. Additionally, for optimization purposes, it would be nice if this code would be stored in one place and shared between all programs. And another wish — we don’t want to resolve all the functions and global variables from the libraries, only those which we need and at those times when we need them. To solve these problems, ELF introduced two sections: PLT (the procedure linkage table) and GOT (the global offset table). The dynamic loader creates a list which contains all external functions and variables from the shared library, but doesn’t resolve them immediately; instead they are placed in the PLT section. Each external symbol is presented by a small function, a stub, e.g. <code>puts@plt</code>. When an external symbol is requested, the stub checks if it was resolved previously. If not, the stub searches for an absolute address of the symbol, returns to the requester and writes it in the GOT table. The next time, the address returns directly from the GOT table.</p><p>In <a href="/how-to-execute-an-object-file-part-3/">Part 3</a> we implemented a simplified PLT/GOT resolution. Firstly, we added a new function <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/3/obj.c#L35"><code>say_hello</code></a> in the <code>obj.c</code>, which calls unresolved system library function <code>puts</code>. Further we added an optional wrapper <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/3/loader.c#L73"><code>my_puts</code></a> in the <code>loader.c</code>. The wrapper isn’t required, we could’ve resolved directly to a standard function, but it's a good example of how the implementation of some functions can be overwritten with custom code. In the next steps we added our PLT/GOT resolution:</p><ul><li><p>PLT section we replaced with a <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/3/loader.c#L340">jumptable</a></p></li><li><p>GOT we replaced with <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/3/loader.c#L238-L248">assembly instructions</a></p></li></ul><p>Basically, we created a small stub with assembly code (our <code>jumptable</code>) to resolve the global address of our <code>my_puts</code> wrapper and jump to it.</p><p>The approach for aarch64 is the same. But the <code>jumptable</code> is very different as it consists of different assembly instructions.</p><p>The big difference here compared to the other parts is that we need to work with a 64-bit address for the GOT resolution. Our custom PLT or <code>jumptable</code> is placed close to the main code of <code>obj.c</code> and can operate with the relative addresses as before. For the GOT or referencing <code>my_puts</code> wrapper we’ll use different branch instructions — <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/BR--Branch-to-Register-"><code>br</code></a> or <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/BLR--Branch-with-Link-to-Register-"><code>blr</code></a>. These instructions branch to the register, where the aarch64 registers can hold 64-bit values.</p><p>We can check how it resolves with the native PLT/GOT in our loader assembly code:</p>
            <pre><code>$ objdump --disassemble --section=.text loader
...
1d2c:	97fffb45 	bl	a40 &lt;puts@plt&gt;
1d30:	f94017e0 	ldr	x0, [sp, #40]
1d34:	d63f0000 	blr	x0
...</code></pre>
            <p>The first instruction is <code>bl</code> jump to <code>puts@plt</code> stub. The next <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LDR--immediate---Load-Register--immediate--"><code>ldr</code></a> instruction tells us that some value was loaded into the register <code>x0</code> from the stack. Each function has its own <a href="https://en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers">stack frame</a> to hold the local variables. The last <code>blr</code> instruction makes a jump to the address stored in <code>x0</code> register. There is an agreement in the register naming: if the stored value is 64-bits then the register is called <code>x0-x30</code>; if only 32-bits are used then it’s called <code>w0-w30</code> (the value will be stored in the lower 32-bits and upper 32-bits will be zeroed).</p><p>We need to do something similar — place the absolute address of our <code>my_puts</code> wrapper in some register and call <code>br</code> on this register. We don’t need to store the link before branching, the call will be returned to <code>say_hello</code> from <code>obj.c</code>, which is why a plain <code>br</code> will be enough. Let’s check an assembly of simple C-function:</p><p>hello.c:</p>
            <pre><code>#include &lt;stdint.h&gt;

void say_hello(void)
{
    uint64_t reg = 0x555555550c14;
}</code></pre>
            
            <pre><code>$ gcc -c hello.c
$ objdump --disassemble --section=.text hello.o

hello.o:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000000000 &lt;say_hello&gt;:
   0:	d10043ff 	sub	sp, sp, #0x10
   4:	d2818280 	mov	x0, #0xc14                 	// #3092
   8:	f2aaaaa0 	movk	x0, #0x5555, lsl #16
   c:	f2caaaa0 	movk	x0, #0x5555, lsl #32
  10:	f90007e0 	str	x0, [sp, #8]
  14:	d503201f 	nop
  18:	910043ff 	add	sp, sp, #0x10
  1c:	d65f03c0 	ret</code></pre>
            <p>The number <code>0x555555550c14</code> is the address returned by <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/3/loader.c#L238"><code>lookup_ext_function</code></a>. We’ve printed it out to use as an example, but any <a href="https://www.kernel.org/doc/html/latest/arch/arm64/memory.html">48-bits</a> hex value can be used.</p><p>In our output we see that the value was split in three sections and written in <code>x0</code> register with three instructions: one <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOV--inverted-wide-immediate---Move--inverted-wide-immediate---an-alias-of-MOVN-"><code>mov</code></a> and two <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOVK--Move-wide-with-keep-?lang=en"><code>movk</code></a>. The documentation says that there are only 16 bits for the immediate value, but a shift can be applied (in our case left shift <code>lsl</code>).</p><p>However, we can’t use <code>x0</code> in our context. By <a href="https://developer.arm.com/documentation/den0024/a/The-ABI-for-ARM-64-bit-Architecture/Register-use-in-the-AArch64-Procedure-Call-Standard/Parameters-in-general-purpose-registers">convention</a> the registers <code>x0-x7</code> are caller-saved and used to pass function parameters between calls to other functions. Let’s use <code>x9</code> then.</p><p>We need to modify our loader. Firstly let’s change the jumptable structure.</p><p>loader.c:</p>
            <pre><code>...
struct ext_jump {
	uint32_t instr[4];
};
...</code></pre>
            <p>As we saw above, we need four instructions: <code>mov</code>, <code>movk</code>, <code>movk</code>, <code>br</code>. We don’t need a stack frame as we aren’t preserving any local variables. We just want to load the address into the register and branch to it. But we can’t write human-readable code</p><p>e.g. <code>mov  x0, #0xc14</code> into instructions, we need machine binary or hex representation, e.g. <code>d2818280</code>.</p><p>Let’s write a simple assembly code to get it:</p><p>hw.s:</p>
            <pre><code>.global _start

_start: mov     x9, #0xc14 
        movk    x9, #0x5555, lsl #16
        movk    x9, #0x5555, lsl #32
        br      x9</code></pre>
            
            <pre><code>$ as -o hw.o hw.s
$ objdump --disassemble --section=.text hw.o

hw.o:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000000000 &lt;_start&gt;:
   0:	d2818289 	mov	x9, #0xc14                 	// #3092
   4:	f2aaaaa9 	movk	x9, #0x5555, lsl #16
   8:	f2caaaa9 	movk	x9, #0x5555, lsl #32
   c:	d61f0120 	br	x9</code></pre>
            <p>Almost done! But there’s one more thing to consider. Even if the value <code>0x555555550c14</code> is a real <code>my_puts</code> wrapper address, it will be different on each run if <a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization">ASLR(Address space layout randomization)</a> is enabled. We need to patch these instructions to put the value which will be returned by <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2021-03-obj-file/3/loader.c#L238"><code>lookup_ext_function</code></a> on each run. We’ll split the obtained value in three parts, 16-bits each, and replace them in our <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOV--inverted-wide-immediate---Move--inverted-wide-immediate---an-alias-of-MOVN-"><code>mov</code></a> and <a href="https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/MOVK--Move-wide-with-keep-?lang=en"><code>movk</code></a> instructions according to the documentation, similar to what we did before for our second part.</p>
            <pre><code>if (symbols[symbol_idx].st_shndx == SHN_UNDEF) {
	static int curr_jmp_idx = 0;

	uint64_t addr = lookup_ext_function(strtab +  symbols[symbol_idx].st_name);
	uint32_t mov = 0b11010010100000000000000000001001 | ((addr &lt;&lt; 48) &gt;&gt; 43);
	uint32_t movk1 = 0b11110010101000000000000000001001 | (((addr &gt;&gt; 16) &lt;&lt; 48) &gt;&gt; 43);
	uint32_t movk2 = 0b11110010110000000000000000001001 | (((addr &gt;&gt; 32) &lt;&lt; 48) &gt;&gt; 43);
	jumptable[curr_jmp_idx].instr[0] = mov;         // mov  x9, #0x0c14
	jumptable[curr_jmp_idx].instr[1] = movk1;       // movk x9, #0x5555, lsl #16
	jumptable[curr_jmp_idx].instr[2] = movk2;       // movk x9, #0x5555, lsl #32
	jumptable[curr_jmp_idx].instr[3] = 0xd61f0120;  // br   x9

	symbol_address = (uint8_t *)(&amp;jumptable[curr_jmp_idx].instr[0]);
	curr_jmp_idx++;
} else {
	symbol_address = section_runtime_base(&amp;sections[symbols[symbol_idx].st_shndx]) + symbols[symbol_idx].st_value;
}
uint32_t val;
switch (type)
{
case R_AARCH64_CALL26:
	/* The mask separates opcode (6 bits) and the immediate value */
	uint32_t mask_bl = (0xffffffff &lt;&lt; 26);
	/* S+A-P, divided by 4 */
	val = (symbol_address + relocations[i].r_addend - patch_offset) &gt;&gt; 2;
	/* Concatenate opcode and value to get final instruction */
	*((uint32_t *)patch_offset) &amp;= mask_bl;
	val &amp;= ~mask_bl;
	*((uint32_t *)patch_offset) |= val;
	break;
...</code></pre>
            <p>In the code we took the address of the first instruction <code>&amp;jumptable[curr_jmp_idx].instr[0]</code> and wrote it in the <code>symbol_address</code>, further because the <code>type</code> is still <code>R_AARCH64_CALL26</code> it will be put into <code>bl</code> - jump to the relative address. Where our relative address is the first <code>mov</code> instruction. The whole <code>jumptable</code> code will be executed and finished with the <code>blr</code> instruction.</p><p>The final run:</p>
            <pre><code>$ gcc -o loader loader.c
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52
Executing get_hello...
get_hello() = Hello, world!
Executing get_var...
get_var() = 5
Executing set_var(42)...
Executing get_var again...
get_var() = 42
Executing say_hello...
my_puts executed
Hello, world!</code></pre>
            <p>The final code is <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/4/3">here</a>.</p>
    <div>
      <h2>Summary</h2>
      <a href="#summary">
        
      </a>
    </div>
    <p>There are several things we covered in this blog post. We gave a brief introduction on how the binary got executed on Linux and how all components are linked together. We saw a big difference between x86 and aarch64 assembly. We learned how we can hook into the code and change its behavior. But just as it was said in the first blog post of this series, the most important thing is to remember to always think about security first. Processing external inputs should always be done with great care. Bounds and integrity checks have been omitted for the purposes of keeping the examples short, so readers should be aware that the code is not production ready and is designed for educational purposes only.</p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <guid isPermaLink="false">6bGK0NoXnHBGOjKvJ60FRu</guid>
            <dc:creator>Oxana Kharitonova</dc:creator>
        </item>
        <item>
            <title><![CDATA[Live-patching security vulnerabilities inside the Linux kernel with eBPF Linux Security Module]]></title>
            <link>https://blog.cloudflare.com/live-patch-security-vulnerabilities-with-ebpf-lsm/</link>
            <pubDate>Wed, 29 Jun 2022 11:45:00 GMT</pubDate>
            <description><![CDATA[ Learn how to patch Linux security vulnerabilities without rebooting the hardware and how to tighten the security of your Linux operating system with eBPF Linux Security Module ]]></description>
            <content:encoded><![CDATA[ <p></p><p><a href="https://www.kernel.org/doc/html/latest/admin-guide/LSM/index.html">Linux Security Modules</a> (LSM) is a hook-based framework for implementing security policies and Mandatory Access Control in the Linux kernel. Until recently users looking to implement a security policy had just two options. Configure an existing LSM module such as AppArmor or SELinux, or write a custom kernel module.</p><p><a href="https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.7">Linux 5.7</a> introduced a third way: <a href="https://docs.kernel.org/bpf/prog_lsm.html">LSM extended Berkeley Packet Filters (eBPF)</a> (LSM BPF for short). LSM BPF allows developers to write granular policies without configuration or loading a kernel module. LSM BPF programs are verified on load, and then executed when an LSM hook is reached in a call path.</p>
    <div>
      <h2>Let’s solve a real-world problem</h2>
      <a href="#lets-solve-a-real-world-problem">
        
      </a>
    </div>
    <p>Modern operating systems provide facilities allowing "partitioning" of kernel resources. For example FreeBSD has "jails", Solaris has "zones". Linux is different - it provides a set of seemingly independent facilities each allowing isolation of a specific resource. These are called "namespaces" and have been growing in the kernel for years. They are the base of popular tools like Docker, lxc or firejail. Many of the namespaces are uncontroversial, like the UTS namespace which allows the host system to hide its hostname and time. Others are complex but straightforward - NET and NS (mount) namespaces are known to be hard to wrap your head around. Finally, there is this very special very curious USER namespace.</p><p>USER namespace is special, since it allows the owner to operate as "root" inside it. How it works is beyond the scope of this blog post, however, suffice to say it's a foundation to having tools like Docker to not operate as true root, and things like rootless containers.</p><p>Due to its nature, allowing unpriviledged users access to USER namespace always carried a great security risk.  One such risk is privilege escalation.</p><p>Privilege escalation is a <a href="https://www.cloudflare.com/learning/security/what-is-an-attack-surface/">common attack surface</a> for operating systems. One way users may gain privilege is by mapping their namespace to the root namespace via the unshare <a href="https://en.wikipedia.org/wiki/System_call">syscall</a> and specifying the <i>CLONE_NEWUSER</i> flag. This tells unshare to create a new user namespace with full permissions, and maps the new user and group ID to the previous namespace. You can use the <a href="https://man7.org/linux/man-pages/man1/unshare.1.html">unshare(1)</a> program to map root to our original namespace:</p>
            <pre><code>$ id
uid=1000(fred) gid=1000(fred) groups=1000(fred) …
$ unshare -rU
# id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
# cat /proc/self/uid_map
         0       1000          1</code></pre>
            <p>In most cases using unshare is harmless, and is intended to run with lower privileges. However, this syscall has been known to be used to <a href="https://nvd.nist.gov/vuln/detail/CVE-2022-0492">escalate privileges</a>.</p><p>Syscalls <i>clone</i> and <i>clone3</i> are worth looking into as they also have the ability to <i>CLONE_NEWUSER</i>. However, for this post we’re going to focus on unshare.</p><p>Debian solved this problem with this <a href="https://sources.debian.org/patches/linux/3.16.56-1+deb8u1/debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch/">"add sysctl to disallow unprivileged CLONE_NEWUSER by default"</a> patch, but it was not mainlined. Another similar patch <a href="https://lore.kernel.org/all/1453502345-30416-3-git-send-email-keescook@chromium.org/">"sysctl: allow CLONE_NEWUSER to be disabled"</a> attempted to mainline, and was met with push back. A critique is the <a href="https://lore.kernel.org/all/87poq5y0jw.fsf@x220.int.ebiederm.org/">inability to toggle this feature</a> for specific applications. In the article “<a href="https://lwn.net/Articles/673597/">Controlling access to user namespaces</a>” the author wrote: “... the current patches do not appear to have an easy path into the mainline.” And as we can see, the patches were ultimately not included in the vanilla kernel.</p>
    <div>
      <h2>Our solution - LSM BPF</h2>
      <a href="#our-solution-lsm-bpf">
        
      </a>
    </div>
    <p>Since upstreaming code that restricts USER namespace seem to not be an option, we decided to use LSM BPF to circumvent these issues. This requires no modifications to the kernel and allows us to express complex rules guarding the access.</p>
    <div>
      <h3>Track down an appropriate hook candidate</h3>
      <a href="#track-down-an-appropriate-hook-candidate">
        
      </a>
    </div>
    <p>First, let us track down the syscall we’re targeting. We can find the prototype in the <a href="https://elixir.bootlin.com/linux/v5.18/source/include/linux/syscalls.h#L608"><i>include/linux/syscalls.h</i></a> file. From there, it’s not as obvious to track down, but the line:</p>
            <pre><code>/* kernel/fork.c */</code></pre>
            <p>Gives us a clue of where to look next in <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/fork.c#L3201"><i>kernel/fork.c</i></a>. There a call to <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/fork.c#L3082"><i>ksys_unshare()</i></a> is made. Digging through that function, we find a call to <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/fork.c#L3129"><i>unshare_userns()</i></a>. This looks promising.</p><p>Up to this point, we’ve identified the syscall implementation, but the next question to ask is what hooks are available for us to use? Because we know from the <a href="https://man7.org/linux/man-pages/man2/unshare.2.html">man-pages</a> that unshare is used to mutate tasks, we look at the task-based hooks in <a href="https://elixir.bootlin.com/linux/v5.18/source/include/linux/lsm_hooks.h#L605"><i>include/linux/lsm_hooks.h</i></a>. Back in the function <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/user_namespace.c#L171"><i>unshare_userns()</i></a> we saw a call to <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/cred.c#L252"><i>prepare_creds()</i></a>. This looks very familiar to the <a href="https://elixir.bootlin.com/linux/v5.18/source/include/linux/lsm_hooks.h#L624"><i>cred_prepare</i></a> hook. To verify we have our match via <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/cred.c#L291"><i>prepare_creds()</i></a>, we see a call to the security hook <a href="https://elixir.bootlin.com/linux/v5.18/source/security/security.c#L1706"><i>security_prepare_creds()</i></a> which ultimately calls the hook:</p>
            <pre><code>…
rc = call_int_hook(cred_prepare, 0, new, old, gfp);
…</code></pre>
            <p>Without going much further down this rabbithole, we know this is a good hook to use because <i>prepare_creds()</i> is called right before <i>create_user_ns()</i> in <a href="https://elixir.bootlin.com/linux/v5.18/source/kernel/user_namespace.c#L181"><i>unshare_userns()</i></a> which is the operation we’re trying to block.</p>
    <div>
      <h3>LSM BPF solution</h3>
      <a href="#lsm-bpf-solution">
        
      </a>
    </div>
    <p>We’re going to compile with the <a href="https://nakryiko.com/posts/bpf-core-reference-guide/#defining-own-co-re-relocatable-type-definitions">eBPF compile once-run everywhere (CO-RE)</a> approach. This allows us to compile on one architecture and load on another. But we’re going to target x86_64 specifically. LSM BPF for ARM64 is still in development, and the following code will not run on that architecture. Watch the <a href="https://lore.kernel.org/bpf/">BPF mailing list</a> to follow the progress.</p><p>This solution was tested on kernel versions &gt;= 5.15 configured with the following:</p>
            <pre><code>BPF_EVENTS
BPF_JIT
BPF_JIT_ALWAYS_ON
BPF_LSM
BPF_SYSCALL
BPF_UNPRIV_DEFAULT_OFF
DEBUG_INFO_BTF
DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
DYNAMIC_FTRACE
FUNCTION_TRACER
HAVE_DYNAMIC_FTRACE</code></pre>
            <p>A boot option <code>lsm=bpf</code> may be necessary if <code>CONFIG_LSM</code> does not contain “bpf” in the list.</p><p>Let’s start with our preamble:</p><p><i>deny_unshare.bpf.c</i>:</p>
            <pre><code>#include &lt;linux/bpf.h&gt;
#include &lt;linux/capability.h&gt;
#include &lt;linux/errno.h&gt;
#include &lt;linux/sched.h&gt;
#include &lt;linux/types.h&gt;

#include &lt;bpf/bpf_tracing.h&gt;
#include &lt;bpf/bpf_helpers.h&gt;
#include &lt;bpf/bpf_core_read.h&gt;

#define X86_64_UNSHARE_SYSCALL 272
#define UNSHARE_SYSCALL X86_64_UNSHARE_SYSCALL</code></pre>
            <p>Next we set up our necessary structures for CO-RE relocation in the following way:</p><p><i>deny_unshare.bpf.c</i>:</p>
            <pre><code>…

typedef unsigned int gfp_t;

struct pt_regs {
	long unsigned int di;
	long unsigned int orig_ax;
} __attribute__((preserve_access_index));

typedef struct kernel_cap_struct {
	__u32 cap[_LINUX_CAPABILITY_U32S_3];
} __attribute__((preserve_access_index)) kernel_cap_t;

struct cred {
	kernel_cap_t cap_effective;
} __attribute__((preserve_access_index));

struct task_struct {
    unsigned int flags;
    const struct cred *cred;
} __attribute__((preserve_access_index));

char LICENSE[] SEC("license") = "GPL";

…</code></pre>
            <p>We don’t need to fully-flesh out the structs; we just need the absolute minimum information a program needs to function. CO-RE will do whatever is necessary to perform the relocations for your kernel. This makes writing the LSM BPF programs easy!</p><p><i>deny_unshare.bpf.c</i>:</p>
            <pre><code>SEC("lsm/cred_prepare")
int BPF_PROG(handle_cred_prepare, struct cred *new, const struct cred *old,
             gfp_t gfp, int ret)
{
    struct pt_regs *regs;
    struct task_struct *task;
    kernel_cap_t caps;
    int syscall;
    unsigned long flags;

    // If previous hooks already denied, go ahead and deny this one
    if (ret) {
        return ret;
    }

    task = bpf_get_current_task_btf();
    regs = (struct pt_regs *) bpf_task_pt_regs(task);
    // In x86_64 orig_ax has the syscall interrupt stored here
    syscall = regs-&gt;orig_ax;
    caps = task-&gt;cred-&gt;cap_effective;

    // Only process UNSHARE syscall, ignore all others
    if (syscall != UNSHARE_SYSCALL) {
        return 0;
    }

    // PT_REGS_PARM1_CORE pulls the first parameter passed into the unshare syscall
    flags = PT_REGS_PARM1_CORE(regs);

    // Ignore any unshare that does not have CLONE_NEWUSER
    if (!(flags &amp; CLONE_NEWUSER)) {
        return 0;
    }

    // Allow tasks with CAP_SYS_ADMIN to unshare (already root)
    if (caps.cap[CAP_TO_INDEX(CAP_SYS_ADMIN)] &amp; CAP_TO_MASK(CAP_SYS_ADMIN)) {
        return 0;
    }

    return -EPERM;
}</code></pre>
            <p>Creating the program is the first step, the second is loading and attaching the program to our desired hook. There are several ways to do this: <a href="https://github.com/cilium/ebpf">Cilium ebpf</a> project, <a href="https://github.com/libbpf/libbpf-rs">Rust bindings</a>, and several others on the <a href="https://ebpf.io/projects/">ebpf.io</a> project landscape page. We’re going to use native libbpf.</p><p><i>deny_unshare.c</i>:</p>
            <pre><code>#include &lt;bpf/libbpf.h&gt;
#include &lt;unistd.h&gt;
#include "deny_unshare.skel.h"

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
    return vfprintf(stderr, format, args);
}

int main(int argc, char *argv[])
{
    struct deny_unshare_bpf *skel;
    int err;

    libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
    libbpf_set_print(libbpf_print_fn);

    // Loads and verifies the BPF program
    skel = deny_unshare_bpf__open_and_load();
    if (!skel) {
        fprintf(stderr, "failed to load and verify BPF skeleton\n");
        goto cleanup;
    }

    // Attaches the loaded BPF program to the LSM hook
    err = deny_unshare_bpf__attach(skel);
    if (err) {
        fprintf(stderr, "failed to attach BPF skeleton\n");
        goto cleanup;
    }

    printf("LSM loaded! ctrl+c to exit.\n");

    // The BPF link is not pinned, therefore exiting will remove program
    for (;;) {
        fprintf(stderr, ".");
        sleep(1);
    }

cleanup:
    deny_unshare_bpf__destroy(skel);
    return err;
}</code></pre>
            <p>Lastly, to compile, we use the following Makefile:</p><p><i>Makefile</i>:</p>
            <pre><code>CLANG ?= clang-13
LLVM_STRIP ?= llvm-strip-13
ARCH := x86
INCLUDES := -I/usr/include -I/usr/include/x86_64-linux-gnu
LIBS_DIR := -L/usr/lib/lib64 -L/usr/lib/x86_64-linux-gnu
LIBS := -lbpf -lelf

.PHONY: all clean run

all: deny_unshare.skel.h deny_unshare.bpf.o deny_unshare

run: all
	sudo ./deny_unshare

clean:
	rm -f *.o
	rm -f deny_unshare.skel.h

#
# BPF is kernel code. We need to pass -D__KERNEL__ to refer to fields present
# in the kernel version of pt_regs struct. uAPI version of pt_regs (from ptrace)
# has different field naming.
# See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fd56e0058412fb542db0e9556f425747cf3f8366
#
deny_unshare.bpf.o: deny_unshare.bpf.c
	$(CLANG) -g -O2 -Wall -target bpf -D__KERNEL__ -D__TARGET_ARCH_$(ARCH) $(INCLUDES) -c $&lt; -o $@
	$(LLVM_STRIP) -g $@ # Removes debug information

deny_unshare.skel.h: deny_unshare.bpf.o
	sudo bpftool gen skeleton $&lt; &gt; $@

deny_unshare: deny_unshare.c deny_unshare.skel.h
	$(CC) -g -Wall -c $&lt; -o $@.o
	$(CC) -g -o $@ $(LIBS_DIR) $@.o $(LIBS)

.DELETE_ON_ERROR:</code></pre>
            
    <div>
      <h3>Result</h3>
      <a href="#result">
        
      </a>
    </div>
    <p>In a new terminal window run:</p>
            <pre><code>$ make run
…
LSM loaded! ctrl+c to exit.</code></pre>
            <p>In another terminal window, we’re successfully blocked!</p>
            <pre><code>$ unshare -rU
unshare: unshare failed: Cannot allocate memory
$ id
uid=1000(fred) gid=1000(fred) groups=1000(fred) …</code></pre>
            <p>The policy has an additional feature to always allow privilege pass through:</p>
            <pre><code>$ sudo unshare -rU
# id
uid=0(root) gid=0(root) groups=0(root)</code></pre>
            <p>In the unprivileged case the syscall early aborts. What is the performance impact in the privileged case?</p>
    <div>
      <h3>Measure performance</h3>
      <a href="#measure-performance">
        
      </a>
    </div>
    <p>We’re going to use a one-line unshare that’ll map the user namespace, and execute a command within for the measurements:</p>
            <pre><code>$ unshare -frU --kill-child -- bash -c "exit 0"</code></pre>
            <p>With a resolution of CPU cycles for syscall unshare enter/exit, we’ll measure the following as root user:</p><ol><li><p>Command ran without the policy</p></li><li><p>Command run with the policy</p></li></ol><p>We’ll record the measurements with <a href="https://docs.kernel.org/trace/ftrace.html">ftrace</a>:</p>
            <pre><code>$ sudo su
# cd /sys/kernel/debug/tracing
# echo 1 &gt; events/syscalls/sys_enter_unshare/enable ; echo 1 &gt; events/syscalls/sys_exit_unshare/enable</code></pre>
            <p>At this point, we’re enabling tracing for the syscall enter and exit for unshare specifically. Now we set the time-resolution of our enter/exit calls to count CPU cycles:</p>
            <pre><code># echo 'x86-tsc' &gt; trace_clock </code></pre>
            <p>Next we begin our measurements:</p>
            <pre><code># unshare -frU --kill-child -- bash -c "exit 0" &amp;
[1] 92014</code></pre>
            <p>Run the policy in a new terminal window, and then run our next syscall:</p>
            <pre><code># unshare -frU --kill-child -- bash -c "exit 0" &amp;
[2] 92019</code></pre>
            <p>Now we have our two calls for comparison:</p>
            <pre><code># cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 4/4   #P:8
#
#                                _-----=&gt; irqs-off
#                               / _----=&gt; need-resched
#                              | / _---=&gt; hardirq/softirq
#                              || / _--=&gt; preempt-depth
#                              ||| / _-=&gt; migrate-disable
#                              |||| /     delay
#           TASK-PID     CPU#  |||||  TIMESTAMP  FUNCTION
#              | |         |   |||||     |         |
         unshare-92014   [002] ..... 762950852559027: sys_unshare(unshare_flags: 10000000)
         unshare-92014   [002] ..... 762950852622321: sys_unshare -&gt; 0x0
         unshare-92019   [007] ..... 762975980681895: sys_unshare(unshare_flags: 10000000)
         unshare-92019   [007] ..... 762975980752033: sys_unshare -&gt; 0x0
</code></pre>
            <p>unshare-92014 used 63294 cycles.unshare-92019 used 70138 cycles.</p><p>We have a 6,844 (~10%) cycle penalty between the two measurements. Not bad!</p><p>These numbers are for a single syscall, and add up the more frequently the code is called. Unshare is typically called at task creation, and not repeatedly during normal execution of a program. Careful consideration and measurement is needed for your use case.</p>
    <div>
      <h2>Outro</h2>
      <a href="#outro">
        
      </a>
    </div>
    <p>We learned a bit about what LSM BPF is, how unshare is used to map a user to root, and how to solve a real-world problem by implementing a solution in eBPF. Tracking down the appropriate hook is not an easy task, and requires a bit of playing and a lot of kernel code. Fortunately, that’s the hard part. Because a policy is written in C, we can granularly tweak the policy to our problem. This means one may extend this policy with an allow-list to allow certain programs or users to continue to use an unprivileged unshare. Finally, we looked at the performance impact of this program, and saw the overhead is worth blocking the attack vector.</p><p>“Cannot allocate memory” is not a clear error message for denying permissions. We proposed a <a href="https://lore.kernel.org/all/20220608150942.776446-1-fred@cloudflare.com/">patch</a> to propagate error codes from the <i>cred_prepare</i> hook up the call stack. Ultimately we came to the conclusion that a new hook is better suited to this problem. Stay tuned!</p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">2AGA68zpZ0kGK4kfyvQ5Fa</guid>
            <dc:creator>Frederick Lawler</dc:creator>
        </item>
        <item>
            <title><![CDATA[How to execute an object file: Part 3]]></title>
            <link>https://blog.cloudflare.com/how-to-execute-an-object-file-part-3/</link>
            <pubDate>Fri, 10 Sep 2021 12:58:20 GMT</pubDate>
            <description><![CDATA[ Continue learning how to import and execute code from an object file. In this part we will handle external library dependencies. ]]></description>
            <content:encoded><![CDATA[ <p></p>
    <div>
      <h2>Dealing with external libraries</h2>
      <a href="#dealing-with-external-libraries">
        
      </a>
    </div>
    <p>In the <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-2/">part 2 of our series</a> we learned how to process relocations in object files in order to properly wire up internal dependencies in the code. In this post we will look into what happens if the code has external dependencies — that is, it tries to call functions from external libraries. As before, we will be building upon <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/2">the code from part 2</a>. Let's add another function to our toy object file:</p><p><i>obj.c</i>:</p>
            <pre><code>#include &lt;stdio.h&gt;
 
...
 
void say_hello(void)
{
    puts("Hello, world!");
}</code></pre>
            <p>In the above scenario our <code>say_hello</code> function now depends on the <code>puts</code> <a href="https://man7.org/linux/man-pages/man3/puts.3.html">function from the C standard library</a>. To try it out we also need to modify our <code>loader</code> to import the new function and execute it:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void execute_funcs(void)
{
    /* pointers to imported functions */
    int (*add5)(int);
    int (*add10)(int);
    const char *(*get_hello)(void);
    int (*get_var)(void);
    void (*set_var)(int num);
    void (*say_hello)(void);
 
...
 
    say_hello = lookup_function("say_hello");
    if (!say_hello) {
        fputs("Failed to find say_hello function\n", stderr);
        exit(ENOENT);
    }
 
    puts("Executing say_hello...");
    say_hello();
}
...</code></pre>
            <p>Let's run it:</p>
            <pre><code>$ gcc -c obj.c
$ gcc -o loader loader.c
$ ./loader
No runtime base address for section</code></pre>
            <p>Seems something went wrong when the <code>loader</code> tried to process relocations, so let's check the relocations table:</p>
            <pre><code>$ readelf --relocs obj.o
 
Relocation section '.rela.text' at offset 0x3c8 contains 7 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000a00000004 R_X86_64_PLT32    0000000000000000 add5 - 4
00000000002d  000a00000004 R_X86_64_PLT32    0000000000000000 add5 - 4
00000000003a  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4
000000000046  000300000002 R_X86_64_PC32     0000000000000000 .data - 4
000000000058  000300000002 R_X86_64_PC32     0000000000000000 .data - 4
000000000066  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4
00000000006b  001100000004 R_X86_64_PLT32    0000000000000000 puts - 4
...</code></pre>
            <p>The compiler generated a relocation for the <code>puts</code> invocation. The relocation type is <code>R_X86_64_PLT32</code> and our <code>loader</code> already knows how to process these, so the problem is elsewhere. The above entry shows that the relocation references 17th entry (<code>0x11</code> in hex) in the symbol table, so let's check that:</p>
            <pre><code>$ readelf --symbols obj.o
 
Symbol table '.symtab' contains 18 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS obj.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    3 var
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
    10: 0000000000000000    15 FUNC    GLOBAL DEFAULT    1 add5
    11: 000000000000000f    36 FUNC    GLOBAL DEFAULT    1 add10
    12: 0000000000000033    13 FUNC    GLOBAL DEFAULT    1 get_hello
    13: 0000000000000040    12 FUNC    GLOBAL DEFAULT    1 get_var
    14: 000000000000004c    19 FUNC    GLOBAL DEFAULT    1 set_var
    15: 000000000000005f    19 FUNC    GLOBAL DEFAULT    1 say_hello
    16: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    17: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts</code></pre>
            <p>Oh! The section index for the <code>puts</code> function is <code>UND</code> (essentially <code>0</code> in the code), which makes total sense: unlike previous symbols, <code>puts</code> is an external dependency, and it is not implemented in our <code>obj.o</code> file. Therefore, it can't be a part of any section within <code>obj.o</code>.So how do we resolve this relocation? We need to somehow point the code to jump to a <code>puts</code> implementation. Our <code>loader</code> actually already has access to the C library <code>puts</code> function (because it is written in C and we've used <code>puts</code> in the <code>loader</code> code itself already), but technically it doesn't have to be the C library <code>puts</code>, just some <code>puts</code> implementation. For completeness, let's implement our own custom <code>puts</code> function in the <code>loader</code>, which is just a decorator around the C library <code>puts</code>:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
/* external dependencies for obj.o */
static int my_puts(const char *s)
{
    puts("my_puts executed");
    return puts(s);
}
...</code></pre>
            <p>Now that we have a <code>puts</code> implementation (and thus its runtime address) we should just write logic in the <code>loader</code> to resolve the relocation by instructing the code to jump to the correct function. However, there is one complication: in <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-2/">part 2 of our series</a>, when we processed relocations for constants and global variables, we learned we're mostly dealing with 32-bit relative relocations and that the code or data we're referencing needs to be no more than 2147483647 (<code>0x7fffffff</code> in hex) bytes away from the relocation itself. <code>R_X86_64_PLT32</code> is also a 32-bit relative relocation, so it has the same requirements, but unfortunately we can't reuse the trick from <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-2/">part 2</a> as our <code>my_puts</code> function is part of the <code>loader</code> itself and we don't have control over where in the address space the operating system places the <code>loader</code> code.</p><p>Luckily, we don't have to come up with any new solutions and can just borrow the approach used in shared libraries.</p>
    <div>
      <h3>Exploring PLT/GOT</h3>
      <a href="#exploring-plt-got">
        
      </a>
    </div>
    <p>Real world ELF executables and shared libraries have the same problem: often executables have dependencies on shared libraries and shared libraries have dependencies on other shared libraries. And all of the different pieces of a complete runtime program may be mapped to random ranges in the process address space. When a shared library or an ELF executable is linked together, the linker enumerates all the external references and creates two or more additional sections (for a refresher on ELF sections check out the <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-1/">part 1 of our series</a>) in the ELF file. The two mandatory ones are <a href="https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_zSeries/x2251.html">the Procedure Linkage Table (PLT) and the Global Offset Table (GOT)</a>.</p><p>We will not deep-dive into specifics of the standard PLT/GOT implementation as there are many other great resources online, but in a nutshell PLT/GOT is just a jumptable for external code. At the linking stage the linker resolves all external 32-bit relative relocations with respect to a locally generated PLT/GOT table. It can do that, because this table would become part of the final ELF file itself, so it will be "close" to the main code, when the file is mapped into memory at runtime. Later, at runtime <a href="https://man7.org/linux/man-pages/man8/ld.so.8.html">the dynamic loader</a> populates PLT/GOT tables for every loaded ELF file (both the executable and the shared libraries) with the runtime addresses of all the dependencies. Eventually, when the program code calls some external library function, the CPU "jumps" through the local PLT/GOT table to the final code:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7xHrWlui04cqRxeurzvRpd/2d4b41f80468fde55541c19933d924c1/image2-5.png" />
            
            </figure><p>Why do we need two ELF sections to implement one jumptable you may ask? Well, because real world PLT/GOT is a bit more complex than described above. Turns out resolving all external references at runtime may significantly slow down program startup time, so symbol resolution is implemented via a "lazy approach": a reference is resolved by <a href="https://man7.org/linux/man-pages/man8/ld.so.8.html">the dynamic loader</a> only when the code actually tries to call a particular function. If the main application code never calls a library function, that reference will never be resolved.</p>
    <div>
      <h3>Implementing a simplified PLT/GOT</h3>
      <a href="#implementing-a-simplified-plt-got">
        
      </a>
    </div>
    <p>For learning and demonstrative purposes though we will not be reimplementing a full-blown PLT/GOT with lazy resolution, but a simple jumptable, which resolves external references when the object file is loaded and parsed. First of all we need to know the size of the table: for ELF executables and shared libraries the linker will count the external references at link stage and create appropriately sized PLT and GOT sections. Because we are dealing with raw object files we would have to do another pass over the <code>.rela.text</code> section and count all the relocations, which point to an entry in the symbol table with undefined section index (or <code>0</code> in code). Let's add a function for this and store the number of external references in a global variable:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
/* number of external symbols in the symbol table */
static int num_ext_symbols = 0;
...
static void count_external_symbols(void)
{
    const Elf64_Shdr *rela_text_hdr = lookup_section(".rela.text");
    if (!rela_text_hdr) {
        fputs("Failed to find .rela.text\n", stderr);
        exit(ENOEXEC);
    }
 
    int num_relocations = rela_text_hdr-&gt;sh_size / rela_text_hdr-&gt;sh_entsize;
    const Elf64_Rela *relocations = (Elf64_Rela *)(obj.base + rela_text_hdr-&gt;sh_offset);
 
    for (int i = 0; i &lt; num_relocations; i++) {
        int symbol_idx = ELF64_R_SYM(relocations[i].r_info);
 
        /* if there is no section associated with a symbol, it is probably
         * an external reference */
        if (symbols[symbol_idx].st_shndx == SHN_UNDEF)
            num_ext_symbols++;
    }
}
...</code></pre>
            <p>This function is very similar to our <code>do_text_relocations</code> function. Only instead of actually performing relocations it just counts the number of external symbol references.</p><p>Next we need to decide the actual size in bytes for our jumptable. <code>num_ext_symbols</code> has the number of external symbol references in the object file, but how many bytes per symbol to allocate? To figure this out we need to design our jumptable format. As we established above, in its simple form our jumptable should be just a collection of unconditional CPU jump instructions — one for each external symbol. However, unfortunately modern x64 CPU architecture <a href="https://www.felixcloutier.com/x86/jmp">does not provide a jump instruction</a>, where an address pointer can be a direct operand. Instead, the jump address needs to be stored in memory somewhere "close" — that is within 32-bit offset — and the offset is the actual operand. So, for each external symbol we need to store the jump address (64 bits or 8 bytes on a 64-bit CPU system) and the actual jump instruction with an offset operand (<a href="https://www.felixcloutier.com/x86/jmp">6 bytes for x64 architecture</a>). We can represent an entry in our jumptable with the following C structure:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
struct ext_jump {
    /* address to jump to */
    uint8_t *addr;
    /* unconditional x64 JMP instruction */
    /* should always be {0xff, 0x25, 0xf2, 0xff, 0xff, 0xff} */
    /* so it would jump to an address stored at addr above */
    uint8_t instr[6];
};
 
struct ext_jump *jumptable;
...</code></pre>
            <p>We've also added a global variable to store the base address of the jumptable, which will be allocated later. Notice that with the above approach the actual jump instruction will always be constant for every external symbol. Since we allocate a dedicated entry for each external symbol with this structure, the <code>addr</code> member would always be at the same offset from the end of the jump instruction in <code>instr</code>: <code>-14</code> bytes or <code>0xfffffff2</code> in hex for a 32-bit operand. So <code>instr</code> will always be <code>{0xff, 0x25, 0xf2, 0xff, 0xff, 0xff}</code>: <code>0xff</code> and <code>0x25</code> is the encoding of the x64 jump instruction and its modifier and <code>0xfffffff2</code> is the operand offset in little-endian format.</p><p>Now that we have defined the entry format for our jumptable, we can allocate and populate it when parsing the object file. First of all, let's not forget to call our new <code>count_external_symbols</code> function from the <code>parse_obj</code> to populate <code>num_ext_symbols</code> (it has to be done before we allocate the jumptable):</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void parse_obj(void)
{
...
 
    count_external_symbols();
 
    /* allocate memory for `.text`, `.data` and `.rodata` copies rounding up each section to whole pages */
    text_runtime_base = mmap(NULL, page_align(text_hdr-&gt;sh_size)...
...
}</code></pre>
            <p>Next we need to allocate memory for the jumptable and store the pointer in the <code>jumptable</code> global variable for later use. Just a reminder that in order to resolve 32-bit relocations from the <code>.text</code> section to this table, it has to be "close" in memory to the main code. So we need to allocate it in the same <code>mmap</code> call as the rest of the object sections. Since we defined the table's entry format in <code>struct ext_jump</code> and have <code>num_ext_symbols</code>, the size of the table would simply be <code>sizeof(struct ext_jump) * num_ext_symbols</code>:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void parse_obj(void)
{
...
 
    count_external_symbols();
 
    /* allocate memory for `.text`, `.data` and `.rodata` copies and the jumptable for external symbols, rounding up each section to whole pages */
    text_runtime_base = mmap(NULL, page_align(text_hdr-&gt;sh_size) + \
                                   page_align(data_hdr-&gt;sh_size) + \
                                   page_align(rodata_hdr-&gt;sh_size) + \
                                   page_align(sizeof(struct ext_jump) * num_ext_symbols),
                                   PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (text_runtime_base == MAP_FAILED) {
        perror("Failed to allocate memory");
        exit(errno);
    }
 
...
    rodata_runtime_base = data_runtime_base + page_align(data_hdr-&gt;sh_size);
    /* jumptable will come after .rodata */
    jumptable = (struct ext_jump *)(rodata_runtime_base + page_align(rodata_hdr-&gt;sh_size));
 
...
}
...</code></pre>
            <p>Finally, because the CPU will actually be executing the jump instructions from our <code>instr</code> fields from the jumptable, we need to mark this memory readonly and executable (after <code>do_text_relocations</code> earlier in this function has completed):</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void parse_obj(void)
{
...
 
    do_text_relocations();
 
...
 
    /* make the jumptable readonly and executable */
    if (mprotect(jumptable, page_align(sizeof(struct ext_jump) * num_ext_symbols), PROT_READ | PROT_EXEC)) {
        perror("Failed to make the jumptable executable");
        exit(errno);
    }
}
...</code></pre>
            <p>At this stage we have our jumptable allocated and usable — all is left to do is to populate it properly. We’ll do this by improving the <code>do_text_relocations</code> implementation to handle the case of external symbols. The <code>No runtime base address for section</code> error from the beginning of this post is actually caused by this line in <code>do_text_relocations</code>:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void do_text_relocations(void)
{
...
    for (int i = 0; i &lt; num_relocations; i++) {
...
        /* symbol, with respect to which the relocation is performed */
        uint8_t *symbol_address = = section_runtime_base(&amp;sections[symbols[symbol_idx].st_shndx]) + symbols[symbol_idx].st_value;
...
}
...</code></pre>
            <p>Currently we try to determine the runtime symbol address for the relocation by looking up the symbol's section runtime address and adding the symbol's offset. But we have established above that external symbols do not have an associated section, so their handling needs to be a special case. Let's update the implementation to reflect this:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void do_text_relocations(void)
{
...
    for (int i = 0; i &lt; num_relocations; i++) {
...
        /* symbol, with respect to which the relocation is performed */
        uint8_t *symbol_address;
        
        /* if this is an external symbol */
        if (symbols[symbol_idx].st_shndx == SHN_UNDEF) {
            static int curr_jmp_idx = 0;
 
            /* get external symbol/function address by name */
            jumptable[curr_jmp_idx].addr = lookup_ext_function(strtab +  symbols[symbol_idx].st_name);
 
            /* x64 unconditional JMP with address stored at -14 bytes offset */
            /* will use the address stored in addr above */
            jumptable[curr_jmp_idx].instr[0] = 0xff;
            jumptable[curr_jmp_idx].instr[1] = 0x25;
            jumptable[curr_jmp_idx].instr[2] = 0xf2;
            jumptable[curr_jmp_idx].instr[3] = 0xff;
            jumptable[curr_jmp_idx].instr[4] = 0xff;
            jumptable[curr_jmp_idx].instr[5] = 0xff;
 
            /* resolve the relocation with respect to this unconditional JMP */
            symbol_address = (uint8_t *)(&amp;jumptable[curr_jmp_idx].instr);
 
            curr_jmp_idx++;
        } else {
            symbol_address = section_runtime_base(&amp;sections[symbols[symbol_idx].st_shndx]) + symbols[symbol_idx].st_value;
        }
...
}
...</code></pre>
            <p>If a relocation symbol does not have an associated section, we consider it external and call a helper function to lookup the symbol's runtime address by its name. We store this address in the next available jumptable entry, populate the x64 jump instruction with our fixed operand and store the address of the instruction in the <code>symbol_address</code> variable. Later, the existing code in <code>do_text_relocations</code> will resolve the <code>.text</code> relocation with respect to the address in <code>symbol_address</code> in the same way it does for local symbols in <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-2/">part 2 of our series</a>.</p><p>The only missing bit here now is the implementation of the newly introduced <code>lookup_ext_function</code> helper. Real world loaders may have complicated logic on how to find and resolve symbols in memory at runtime. But for the purposes of this article we'll provide a simple naive implementation, which can only resolve the <code>puts</code> function:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void *lookup_ext_function(const char *name)
{
    size_t name_len = strlen(name);
 
    if (name_len == strlen("puts") &amp;&amp; !strcmp(name, "puts"))
        return my_puts;
 
    fprintf(stderr, "No address for function %s\n", name);
    exit(ENOENT);
}
...</code></pre>
            <p>Notice though that because we control the <code>loader</code> logic we are free to implement resolution as we please. In the above case we actually "divert" the object file to use our own "custom" <code>my_puts</code> function instead of the C library one. Let's recompile the <code>loader</code> and see if it works:</p>
            <pre><code>$ gcc -o loader loader.c
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52
Executing get_hello...
get_hello() = Hello, world!
Executing get_var...
get_var() = 5
Executing set_var(42)...
Executing get_var again...
get_var() = 42
Executing say_hello...
my_puts executed
Hello, world!</code></pre>
            <p>Hooray! We not only fixed our <code>loader</code> to handle external references in object files — we have also learned how to "hook" any such external function call and divert the code to a custom implementation, which might be useful in some cases, like malware research.</p><p>As in the previous posts, the complete source code from this post is <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/3">available on GitHub</a>.</p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <guid isPermaLink="false">3zPmdVaAOcTsffVeGWzsCW</guid>
            <dc:creator>Ignat Korchagin</dc:creator>
        </item>
        <item>
            <title><![CDATA[Branch predictor: How many "if"s are too many? Including x86 and M1 benchmarks!]]></title>
            <link>https://blog.cloudflare.com/branch-predictor/</link>
            <pubDate>Thu, 06 May 2021 13:00:00 GMT</pubDate>
            <description><![CDATA[ Is it ok to have if clauses that will basically never be run? Surely, there must be some performance cost to that... ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Some time ago I was looking at a hot section in our code and I saw this:</p>
            <pre><code>
	if (debug) {
    	  log("...");
    }
    </code></pre>
            <p>This got me thinking. This code is in a performance critical loop and it looks like a waste - we never run with the "debug" flag enabled<sup>[</sup><a href="#footnotes"><sup>1</sup></a><sup>].</sup> Is it ok to have <code>if</code> clauses that will basically never be run? Surely, there must be some performance cost to that...</p>
    <div>
      <h3>Just how bad is peppering the code with avoidable <code>if</code> statements?</h3>
      <a href="#just-how-bad-is-peppering-the-code-with-avoidable-if-statements">
        
      </a>
    </div>
    <p>Back in the days the general rule was: a fully predictable branch has close to zero CPU cost.</p><p>To what extent is this true? If one branch is fine, then how about ten? A hundred? A thousand? When does adding one more <code>if</code> statement become a bad idea?</p><p>At some point the negligible cost of simple branch instructions surely adds up to a significant amount. As another example, a colleague of mine found this snippet in our production code:</p>
            <pre><code>
const char *getCountry(int cc) {
		if(cc == 1) return "A1";
        if(cc == 2) return "A2";
        if(cc == 3) return "O1";
        if(cc == 4) return "AD";
        if(cc == 5) return "AE";
        if(cc == 6) return "AF";
        if(cc == 7) return "AG";
        if(cc == 8) return "AI";
        ...
        if(cc == 252) return "YT";
        if(cc == 253) return "ZA";
        if(cc == 254) return "ZM";
        if(cc == 255) return "ZW";
        if(cc == 256) return "XK";
        if(cc == 257) return "T1";
        return "UNKNOWN";
}
        </code></pre>
            <p>Obviously, this code could be improved<sup>[</sup><a href="#footnotes"><sup>2</sup></a><sup>]</sup>. But when I thought about it more: <i>should</i> it be improved? Is there an actual performance hit of a code that consists of a series of simple branches?</p>
    <div>
      <h3>Understanding the cost of jump</h3>
      <a href="#understanding-the-cost-of-jump">
        
      </a>
    </div>
    <p>We must start our journey with a bit of theory. We want to figure out if the CPU cost of a branch increases as we add more of them. As it turns out, assessing the cost of a branch is not trivial. On modern processors it takes between one and twenty CPU cycles. There are at least four categories of control flow instructions<sup>[</sup><a href="#footnotes"><sup>3</sup></a><sup>]</sup>: unconditional branch (jmp on x86), call/return, conditional branch (e.g. je on x86) taken and conditional branch not taken. The taken branches are especially problematic: without special care they are inherently costly - we'll explain this in the following section. To bring down the cost, modern CPU's try to predict the future and figure out the branch <b>target</b> before the branch is actually fully executed! This is done in a special part of the processor called the branch predictor unit (BPU).</p><p>The branch predictor attempts to figure out a destination of a branching instruction very early and with very little context. This magic happens <b>before</b> the "decoder" pipeline stage and the predictor has very limited data available. It only has some past history and the address of the current instruction. If you think about it - this is super powerful. Given only current instruction pointer it can assess, with very high confidence, where the target of the jump will be.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1K3IOo5qkOOP0hhRtwu10U/e9997acf855e96044f2684e1adae87b0/pasted-image-0-1.png" />
            
            </figure><p>Source: <a href="https://en.wikipedia.org/wiki/Branch_predictor">https://en.wikipedia.org/wiki/Branch_predictor</a></p><p>The BPU maintains a couple of data structures, but today we'll focus on Branch Target Buffer (BTB). It's a place where the BPU remembers the target instruction pointer of previously taken branches. The whole mechanism is much more complex, take a look a the <a href="http://www.ece.uah.edu/~milenka/docs/VladimirUzelac.thesis.pdf">Vladimir Uzelac's Master thesis</a> for details about branch prediction on CPU's from 2008 era:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FO1GCWdkQYR5I90qGopuH/9f51e10ca53eafd001f2238896103327/pasted-image-0--1-.png" />
            
            </figure><p>For the scope of this article we'll simplify and focus on the BTB only. We'll try to show how large it is and how it behaves under different conditions.</p>
    <div>
      <h3>Why is branch prediction needed?</h3>
      <a href="#why-is-branch-prediction-needed">
        
      </a>
    </div>
    <p>But first, why is branch prediction used at all? In order to get the best performance, the CPU pipeline must feed a constant flow of instructions. Consider what happens to the multi-stage CPU pipeline on a branch instruction. To illustrate let's consider the following ARM program:</p>
            <pre><code>
	BR label_a;
    X1
    ...
label_a:
 	Y1
    </code></pre>
            <p>Assuming a simplistic CPU model, the operations would flow through the pipeline like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6LYtd8rNXEQA2X2pOPwmvd/e9bbdd4d54a72dc78730684252d01a84/3P6PIWN6gPAdYzP8oDgrsaOMKgUmG51zIiFhbm071cZKM276S7vRb5atpTwlKrM1lFHRYsobw8P4e-Z9t1Vb9TGeutpBe2CkMrNGruWO8yb5Qz0vZ6Qn6RbOi5Tp.png" />
            
            </figure><p>In the first cycle the BR instruction is fetched. This is an unconditional branch instruction changing the execution flow of the CPU. At this point it's not yet decoded, but the CPU would like to fetch another instruction already! Without a branch predictor in cycle 2 the fetch unit either has to wait or simply continues to the next instruction in memory, hoping it will be the right one.</p><p>In our example, instruction X1 is fetched even though this isn't the correct instruction to run. In cycle 4, when the branch instruction finishes the execute stage, the CPU will be able to understand the mistake, and roll back the speculated instructions before they have any effect. At this point the fetch unit is updated to correctly get the right instruction - Y1 in our case.</p><p>This situation of losing a number of cycles due to fetching code from an incorrect place is called a "frontend bubble". Our theoretical CPU has a two-cycle frontend bubble when a branch target wasn’t predicted right.</p><p>In this example we see that, although the CPU does the right thing in the end, without good branch prediction it wasted effort on bad instructions. In the past, various techniques have been used to reduce this problem, such as static branch prediction and branch delay slots. But the dominant CPU designs today rely <a href="https://danluu.com/branch-prediction/#one-bit">on <i>dynamic branch prediction</i></a>. This technique is able to mostly avoid the frontend bubble problem, by predicting the correct address of the next instruction even for branches that aren’t fully decoded and executed yet.</p>
    <div>
      <h3>Playing with the BTB</h3>
      <a href="#playing-with-the-btb">
        
      </a>
    </div>
    <p>Today we're focusing on the BTB - a data structure managed by the branch predictor responsible for figuring out a target of a branch. It's important to note that the BTB is distinct from and independent of the system assessing if the branch was taken or not taken. Remember, we want to figure out if a cost of a branch increases as we run more of them.</p><p>Preparing an experiment to stress only the BTB is relatively simple (<a href="https://xania.org/201602/bpu-part-three">based on Matt Godbolt's work</a>). It turns out a sequence of unconditional <code>jmps</code> is totally sufficient. Consider this x86 code:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/259y50RQfLqaFcsT4tljGb/5010158442d4e2afb6ebb3c105ee4e5b/pasted-image-0--2-.png" />
            
            </figure><p>This code stresses the BTB to an extreme - it just consists of a chain of <code>jmp +2</code> statements (i.e. literally jumping to the next instruction). In order to avoid wasting cycles on frontend pipeline bubbles, each taken jump needs a BTB hit. This branch prediction must happen very early in the CPU pipeline, before instruction decode is finished. This same mechanism is needed for any taken branch, whether it's unconditional, conditional or a function call.</p><p>The code above was run inside a test harness that measures how many CPU cycles elapse for each instruction. For example, in this run we're measuring times of dense - every two bytes - 1024 jmp instructions one after another:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3QofFzm1kmqFLuRrFPoyjQ/857bfbfe366720bd480653388f97eac8/pasted-image-0--3-.png" />
            
            </figure><p>We’ll look at the results of experiments like this for a few different CPUs. But in this instance, it was run on a machine with an AMD EPYC 7642. Here, the cold run took 10.5 cycles per jmp, and then all subsequent runs took ~3.5 cycles per jmp. The code is prepared in such a way to make sure it's the BTB that is slowing down the first run. Take a look at the full code, there is quite some magic to warm up the L1 cache and iTLB without priming the BTB.</p><p><b>Top tip 1. On this CPU a branch instruction that is taken but not predicted, costs ~7 cycles more than one that is taken and predicted.</b> Even if the branch was unconditional.</p>
    <div>
      <h3>Density matters</h3>
      <a href="#density-matters">
        
      </a>
    </div>
    <p>To get a full picture we also need to think about the density of jmp instructions in the code. The code above did eight jmps per 16-byte code block. This is a lot. For example, the code below contains one jmp instruction in each block of 16 bytes. Notice that the <code>nop</code> opcodes are jumped over. The block size doesn't change the number of executed instructions, only the code density:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2uenA2zFAkPWQZldVX7gba/8823f9ec4052618dc06c21d0621a6581/pasted-image-0--4-.png" />
            
            </figure><p>Varying the jmp block size might be important. It allows us to control the placement of the jmp opcodes. Remember the BTB is indexed by instruction pointer address. Its value and its alignment might influence the placement in the BTB and help us reveal the BTB layout. Increasing the alignment will cause more nop padding to be added. The sequence of a single measured instruction - jmp in this case - and zero or more nops, I will call "block", and its size "block size". Notice that the larger the block size, the larger the working code size for the CPU. At larger values we might see some performance drop due to exhausting L1 cache space.</p>
    <div>
      <h3>The experiment</h3>
      <a href="#the-experiment">
        
      </a>
    </div>
    <p>Our experiment is crafted to show the performance drop depending on the number of branches, across different working code sizes. Hopefully, we will be able to prove the performance is mostly dependent on the number of blocks - and therefore the BTB size, and not the working code size.</p><p>See the <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-05-branch-prediction">code on GitHub</a>. If you want to see the generated machine code, though, you need to run a special command. It's created procedurally by the code, customized by passed parameters. Here's an example <code>gdb</code> incantation:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7aAKMXz8aruwblN67UvZd7/1eb2aea7cc6e2e3a9c0f6823f60b8f08/pasted-image-0--5-.png" />
            
            </figure><p>Let's bring this experiment forward, what if we took the best times of each run - with a fully primed BTB - for varying values of jmp block sizes and number of blocks - working set size? Here you go:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ZNeolS38Q90vdHPvehvVa/64e0c16d163d74c05cfbaee6f8d9e15c/pasted-image-0--6-.png" />
            
            </figure><p>This is an astonishing chart. First, it's obvious something happens at the 4096 jmp mark[<a href="#footnotes">4</a>] regardless of how large the jmp block sizes - how many nop's we skip over. Reading it aloud:</p><ul><li><p>On the far left, we see that if the amount of code is small enough - less than 2048 bytes (256 times a block of 8 bytes) - it's possible to hit some kind of uop/L1 cache and get ~1.5 cycles per fully predicted branch. This is amazing.</p></li><li><p>Otherwise, if you keep your hot loop to 4096 branches then, no matter how dense your code is you are likely to see ~3.4 cycles per fully predicted branch</p></li><li><p>Above 4096 branches the branch predictor gives up and the cost of each branch shoots to ~10.5 cycles per jmp. This is consistent with what we saw above - unpredicted branch on flushed BTB took ~10.5 cycles.</p></li></ul><p>Great, so what does it mean? Well, you should avoid branch instructions if you want to avoid branch misses because you have at most 4096 of fast BTB slots. This is not a very pragmatic advice though - it's not like we deliberately put many unconditional <code>jmp</code>s in real code!</p><p>There are a couple of takeaways for the discussed CPU. I repeated the experiment with an always-taken conditional branch sequence and the resulting chart looks almost identical. The only difference being the predicted taken conditional-je instruction being 2 cycles slower than unconditional jmp.</p><p>An entry to BTB is added wherever a branch is "taken" - that is, the jump actually happens. An unconditional "jmp" or always taken conditional branch, will cost a BTB slot. To get best performance make sure to not have more than 4096 taken branches in the hot loop. The good news is that branches never-taken don't take space in the BTB. We can illustrate this with another experiment:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5gd2JKAwYMpgk5obd4E0Hz/29876ce9f45dc01edbb8e3966bcb9903/pasted-image-0--7-.png" />
            
            </figure><p>This boring code is going over not-taken <code>jne</code> followed by two nops (block size=4). Aimed with this test (jne never-taken), the previous one (jmp always-taken) and a conditional branch <code>je</code> always-taken, we can draw this chart:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1F2STBl6iw6OpkwqmIdlR9/1de627e490ddd75816bb3899f99f6ed7/pasted-image-0--8-.png" />
            
            </figure><p>First, without any surprise we can see the conditional 'je always-taken' is getting slightly more costly than the simple unconditional <code>jmp</code>, but only after the 4096 branches mark. This makes sense, the conditional branch is resolved later in the pipeline so the frontend bubble is longer. Then take a look at the blue line hovering near zero. This is the "jne never-taken" line flat at 0.3 clocks / block, no matter how many blocks we run in sequence. The takeaway is clear - you can have as many never-taken branches as you want, without incurring any cost. There isn't any spike at 4096 mark, meaning BTB is not used in this case. It seems the conditional jump not seen before is guessed to be not-taken.</p><p><b>Top tip 2: conditional branches never-taken are basically free</b> - at least on this CPU.</p><p>So far we established that branches always-taken occupy BTB, branches never taken do not. How about other control flow instructions, like the <code>call</code>?</p><p>I haven't been able to find this in the literature, but it seems call/ret also need the BTB entry for best performance. I was able to illustrate this on our AMD EPYC. Let's take a look at this test:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/fHArGj5TWvRM9AEM84NLJ/1951dfe42651b923551d90dddc63964f/pasted-image-0--9-.png" />
            
            </figure><p>This time we'll issue a number of <code>callq</code> instructions followed by <code>ret</code> - both of which should be fully predicted. The experiment is crafted so that each callq calls a unique function, to allow for retq prediction - each one returns to exactly one caller.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/677H5BdxwzZ9B6hbebRFnB/a1ac1602d5efab51152a6219fde87579/pasted-image-0--10-.png" />
            
            </figure><p>This chart confirms the theory: no matter the code density - with the exception of 64-byte block size being notably slower -  the cost of predicted call/ret starts to deteriorate after the 2048 mark. At this point the BTB is filled with call and ret predictions and can't handle any more data. This leads to an important conclusion:</p><p><b>Top tip 3. In the hot code you want to have less than 2K function calls</b> - on this CPU.</p><p>In our test CPU a sequence of fully predicted call/ret takes about 7 cycles, which is about the same as two unconditional predicted <code>jmp</code> opcodes. It's consistent with our results above.</p><p>So far we thoroughly checked AMD EPYC 7642. We started with this CPU because the branch predictor is relatively simple and the charts were easy to read. It turns out more recent CPUs are less clear.</p>
    <div>
      <h3>AMD EPYC 7713</h3>
      <a href="#amd-epyc-7713">
        
      </a>
    </div>
    <p>Newer AMD is more complex than the previous generations. Let's run the two most important experiments. First, the <code>jmp</code> one:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/12g3Zg18eWyHIwyUuf63gj/0cb89d1fc7a8fedbed929aa455e11dbf/pasted-image-0--11-.png" />
            
            </figure><p>For the always-taken branches case we can see a very good, sub 1 cycle, timings when the number of branches doesn't exceed 1024 and the code isn't too dense.</p><p><b>Top tip 4. On this CPU it's possible to get &lt;1 cycle per predicted jmp when the hot loop fits in ~32KiB.</b></p><p>Then there is some noise starting after the 4096 jmps mark. This is followed by a complete drop of speed at about 6000 branches. This is in line with the theory that BTB is 4096 entries long. We can speculate that some other prediction mechanism is successfully kicking in beyond that, and keeps up the performance up the ~6k mark.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4X5KfDDT36u9u2MGb7iu7t/90c4fbf3d04cd386ed6eecae645f25f8/pasted-image-0--12-.png" />
            
            </figure><p>The call/ret chart shows a similar tale, the timings start breaking after 2048 mark, and completely fail to be predicted beyond ~3000.</p>
    <div>
      <h3>Xeon Gold 6262</h3>
      <a href="#xeon-gold-6262">
        
      </a>
    </div>
    <p>The Intel Xeon looks different from the AMD:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7hIriKLopeE26yIor9qGG/9ab0d56fd18cfd4a782b7270845bc66f/pasted-image-0--13-.png" />
            
            </figure><p>Our test shows the predicted taken branch costs 2 cycles. Intel has documented a clock penalty for very dense branching code - this explains the 4-byte block size line hovering at ~3 cycles. The branch cost breaks at the 4096 jmp mark, confirming the theory that the Intel BTB can hold 4096 entries. The 64-byte block size chart looks confusing, but really isn't. The branch cost stays at flat 2 cycles up till the 512 jmp count. Then it increases. This is caused by the internal layout of the BTB which is said to be 8-way associative. It seems with the 64-byte block size we can utilize at most half of the 4096 BTB slots.</p><p><b>Top tip 5. On Intel avoid placing your jmp/call/ret instructions at regular 64-byte intervals.</b></p><p>Then the call/ret chart:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1XU4ofCRG3wfjLZlwsEhBv/2df1b19f6623a26be745caf35c28ee33/pasted-image-0--14-.png" />
            
            </figure><p>Similarly, we can see the branch predictions failing after the 2048 jmp mark - in this experiment one block uses two flow control instructions: call and ret. This again confirms the BTB size of 4K entries. The 64-byte block size is generally slower due to the nop padding but also breaks faster due to the instructions alignment issue. Notice, we haven't seen this effect on AMD.</p>
    <div>
      <h3>Apple Silicon M1</h3>
      <a href="#apple-silicon-m1">
        
      </a>
    </div>
    <p>So far we saw examples of AMD and Intel server grade CPUs. How does an Apple Silicon M1 fit in this picture?</p><p>We expect it to be very different - it's designed for mobile and it's using ARM64 architecture. Let's see our two experiments:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/bJ9lzYsIARltRCkOEJVZZ/6b1b5edcdf00e3c0a3c353fff72c8232/pasted-image-0--15-.png" />
            
            </figure><p>The predicted <code>jmp</code> test shows an interesting story. First, when the code fits 4096 bytes (1024*4 or 512*8, etc) you can expect a predicted <code>jmp</code> to cost 1 clock cycle. This is an excellent score.</p><p>Beyond that, generally, you can expect a cost of 3 clock cycles per predicted jmp. This is also very good. This starts to deteriorate when the working code grows beyond ~200KiB. This is visible with block size 64 breaking at 3072 mark 3072*64=196K, and for block 32 at 6144: 6144*32=196K. At this point the prediction seems to stop working. The documentation indicates that the M1 CPU has 192 KB L1 of instruction cache - our experiment matches that.</p><p>Let's compare the "predicted jmp" with the "unpredicted jmp" chart. Take this chart with a grain of salt, because flushing the branch predictor is notoriously difficult.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2VCtlgVdJkSB3MFuYbR5MQ/31b80611cab5b7a5ec14514dd375e7ea/pasted-image-0--16-.png" />
            
            </figure><p>However, even if we don't trust the flush-bpu code (<a href="https://xania.org/201602/bpu-part-three">adapted from Matt Godbolt</a>), this chart reveals two things. First, the "unpredicted" branch cost seems to be correlated with the branch distance. The longer the branch the costlier it is. We haven't seen such behaviour on x86 CPUs.</p><p>Then there is the cost itself. We saw a predicted sequence of branches cost, and what a supposedly-unpredicted jmp costs. In the first chart we saw that beyond ~192KiB working code, the branch predictor seems to become ineffective. The supposedly-flushed BPU seems to show the same cost. For example, the cost of a 64-byte block size jmp with a small working set size is 3 cycles. A miss is ~8 cycles. For a large working set size both times are ~8 cycles. It seems that the BTB is linked to the L1 cache state. <a href="https://www.realworldtech.com/forum/?threadid=159985&amp;curpostid=160001">Paul A. Clayton suggested</a> a possibility of such a design back in 2016.</p><p><b>Top tip 6. on M1 the predicted-taken branch generally takes 3 cycles and unpredicted but taken has varying cost, depending on jmp length. BTB is likely linked with L1 cache.</b></p><p>The call/ret chart is funny:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/54s7q6CJamAHCjpzDHFm6V/d1db62f4d8ec351ce539709cb6a512cd/pasted-image-0--17-.png" />
            
            </figure><p>Like in the chart before, we can see a big benefit if hot code fits within 4096 bytes (512*4 or 256*8). Otherwise, you can count on 4-6 cycles per call/ret sequence (or, bl/ret as it's known in ARM). The chart shows funny alignment issues. It's unclear what they are caused by. Beware, comparing the numbers in this chart with x86 is unfair, since ARM <code>call</code> operation differs substantially from the x86 variant.</p><p>M1 seems pretty fast, with predicted branches usually at 3 clock cycles. Even unpredicted branches never cost more than 8 ticks in our benchmark. Call+ret sequence for dense code should fit under 5 cycles.</p>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>We started our journey from a piece of trivial code, and asked a basic question: how costly is  adding a never-taken <code>if</code> branch in the hot portion of code?</p><p>Then we quickly dived in very low level CPU features. By the end of this article, hopefully, an astute reader might get better intuition how a modern branch predictors works.</p><p>On x86 the hot code needs to split the BTB budget between function calls and taken branches. The BTB has only a size of 4096 entries. There are strong benefits in keeping the hot code under 16KiB.</p><p>On the other hand on M1 the BTB seems to be limited by L1 instruction cache. If you're writing super hot code, ideally it should fit 4KiB.</p><p>Finally, can you add this one more <code>if</code> statement? If it's never-taken, it's probably ok. I found no evidence that such branches incur any extra cost. But do avoid always-taken branches and function calls.</p><p><b>Sources</b></p><p>I'm not the first person to investigate how BTB works. I based my experiments on:</p><ul><li><p><a href="http://www.ece.uah.edu/~milenka/docs/VladimirUzelac.thesis.pdf">Vladimir Uzelac thesis</a></p></li><li><p><a href="https://xania.org/201602/bpu-part-three">Matt Godbolt work</a>. The series has 5 articles.</p></li><li><p><a href="https://www.realworldtech.com/forum/?threadid=159985&amp;curpostid=159985">Travis Downs BTB questions</a> on Real World Tech</p></li><li><p><a href="https://stackoverflow.com/questions/38811901/slow-jmp-instruction">various</a> <a href="https://stackoverflow.com/questions/51822731/why-did-intel-change-the-static-branch-prediction-mechanism-over-these-years">stackoverflow</a> <a href="https://stackoverflow.com/questions/38512886/btb-size-for-haswell-sandy-bridge-ivy-bridge-and-skylake">discussions</a>. Especially <a href="https://stackoverflow.com/questions/31280817/what-branch-misprediction-does-the-branch-target-buffer-detect">this one</a> and <a href="https://stackoverflow.com/questions/31642902/intel-cpus-instruction-queue-provides-static-branch-prediction">this</a></p></li><li><p><a href="https://www.agner.org/optimize/microarchitecture.pdf">Agner Fog</a> microarchitecture guide has a good section on branch predictions.</p></li></ul>
    <div>
      <h3>Acknowledgements</h3>
      <a href="#acknowledgements">
        
      </a>
    </div>
    <p>Thanks to <a href="/author/david-wragg/">David Wragg</a> and <a href="https://twitter.com/danluu">Dan Luu</a> for technical expertise and proofreading help.</p>
    <div>
      <h3>PS</h3>
      <a href="#ps">
        
      </a>
    </div>
    <p>Oh, oh. But this is not the whole story! Similar research was the base to the <a href="https://spectreattack.com/spectre.pdf">Spectre v2</a> attack. The attack was exploiting the little known fact that the BPU state was not cleared between context switches. With the correct technique it was possible to train the BPU - in the case of Spectre it was iBTB - and force a privileged piece of code to be speculatively executed. This, combined with a cache side-channel data leak, allowed an attacker to steal secrets from the privileged kernel. Powerful stuff.</p><p>A proposed solution was to avoid using shared BTB. This can be done in two ways: make the indirect jumps to always fail to predict, or fix the CPU to avoid sharing BTB state across isolation domains. This is a long story, maybe for another time...</p><hr /><p><a>Footnotes</a></p><p>1. One historical solution to this specific 'if debug' problem is called "runtime nop'ing". The idea is to modify the code in runtime and patch the never-taken branch instruction with a <code>nop</code>. For example, see the "ISENABLED" discussion on <a href="https://bugzilla.mozilla.org/showbug.cgi?id=370906.">https://bugzilla.mozilla.org/showbug.cgi?id=370906.</a></p><p>2. Fun fact: modern compilers are pretty smart. New gcc (&gt;=11) and older clang (&gt;=3.7) are able to actually optimize it quite a lot. <a href="https://godbolt.org/z/KWYEW3d9s">See for yourself</a>. But, let's not get distracted by that. This article is about low level machine code branch instructions!</p><p>3. This is a simplification. There are of course more control flow instructions, like: software interrupts, syscalls, VMENTER/VMEXIT.</p><p>4. Ok, I'm slightly overinterpreting the chart. Maybe the 4096 jmp mark is due to the 4096 uop cache or some instruction decoder artifact? To prove this spike is indeed BTB related I looked at Intel BPUCLEARS.EARLY and BACLEAR.CLEAR performance counters. Its value is small for block count under 4096 and large for block count greater than 5378. This is strong evidence that the performance drop is indeed caused by the BPU and likely BTB.</p> ]]></content:encoded>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">2pvX64jHrEfNLMSmJO1Iv4</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
        <item>
            <title><![CDATA[How to execute an object file: Part 2]]></title>
            <link>https://blog.cloudflare.com/how-to-execute-an-object-file-part-2/</link>
            <pubDate>Fri, 02 Apr 2021 11:00:00 GMT</pubDate>
            <description><![CDATA[ Continue learning how to import and execute code from an object file. This time we will investigate ELF relocations. ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h2>Handling relocations</h2>
      <a href="#handling-relocations">
        
      </a>
    </div>
    <p>In the <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-1/">previous post</a>, we learned how to parse an object file and import and execute some functions from it. However, the functions in our toy object file were simple and self-contained: they computed their output solely based on their inputs and didn't have any external code or data dependencies. In this post we will build upon <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/1">the code from part 1</a>, exploring additional steps needed to handle code with some dependencies.</p><p>As an example, we may notice that we can actually rewrite our <code>add10</code> function using our <code>add5</code> function:</p><p><i>obj.c</i>:</p>
            <pre><code>int add5(int num)
{
    return num + 5;
}
 
int add10(int num)
{
    num = add5(num);
    return add5(num);
}</code></pre>
            <p>Let's recompile the object file and try to use it as a library with our <code>loader</code> program:</p>
            <pre><code>$ gcc -c obj.c
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 42</code></pre>
            <p>Whoa! Something is not right here. <code>add5</code> still produces the correct result, but <code>add10</code> does not . Depending on your environment and code composition, you may even see the <code>loader</code> program crashing instead of outputting incorrect results. To understand what happened, let's investigate the machine code generated by the compiler. We can do that by asking the <a href="https://man7.org/linux/man-pages/man1/objdump.1.html">objdump tool</a> to disassemble the <code>.text</code> section from our <code>obj.o</code>:</p>
            <pre><code>$ objdump --disassemble --section=.text obj.o
 
obj.o:     file format elf64-x86-64
 
 
Disassembly of section .text:
 
0000000000000000 &lt;add5&gt;:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	89 7d fc             	mov    %edi,-0x4(%rbp)
   7:	8b 45 fc             	mov    -0x4(%rbp),%eax
   a:	83 c0 05             	add    $0x5,%eax
   d:	5d                   	pop    %rbp
   e:	c3                   	retq
 
000000000000000f &lt;add10&gt;:
   f:	55                   	push   %rbp
  10:	48 89 e5             	mov    %rsp,%rbp
  13:	48 83 ec 08          	sub    $0x8,%rsp
  17:	89 7d fc             	mov    %edi,-0x4(%rbp)
  1a:	8b 45 fc             	mov    -0x4(%rbp),%eax
  1d:	89 c7                	mov    %eax,%edi
  1f:	e8 00 00 00 00       	callq  24 &lt;add10+0x15&gt;
  24:	89 45 fc             	mov    %eax,-0x4(%rbp)
  27:	8b 45 fc             	mov    -0x4(%rbp),%eax
  2a:	89 c7                	mov    %eax,%edi
  2c:	e8 00 00 00 00       	callq  31 &lt;add10+0x22&gt;
  31:	c9                   	leaveq
  32:	c3                   	retq</code></pre>
            <p>You don't have to understand the full output above. There are only two relevant lines here: <code>1f: e8 00 00 00 00</code> and <code>2c: e8 00 00 00 00</code>. These correspond to the two <code>add5</code> function invocations we have in the source code and <a href="https://man7.org/linux/man-pages/man1/objdump.1.html">objdump</a> even conveniently decodes the instruction for us as <code>callq</code>. By looking at descriptions of the <code>callq</code> instruction online (like <a href="https://www.felixcloutier.com/x86/call">this one</a>), we can further see we're dealing with a "near, relative call", because of the <code>0xe8</code> prefix:</p><blockquote><p>Call near, relative, displacement relative to next instruction.</p></blockquote><p>According to the <a href="https://www.felixcloutier.com/x86/call">description</a>, this variant of the <code>callq</code> instruction consists of 5 bytes: the <code>0xe8</code> prefix and a 4-byte (32 bit) argument. This is where "relative" comes from: the argument should contain the “distance” between the function we want to call and the current position — because the way how x86 works this distance is calculated from the next instruction and not our current <code>callq</code> instruction. <a href="https://man7.org/linux/man-pages/man1/objdump.1.html">objdump</a> conveniently outputs each machine instruction's offset in the output above, so we can easily calculate the needed argument. For example, for the first <code>callq</code> instruction (<code>1f: e8 00 00 00 00</code>) the next instruction is at offset <code>0x24</code>. We know we should be calling the <code>add5</code> function, which starts at offset <code>0x0</code> (beginning of our <code>.text</code> section). So the relative offset is <code>0x0 - 0x24 = -0x24</code>. Notice, we have a negative argument, because the <code>add5</code> function is located before our calling instruction, so we would be instructing the CPU to "jump backwards" from its current position. Lastly, we have to remember that negative numbers — at least on x86 systems — are presented by their <a href="https://en.wikipedia.org/wiki/Two%27s_complement">two's complements</a>, so a 4-byte (32 bit) representation of <code>-0x24</code> would be <code>0xffffffdc</code>. In the same way we can calculate the <code>callq</code> argument for the second <code>add5</code> call: <code>0x0 - 0x31 = -0x31</code>, two's complement - <code>0xffffffcf</code>:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7hr8krlEJ3GlvbDl2xV3Ww/4d838959fb33b65d3bc712c1b152262c/relative-calls.png" />
            
            </figure><p>It seems the compiler does not generate the right <code>callq</code> arguments for us. We've calculated the expected arguments to be <code>0xffffffdc</code> and <code>0xffffffcf</code>, but the compiler has just left <code>0x00000000</code> in both places. Let's check first if our expectations are correct by patching our loaded <code>.text</code> copy before trying to execute it:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void parse_obj(void)
{
...
    /* copy the contents of `.text` section from the ELF file */
    memcpy(text_runtime_base, obj.base + text_hdr-&gt;sh_offset, text_hdr-&gt;sh_size);
 
    /* the first add5 callq argument is located at offset 0x20 and should be 0xffffffdc:
     * 0x1f is the instruction offset + 1 byte instruction prefix
     */
    *((uint32_t *)(text_runtime_base + 0x1f + 1)) = 0xffffffdc;
 
    /* the second add5 callq argument is located at offset 0x2d and should be 0xffffffcf */
    *((uint32_t *)(text_runtime_base + 0x2c + 1)) = 0xffffffcf;
 
    /* make the `.text` copy readonly and executable */
    if (mprotect(text_runtime_base, page_align(text_hdr-&gt;sh_size), PROT_READ | PROT_EXEC)) {
...</code></pre>
            <p>And now let's test it out:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader 
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52</code></pre>
            <p>Clearly our monkey-patching helped: <code>add10</code> executes fine now and produces the correct output. This means our expected <code>callq</code> arguments, which we calculated, are correct. So why did the compiler emit wrong <code>callq</code> arguments?</p>
    <div>
      <h3>Relocations</h3>
      <a href="#relocations">
        
      </a>
    </div>
    <p>The problem with our toy object file is that both functions are declared with external linkage — the default setting for all functions and global variables in C. And, although both functions are declared in the same file, the compiler is not sure where the <code>add5</code> code will end up in the target binary. So the compiler avoids making any assumptions and doesn’t calculate the relative offset argument of the <code>callq</code> instructions. Let's verify this by removing our monkey patching and declaring the <code>add5</code> function as <code>static</code>:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
    /* the first add5 callq argument is located at offset 0x20 and should be 0xffffffdc:
     * 0x1f is the instruction offset + 1 byte instruction prefix
     */
    /* *((uint32_t *)(text_runtime_base + 0x1f + 1)) = 0xffffffdc; */
 
    /* the second add5 callq argument is located at offset 0x2d and should be 0xffffffcf */
    /* *((uint32_t *)(text_runtime_base + 0x2c + 1)) = 0xffffffcf; */
 
...</code></pre>
            <p><i>obj.c</i>:</p>
            <pre><code>/* int add5(int num) */
static int add5(int num)
...</code></pre>
            <p>Recompiling and disassembling <code>obj.o</code> gives us the following:</p>
            <pre><code>$ gcc -c obj.c
$ objdump --disassemble --section=.text obj.o
 
obj.o:     file format elf64-x86-64
 
 
Disassembly of section .text:
 
0000000000000000 &lt;add5&gt;:
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	89 7d fc             	mov    %edi,-0x4(%rbp)
   7:	8b 45 fc             	mov    -0x4(%rbp),%eax
   a:	83 c0 05             	add    $0x5,%eax
   d:	5d                   	pop    %rbp
   e:	c3                   	retq
 
000000000000000f &lt;add10&gt;:
   f:	55                   	push   %rbp
  10:	48 89 e5             	mov    %rsp,%rbp
  13:	48 83 ec 08          	sub    $0x8,%rsp
  17:	89 7d fc             	mov    %edi,-0x4(%rbp)
  1a:	8b 45 fc             	mov    -0x4(%rbp),%eax
  1d:	89 c7                	mov    %eax,%edi
  1f:	e8 dc ff ff ff       	callq  0 &lt;add5&gt;
  24:	89 45 fc             	mov    %eax,-0x4(%rbp)
  27:	8b 45 fc             	mov    -0x4(%rbp),%eax
  2a:	89 c7                	mov    %eax,%edi
  2c:	e8 cf ff ff ff       	callq  0 &lt;add5&gt;
  31:	c9                   	leaveq
  32:	c3                   	retq</code></pre>
            <p>Because we re-declared the <code>add5</code> function with internal linkage, the compiler is more confident now and calculates <code>callq</code> arguments correctly (note that x86 systems are <a href="https://en.wikipedia.org/wiki/Endianness">little-endian</a>, so multibyte numbers like <code>0xffffffdc</code> will be represented with least significant byte first). We can double check this by recompiling and running our <code>loader</code> test tool:</p>
            <pre><code>$ gcc -o loader loader.c
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52</code></pre>
            <p>Even though the <code>add5</code> function is declared as <code>static</code>, we can still call it from the <code>loader</code> tool, basically ignoring the fact that it is an "internal" function now. Because of this, the <code>static</code> keyword should not be used as a security feature to hide APIs from potential malicious users.</p><p>But let's step back and revert our <code>add5</code> function in <code>obj.c</code> to the one with external linkage:</p><p><i>obj.c</i>:</p>
            <pre><code>int add5(int num)
...</code></pre>
            
            <pre><code>$ gcc -c obj.c
$ ./loader
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 42</code></pre>
            <p>As we have established above, the compiler did not compute proper <code>callq</code> arguments for us because it didn't have enough information. But later stages (namely the linker) will have that information, so instead the compiler leaves some clues on how to fix those arguments. These clues — or instructions for the later stages — are called <b>relocations</b>. We can inspect them with our friend, the <a href="https://man7.org/linux/man-pages/man1/readelf.1.html">readelf</a> utility. Let's examine <code>obj.o</code> sections table again:</p>
            <pre><code>$ readelf --sections obj.o
There are 12 section headers, starting at offset 0x2b0:
 
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000033  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  000001f0
       0000000000000030  0000000000000018   I       9     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000073
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .bss              NOBITS           0000000000000000  00000073
       0000000000000000  0000000000000000  WA       0     0     1
  [ 5] .comment          PROGBITS         0000000000000000  00000073
       000000000000001d  0000000000000001  MS       0     0     1
  [ 6] .note.GNU-stack   PROGBITS         0000000000000000  00000090
       0000000000000000  0000000000000000           0     0     1
  [ 7] .eh_frame         PROGBITS         0000000000000000  00000090
       0000000000000058  0000000000000000   A       0     0     8
  [ 8] .rela.eh_frame    RELA             0000000000000000  00000220
       0000000000000030  0000000000000018   I       9     7     8
  [ 9] .symtab           SYMTAB           0000000000000000  000000e8
       00000000000000f0  0000000000000018          10     8     8
  [10] .strtab           STRTAB           0000000000000000  000001d8
       0000000000000012  0000000000000000           0     0     1
  [11] .shstrtab         STRTAB           0000000000000000  00000250
       0000000000000059  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)</code></pre>
            <p>We see that the compiler created a new section called <code>.rela.text</code>. By convention, a section with relocations for a section named <code>.foo</code> will be called <code>.rela.foo</code>, so we can see that the compiler created a section with relocations for the <code>.text</code> section. We can examine the relocations further:</p>
            <pre><code>$ readelf --relocs obj.o
 
Relocation section '.rela.text' at offset 0x1f0 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000800000004 R_X86_64_PLT32    0000000000000000 add5 - 4
00000000002d  000800000004 R_X86_64_PLT32    0000000000000000 add5 - 4
 
Relocation section '.rela.eh_frame' at offset 0x220 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
000000000040  000200000002 R_X86_64_PC32     0000000000000000 .text + f</code></pre>
            <p>Let's ignore the relocations from the <code>.rela.eh_frame</code> section because they are out of scope of this post. Instead, let’s try to understand the relocations from the <code>.rela.text</code>:</p><ul><li><p><code>Offset</code> column tells us exactly where in the target section (<code>.text</code> in this case) the fix/adjustment is needed. Note that these offsets are exactly the same as in our self-calculated monkey-patching above.</p></li><li><p><code>Info</code> is a combined value: the upper 32 bits — only 16 bits are shown in the output above — represent the index of the symbol in the symbol table, with respect to which the relocation is performed. In our example it is <code>8</code> and if we run <code>readelf --symbols obj.o</code> we will see that it points to an entry corresponding to the <code>add5</code> function. The lower 32 bits (<code>4</code> in our case) is a relocation type (see <code>Type</code> below).</p></li><li><p><code>Type</code> describes the relocation type. This is a pseudo-column: <code>readelf</code> actually generates it from the lower 32 bits of the <code>Info</code> field. Different relocation types have different formulas we need to apply to perform the relocation.</p></li><li><p><code>Sym. Value</code> may mean different things depending on the relocation type, but most of the time it is the symbol offset with respect to which we perform the relocation. The offset is calculated from the beginning of that symbol’s section.</p></li><li><p><code>Addend</code> is a constant we may need to use in the relocation formula. Depending on the relocation type, <a href="https://man7.org/linux/man-pages/man1/readelf.1.html">readelf</a> actually adds the decoded symbol name to the output, so the column name is <code>Sym. Name + Addend</code> above but the actual field stores the addend only.</p></li></ul><p>In a nutshell, these entries tell us that we need to patch the <code>.text</code> section at offsets <code>0x20</code> and <code>0x2d</code>. To calculate what to put there, we need to apply the formula for the <code>R_X86_64_PLT32</code> relocation type. Searching online, we can find different ELF specifications — like <a href="https://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf">this one</a> — which will tell us how to implement the <code>R_X86_64_PLT32</code> relocation. The specification mentions that the result of this relocation is <code>word32</code> — which is what we expect because <code>callq</code> arguments are 32 bit in our case — and the formula we need to apply is <code>L + A - P</code>, where:</p><ul><li><p><code>L</code> is the address of the symbol, with respect to which the relocation is performed (<code>add5</code> in our case)</p></li><li><p><code>A</code> is the constant addend (<code>4</code> in our case)</p></li><li><p><code>P</code> is the address/offset, where we store the result of the relocation</p></li></ul><p>When the relocation formula references some symbol addresses or offsets, we should use the actual — runtime in our case — addresses in the calculations. For example, we will be using <code>text_runtime_base + 0x2d</code> as <code>P</code> for the second relocation and not just <code>0x2d</code>. So let's try to implement this relocation logic in our object loader:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
/* from https://elixir.bootlin.com/linux/v5.11.6/source/arch/x86/include/asm/elf.h#L51 */
#define R_X86_64_PLT32 4
 
...
 
static uint8_t *section_runtime_base(const Elf64_Shdr *section)
{
    const char *section_name = shstrtab + section-&gt;sh_name;
    size_t section_name_len = strlen(section_name);
 
    /* we only mmap .text section so far */
    if (strlen(".text") == section_name_len &amp;&amp; !strcmp(".text", section_name))
        return text_runtime_base;
 
    fprintf(stderr, "No runtime base address for section %s\n", section_name);
    exit(ENOENT);
}
 
static void do_text_relocations(void)
{
    /* we actually cheat here - the name .rela.text is a convention, but not a
     * rule: to figure out which section should be patched by these relocations
     * we would need to examine the rela_text_hdr, but we skip it for simplicity
     */
    const Elf64_Shdr *rela_text_hdr = lookup_section(".rela.text");
    if (!rela_text_hdr) {
        fputs("Failed to find .rela.text\n", stderr);
        exit(ENOEXEC);
    }
 
    int num_relocations = rela_text_hdr-&gt;sh_size / rela_text_hdr-&gt;sh_entsize;
    const Elf64_Rela *relocations = (Elf64_Rela *)(obj.base + rela_text_hdr-&gt;sh_offset);
 
    for (int i = 0; i &lt; num_relocations; i++) {
        int symbol_idx = ELF64_R_SYM(relocations[i].r_info);
        int type = ELF64_R_TYPE(relocations[i].r_info);
 
        /* where to patch .text */
        uint8_t *patch_offset = text_runtime_base + relocations[i].r_offset;
        /* symbol, with respect to which the relocation is performed */
        uint8_t *symbol_address = section_runtime_base(&amp;sections[symbols[symbol_idx].st_shndx]) + symbols[symbol_idx].st_value;
 
        switch (type)
        {
        case R_X86_64_PLT32:
            /* L + A - P, 32 bit output */
            *((uint32_t *)patch_offset) = symbol_address + relocations[i].r_addend - patch_offset;
            printf("Calculated relocation: 0x%08x\n", *((uint32_t *)patch_offset));
            break;
        }
    }
}
 
static void parse_obj(void)
{
...
 
    /* copy the contents of `.text` section from the ELF file */
    memcpy(text_runtime_base, obj.base + text_hdr-&gt;sh_offset, text_hdr-&gt;sh_size);
 
    do_text_relocations();
 
    /* make the `.text` copy readonly and executable */
    if (mprotect(text_runtime_base, page_align(text_hdr-&gt;sh_size), PROT_READ | PROT_EXEC)) {
 
...
}
 
...</code></pre>
            <p>We are now calling the <code>do_text_relocations</code> function before marking our <code>.text</code> copy executable. We have also added some debugging output to inspect the result of the relocation calculations. Let's try it out:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader 
Calculated relocation: 0xffffffdc
Calculated relocation: 0xffffffcf
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52</code></pre>
            <p>Great! Our imported code works as expected now. By following the relocation hints left for us by the compiler, we've got the same results as in our monkey-patching calculations in the beginning of this post. Our relocation calculations also involved <code>text_runtime_base</code> address, which is not available at compile time. That's why the compiler could not calculate the <code>callq</code> arguments in the first place and had to emit the relocations instead.</p>
    <div>
      <h3>Handling constant data and global variables</h3>
      <a href="#handling-constant-data-and-global-variables">
        
      </a>
    </div>
    <p>So far, we have been dealing with object files containing only executable code with no state. That is, the imported functions could compute their output solely based on the inputs. Let's see what happens if we add some constant data and global variables dependencies to our imported code. First, we add some more functions to our <code>obj.o</code>:</p><p><i>obj.c</i>:</p>
            <pre><code>...
 
const char *get_hello(void)
{
    return "Hello, world!";
}
 
static int var = 5;
 
int get_var(void)
{
    return var;
}
 
void set_var(int num)
{
    var = num;
}</code></pre>
            <p><code>get_hello</code> returns a constant string and <code>get_var</code>/<code>set_var</code> get and set a global variable respectively. Next, let's recompile the <code>obj.o</code> and run our loader:</p>
            <pre><code>$ gcc -c obj.c
$ ./loader 
Calculated relocation: 0xffffffdc
Calculated relocation: 0xffffffcf
No runtime base address for section .rodata</code></pre>
            <p>Looks like our loader tried to process more relocations but could not find the runtime address for <code>.rodata</code> section. Previously, we didn't even have a <code>.rodata</code> section, but it was added now because our <code>obj.o</code> needs somewhere to store the constant string <code>Hello, world!:</code></p>
            <pre><code>$ readelf --sections obj.o
There are 13 section headers, starting at offset 0x478:
 
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000005f  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  00000320
       0000000000000078  0000000000000018   I      10     1     8
  [ 3] .data             PROGBITS         0000000000000000  000000a0
       0000000000000004  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  000000a4
       0000000000000000  0000000000000000  WA       0     0     1
  [ 5] .rodata           PROGBITS         0000000000000000  000000a4
       000000000000000d  0000000000000000   A       0     0     1
  [ 6] .comment          PROGBITS         0000000000000000  000000b1
       000000000000001d  0000000000000001  MS       0     0     1
  [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000ce
       0000000000000000  0000000000000000           0     0     1
  [ 8] .eh_frame         PROGBITS         0000000000000000  000000d0
       00000000000000b8  0000000000000000   A       0     0     8
  [ 9] .rela.eh_frame    RELA             0000000000000000  00000398
       0000000000000078  0000000000000018   I      10     8     8
  [10] .symtab           SYMTAB           0000000000000000  00000188
       0000000000000168  0000000000000018          11    10     8
  [11] .strtab           STRTAB           0000000000000000  000002f0
       000000000000002c  0000000000000000           0     0     1
  [12] .shstrtab         STRTAB           0000000000000000  00000410
       0000000000000061  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)</code></pre>
            <p>We also have more <code>.text</code> relocations:</p>
            <pre><code>$ readelf --relocs obj.o
 
Relocation section '.rela.text' at offset 0x320 contains 5 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000a00000004 R_X86_64_PLT32    0000000000000000 add5 - 4
00000000002d  000a00000004 R_X86_64_PLT32    0000000000000000 add5 - 4
00000000003a  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4
000000000046  000300000002 R_X86_64_PC32     0000000000000000 .data - 4
000000000058  000300000002 R_X86_64_PC32     0000000000000000 .data - 4
...</code></pre>
            <p>The compiler emitted three more <code>R_X86_64_PC32</code> relocations this time. They reference symbols with index <code>3</code> and <code>5</code>, so let's find out what they are:</p>
            <pre><code>$ readelf --symbols obj.o
 
Symbol table '.symtab' contains 15 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS obj.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    3 var
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
    10: 0000000000000000    15 FUNC    GLOBAL DEFAULT    1 add5
    11: 000000000000000f    36 FUNC    GLOBAL DEFAULT    1 add10
    12: 0000000000000033    13 FUNC    GLOBAL DEFAULT    1 get_hello
    13: 0000000000000040    12 FUNC    GLOBAL DEFAULT    1 get_var
    14: 000000000000004c    19 FUNC    GLOBAL DEFAULT    1 set_var</code></pre>
            <p>Entries <code>3</code> and <code>5</code> don't have any names attached, but they reference something in sections with index <code>3</code> and <code>5</code> respectively. In the output of the section table above, we can see that the section with index <code>3</code> is <code>.data</code> and the section with index <code>5</code> is <code>.rodata</code>. For a refresher on the most common sections in an ELF file check out our <a href="https://blog.cloudflare.com/how-to-execute-an-object-file-part-1/">previous post</a>. To import our newly added code and make it work, we also need to map <code>.data</code> and <code>.rodata</code> sections in addition to the <code>.text</code> section and process these <code>R_X86_64_PC32</code> relocations.</p><p>There is one caveat though. If we check <a href="https://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf">the specification</a>, we'll see that <code>R_X86_64_PC32</code> relocation produces a 32-bit output similar to the <code>R_X86_64_PLT32</code> relocation. This means that the "distance" in memory between the patched position in <code>.text</code> and the referenced symbol has to be small enough to fit into a 32-bit value (1 bit for the positive/negative sign and 31 bits for the actual data, so less than 2147483647 bytes). Our <code>loader</code> program uses <a href="https://man7.org/linux/man-pages/man2/mmap.2.html">mmap system call</a> to allocate memory for the object section copies, but <a href="https://man7.org/linux/man-pages/man2/mmap.2.html">mmap</a> may allocate the mapping almost anywhere in the process address space. If we modify the <code>loader</code> program to call <a href="https://man7.org/linux/man-pages/man2/mmap.2.html">mmap</a> for each section separately, we may end up having <code>.rodata</code> or <code>.data</code> section mapped too far away from the <code>.text</code> section and will not be able to process the <code>R_X86_64_PC32</code> relocations. In other words, we need to ensure that <code>.data</code> and <code>.rodata</code> sections are located relatively close to the <code>.text</code> section at runtime:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4e8Qr6ZYKMwqrHQAgJhnHD/402256ee621e61484ca011ed8994b185/runtime-diff.png" />
            
            </figure><p>One way to achieve that would be to allocate the memory we need for all the sections with one <a href="https://man7.org/linux/man-pages/man2/mmap.2.html">mmap call</a>. Then, we’d break it in chunks and assign proper access permissions to each chunk. Let's modify our <code>loader</code> program to do just that:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
/* runtime base address of the imported code */
static uint8_t *text_runtime_base;
/* runtime base of the .data section */
static uint8_t *data_runtime_base;
/* runtime base of the .rodata section */
static uint8_t *rodata_runtime_base;
 
...
 
static void parse_obj(void)
{
...
 
    /* find the `.text` entry in the sections table */
    const Elf64_Shdr *text_hdr = lookup_section(".text");
    if (!text_hdr) {
        fputs("Failed to find .text\n", stderr);
        exit(ENOEXEC);
    }
 
    /* find the `.data` entry in the sections table */
    const Elf64_Shdr *data_hdr = lookup_section(".data");
    if (!data_hdr) {
        fputs("Failed to find .data\n", stderr);
        exit(ENOEXEC);
    }
 
    /* find the `.rodata` entry in the sections table */
    const Elf64_Shdr *rodata_hdr = lookup_section(".rodata");
    if (!rodata_hdr) {
        fputs("Failed to find .rodata\n", stderr);
        exit(ENOEXEC);
    }
 
    /* allocate memory for `.text`, `.data` and `.rodata` copies rounding up each section to whole pages */
    text_runtime_base = mmap(NULL, page_align(text_hdr-&gt;sh_size) + page_align(data_hdr-&gt;sh_size) + page_align(rodata_hdr-&gt;sh_size), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (text_runtime_base == MAP_FAILED) {
        perror("Failed to allocate memory");
        exit(errno);
    }
 
    /* .data will come right after .text */
    data_runtime_base = text_runtime_base + page_align(text_hdr-&gt;sh_size);
    /* .rodata will come after .data */
    rodata_runtime_base = data_runtime_base + page_align(data_hdr-&gt;sh_size);
 
    /* copy the contents of `.text` section from the ELF file */
    memcpy(text_runtime_base, obj.base + text_hdr-&gt;sh_offset, text_hdr-&gt;sh_size);
    /* copy .data */
    memcpy(data_runtime_base, obj.base + data_hdr-&gt;sh_offset, data_hdr-&gt;sh_size);
    /* copy .rodata */
    memcpy(rodata_runtime_base, obj.base + rodata_hdr-&gt;sh_offset, rodata_hdr-&gt;sh_size);
 
    do_text_relocations();
 
    /* make the `.text` copy readonly and executable */
    if (mprotect(text_runtime_base, page_align(text_hdr-&gt;sh_size), PROT_READ | PROT_EXEC)) {
        perror("Failed to make .text executable");
        exit(errno);
    }
 
    /* we don't need to do anything with .data - it should remain read/write */
 
    /* make the `.rodata` copy readonly */
    if (mprotect(rodata_runtime_base, page_align(rodata_hdr-&gt;sh_size), PROT_READ)) {
        perror("Failed to make .rodata readonly");
        exit(errno);
    }
}
 
...</code></pre>
            <p>Now that we have runtime addresses of <code>.data</code> and <code>.rodata</code>, we can update the relocation runtime address lookup function:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static uint8_t *section_runtime_base(const Elf64_Shdr *section)
{
    const char *section_name = shstrtab + section-&gt;sh_name;
    size_t section_name_len = strlen(section_name);
 
    if (strlen(".text") == section_name_len &amp;&amp; !strcmp(".text", section_name))
        return text_runtime_base;
 
    if (strlen(".data") == section_name_len &amp;&amp; !strcmp(".data", section_name))
        return data_runtime_base;
 
    if (strlen(".rodata") == section_name_len &amp;&amp; !strcmp(".rodata", section_name))
        return rodata_runtime_base;
 
    fprintf(stderr, "No runtime base address for section %s\n", section_name);
    exit(ENOENT);
}</code></pre>
            <p>And finally we can import and execute our new functions:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
static void execute_funcs(void)
{
    /* pointers to imported functions */
    int (*add5)(int);
    int (*add10)(int);
    const char *(*get_hello)(void);
    int (*get_var)(void);
    void (*set_var)(int num);
 
...
 
    printf("add10(%d) = %d\n", 42, add10(42));
 
    get_hello = lookup_function("get_hello");
    if (!get_hello) {
        fputs("Failed to find get_hello function\n", stderr);
        exit(ENOENT);
    }
 
    puts("Executing get_hello...");
    printf("get_hello() = %s\n", get_hello());
 
    get_var = lookup_function("get_var");
    if (!get_var) {
        fputs("Failed to find get_var function\n", stderr);
        exit(ENOENT);
    }
 
    puts("Executing get_var...");
    printf("get_var() = %d\n", get_var());
 
    set_var = lookup_function("set_var");
    if (!set_var) {
        fputs("Failed to find set_var function\n", stderr);
        exit(ENOENT);
    }
 
    puts("Executing set_var(42)...");
    set_var(42);
 
    puts("Executing get_var again...");
    printf("get_var() = %d\n", get_var());
}
...</code></pre>
            <p>Let's try it out:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader 
Calculated relocation: 0xffffffdc
Calculated relocation: 0xffffffcf
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52
Executing get_hello...
get_hello() = ]�UH��
Executing get_var...
get_var() = 1213580125
Executing set_var(42)...
Segmentation fault</code></pre>
            <p>Uh-oh! We forgot to implement the new <code>R_X86_64_PC32</code> relocation type. The <a href="https://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf">relocation formula</a> here is <code>S + A - P</code>. We already know about <code>A</code> and <code>P</code>. As for <code>S</code> (quoting from <a href="https://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf">the spec</a>):</p><blockquote><p>“the value of the symbol whose index resides in the relocation entry"</p></blockquote><p>In our case, it is essentially the same as <code>L</code> for <code>R_X86_64_PLT32</code>. We can just reuse the implementation and remove the debug output in the process:</p><p><i>loader.c</i>:</p>
            <pre><code>...
 
/* from https://elixir.bootlin.com/linux/v5.11.6/source/arch/x86/include/asm/elf.h#L51 */
#define R_X86_64_PC32 2
#define R_X86_64_PLT32 4
 
...
 
static void do_text_relocations(void)
{
    /* we actually cheat here - the name .rela.text is a convention, but not a
     * rule: to figure out which section should be patched by these relocations
     * we would need to examine the rela_text_hdr, but we skip it for simplicity
     */
    const Elf64_Shdr *rela_text_hdr = lookup_section(".rela.text");
    if (!rela_text_hdr) {
        fputs("Failed to find .rela.text\n", stderr);
        exit(ENOEXEC);
    }
 
    int num_relocations = rela_text_hdr-&gt;sh_size / rela_text_hdr-&gt;sh_entsize;
    const Elf64_Rela *relocations = (Elf64_Rela *)(obj.base + rela_text_hdr-&gt;sh_offset);
 
    for (int i = 0; i &lt; num_relocations; i++) {
        int symbol_idx = ELF64_R_SYM(relocations[i].r_info);
        int type = ELF64_R_TYPE(relocations[i].r_info);
 
        /* where to patch .text */
        uint8_t *patch_offset = text_runtime_base + relocations[i].r_offset;
        /* symbol, with respect to which the relocation is performed */
        uint8_t *symbol_address = section_runtime_base(&amp;sections[symbols[symbol_idx].st_shndx]) + symbols[symbol_idx].st_value;
 
        switch (type)
        {
        case R_X86_64_PC32:
            /* S + A - P, 32 bit output, S == L here */
        case R_X86_64_PLT32:
            /* L + A - P, 32 bit output */
            *((uint32_t *)patch_offset) = symbol_address + relocations[i].r_addend - patch_offset;
            break;
        }
    }
}
 
...</code></pre>
            <p>Now we should be done. Another try:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader 
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52
Executing get_hello...
get_hello() = Hello, world!
Executing get_var...
get_var() = 5
Executing set_var(42)...
Executing get_var again...
get_var() = 42</code></pre>
            <p>This time we can successfully import functions that reference static constant data and global variables. We can even manipulate the object file’s internal state through the defined accessor interface. As before, the complete source code for this post is <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/2">available on GitHub</a>.</p><p>In the next post, we will look into importing and executing object code with references to external libraries. Stay tuned!</p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <guid isPermaLink="false">6S16duVAPX4oHU5pN43RlW</guid>
            <dc:creator>Ignat Korchagin</dc:creator>
        </item>
        <item>
            <title><![CDATA[How to execute an object file: Part 1]]></title>
            <link>https://blog.cloudflare.com/how-to-execute-an-object-file-part-1/</link>
            <pubDate>Tue, 02 Mar 2021 12:00:00 GMT</pubDate>
            <description><![CDATA[ Ever wondered if it is possible to execute an object file without linking? Or use any object file as a library? Follow along to learn how to decompose an object file and import code from it along the way. ]]></description>
            <content:encoded><![CDATA[ <p></p>
    <div>
      <h2>Calling a simple function without linking</h2>
      <a href="#calling-a-simple-function-without-linking">
        
      </a>
    </div>
    <p>When we write software using a high-level compiled programming language, there are usually a number of steps involved in transforming our source code into the final executable binary:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3RNZmg4aDxjJOAjAmYxFk9/c1279a03f8962b5bb74f812b66a4a448/build.png" />
            
            </figure><p>First, our source files are compiled by a <i>compiler</i> translating the high-level programming language into machine code. The output of the compiler is a number of <i>object</i> files. If the project contains multiple source files, we usually get as many object files. The next step is the <i>linker</i>: since the code in different object files may reference each other, the linker is responsible for assembling all these object files into one big program and binding these references together. The output of the linker is usually our target executable, so only one file.</p><p>However, at this point, our executable might still be incomplete. These days, most executables on Linux are dynamically linked: the executable itself does not have all the code it needs to run a program. Instead it expects to "borrow" part of the code at runtime from <a href="https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries">shared libraries</a> for some of its functionality:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4qgviYFjrBDkGj5OckqJFi/a94b46caad8bfcda8eb96ad7eba84d67/runtime.png" />
            
            </figure><p>This process is called <i>runtime linking</i>: when our executable is being started, the operating system will invoke the <i>dynamic loader</i>, which should find all the needed libraries, copy/map their code into our target process address space, and resolve all the dependencies our code has on them.</p><p>One interesting thing to note about this overall process is that we get the executable machine code directly from step 1 (compiling the source code), but if any of the later steps fail, we still can't execute our program. So, in this series of blog posts we will investigate if it is possible to execute machine code directly from object files skipping all the later steps.</p>
    <div>
      <h4>Why would we want to execute an object file?</h4>
      <a href="#why-would-we-want-to-execute-an-object-file">
        
      </a>
    </div>
    <p>There may be many reasons. Perhaps we're writing an open-source replacement for a proprietary Linux driver or an application, and want to compare if the behaviour of some code is the same. Or we have a piece of a rare, obscure program and we can't link to it, because it was compiled with a rare, obscure compiler. Maybe we have a source file, but cannot create a full featured executable, because of the missing build time or runtime dependencies. Malware analysis, code from a different operating system etc - all these scenarios may put us in a position, where either linking is not possible or the runtime environment is not suitable.</p>
    <div>
      <h3>A simple toy object file</h3>
      <a href="#a-simple-toy-object-file">
        
      </a>
    </div>
    <p>For the purposes of this article, let's create a simple toy object file, so we can use it in our experiments:</p><p><i>obj.c</i>:</p>
            <pre><code>int add5(int num)
{
    return num + 5;
}

int add10(int num)
{
    return num + 10;
}</code></pre>
            <p>Our source file contains only 2 functions, <code>add5</code> and <code>add10</code>, which adds 5 or 10 respectively to the only input parameter. It's a small but fully functional piece of code, and we can easily compile it into an object file:</p>
            <pre><code>$ gcc -c obj.c 
$ ls
obj.c  obj.o</code></pre>
            
    <div>
      <h3>Loading an object file into the process memory</h3>
      <a href="#loading-an-object-file-into-the-process-memory">
        
      </a>
    </div>
    <p>Now we will try to import the <code>add5</code> and <code>add10</code> functions from the object file and execute them. When we talk about executing an object file, we mean using an object file as some sort of a library. As we learned above, when we have an executable that utilises external shared libraries, the <i>dynamic loader</i> loads these libraries into the process address space for us. With object files, however, we have to do this manually, because ultimately we can't execute machine code that doesn't reside in the operating system's RAM. So, to execute object files we still need some kind of a wrapper program:</p><p><i>loader.c</i>:</p>
            <pre><code>#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

static void load_obj(void)
{
    /* load obj.o into memory */
}

static void parse_obj(void)
{
    /* parse an object file and find add5 and add10 functions */
}

static void execute_funcs(void)
{
    /* execute add5 and add10 with some inputs */
}

int main(void)
{
    load_obj();
    parse_obj();
    execute_funcs();

    return 0;
}</code></pre>
            <p>Above is a self-contained object loader program with some functions as placeholders. We will be implementing these functions (and adding more) in the course of this post.</p><p>First, as we established already, we need to load our object file into the process address space. We could just read the whole file into a buffer, but that would not be very efficient. Real-world object files might be big, but as we will see later, we don't need all of the object's file contents. So it is better to <a href="https://man7.org/linux/man-pages/man2/mmap.2.html"><code>mmap</code></a> the file instead: this way the operating system will lazily read the parts from the file we need at the time we need them. Let's implement the <code>load_obj</code> function:</p><p><i>loader.c</i>:</p>
            <pre><code>...
/* for open(2), fstat(2) */
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;

/* for close(2), fstat(2) */
#include &lt;unistd.h&gt;

/* for mmap(2) */
#include &lt;sys/mman.h&gt;

/* parsing ELF files */
#include &lt;elf.h&gt;

/* for errno */
#include &lt;errno.h&gt;

typedef union {
    const Elf64_Ehdr *hdr;
    const uint8_t *base;
} objhdr;

/* obj.o memory address */
static objhdr obj;

static void load_obj(void)
{
    struct stat sb;

    int fd = open("obj.o", O_RDONLY);
    if (fd &lt;= 0) {
        perror("Cannot open obj.o");
        exit(errno);
    }

    /* we need obj.o size for mmap(2) */
    if (fstat(fd, &amp;sb)) {
        perror("Failed to get obj.o info");
        exit(errno);
    }

    /* mmap obj.o into memory */
    obj.base = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (obj.base == MAP_FAILED) {
        perror("Maping obj.o failed");
        exit(errno);
    }
    close(fd);
}
...</code></pre>
            <p>If we don't encounter any errors, after <code>load_obj</code> executes we should get the memory address, which points to the beginning of our <code>obj.o</code> in the <code>obj</code> global variable. It is worth noting we have created a special union type for the <code>obj</code> variable: we will be parsing <code>obj.o</code> later (and peeking ahead - object files are actually <a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">ELF files</a>), so will be referring to the address both as <code>Elf64_Ehdr</code> (ELF header structure in C) and a byte pointer (parsing ELF files involves calculations of byte offsets from the beginning of the file).</p>
    <div>
      <h3>A peek inside an object file</h3>
      <a href="#a-peek-inside-an-object-file">
        
      </a>
    </div>
    <p>To use some code from an object file, we need to find it first. As I've leaked above, object files are actually <a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">ELF files</a> (the same format as Linux executables and shared libraries) and luckily they’re easy to parse on Linux with the help of the standard <code>elf.h</code> header, which includes many useful definitions related to the ELF file structure. But we actually need to know what we’re looking for, so a high-level understanding of an ELF file is needed.</p>
    <div>
      <h4>ELF segments and sections</h4>
      <a href="#elf-segments-and-sections">
        
      </a>
    </div>
    <p>Segments (also known as program headers) and sections are probably the main parts of an ELF file and usually a starting point of any ELF tutorial. However, there is often some confusion between the two. Different sections contain different types of ELF data: executable code (which we are most interested in in this post), constant data, global variables etc. Segments, on the other hand, do not contain any data themselves - they just describe to the operating system how to properly load sections into RAM for the executable to work correctly. Some tutorials say "a segment may include 0 or more sections", which is not entirely accurate: segments do not contain sections, rather they just indicate to the OS where in memory a particular section should be loaded and what is the access pattern for this memory (read, write or execute):</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7E14iCMhz5ADpvhMnfyswT/8f97b1cf69b5788744e31b1a5853c8db/segments-sections.png" />
            
            </figure><p>Furthermore, object files do not contain any segments at all: an object file is not meant to be directly loaded by the OS. Instead, it is assumed it will be linked with some other code, so ELF segments are usually generated by the linker, not the compiler. We can check this by using the <a href="https://man7.org/linux/man-pages/man1/readelf.1.html">readelf command</a>:</p>
            <pre><code>$ readelf --segments obj.o

There are no program headers in this file.</code></pre>
            
    <div>
      <h4>Object file sections</h4>
      <a href="#object-file-sections">
        
      </a>
    </div>
    <p>The same <a href="https://man7.org/linux/man-pages/man1/readelf.1.html">readelf command</a> can be used to get all the sections from our object file:</p>
            <pre><code>$ readelf --sections obj.o
There are 11 section headers, starting at offset 0x268:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000001e  0000000000000000  AX       0     0     1
  [ 2] .data             PROGBITS         0000000000000000  0000005e
       0000000000000000  0000000000000000  WA       0     0     1
  [ 3] .bss              NOBITS           0000000000000000  0000005e
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .comment          PROGBITS         0000000000000000  0000005e
       000000000000001d  0000000000000001  MS       0     0     1
  [ 5] .note.GNU-stack   PROGBITS         0000000000000000  0000007b
       0000000000000000  0000000000000000           0     0     1
  [ 6] .eh_frame         PROGBITS         0000000000000000  00000080
       0000000000000058  0000000000000000   A       0     0     8
  [ 7] .rela.eh_frame    RELA             0000000000000000  000001e0
       0000000000000030  0000000000000018   I       8     6     8
  [ 8] .symtab           SYMTAB           0000000000000000  000000d8
       00000000000000f0  0000000000000018           9     8     8
  [ 9] .strtab           STRTAB           0000000000000000  000001c8
       0000000000000012  0000000000000000           0     0     1
  [10] .shstrtab         STRTAB           0000000000000000  00000210
       0000000000000054  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)</code></pre>
            <p>There are different tutorials online describing the most popular ELF sections in detail. Another great reference is the <a href="https://man7.org/linux/man-pages/man5/elf.5.html">Linux manpages project</a>. It is handy because it describes both sections’ purpose as well as C structure definitions from <code>elf.h</code>, which makes it a one-stop shop for parsing ELF files. However, for completeness, below is a short description of the most popular sections one may encounter in an ELF file:</p><ul><li><p><code>.text</code>: this section contains the executable code (the actual machine code, which was created by the compiler from our source code). This section is the primary area of interest for this post as it should contain the <code>add5</code> and <code>add10</code> functions we want to use.</p></li><li><p><code>.data</code> and <code>.bss</code>: these sections contain global and static local variables. The difference is: <code>.data</code> has variables with an initial value (defined like <code>int foo = 5;</code>) and <code>.bss</code> just reserves space for variables with no initial value (defined like <code>int bar;</code>).</p></li><li><p><code>.rodata</code>: this section contains constant data (mostly strings or byte arrays). For example, if we use a string literal in the code (for example, for <code>printf</code> or some error message), it will be stored here. Note, that <code>.rodata</code> is missing from the output above as we didn't use any string literals or constant byte arrays in <code>obj.c</code>.</p></li><li><p><code>.symtab</code>: this section contains information about the symbols in the object file: functions, global variables, constants etc. It may also contain information about external symbols the object file needs, like needed functions from the external libraries.</p></li><li><p><code>.strtab</code> and <code>.shstrtab</code>: contain packed strings for the ELF file. Note, that these are not the strings we may define in our source code (those go to the <code>.rodata</code> section). These are the strings describing the names of other ELF structures, like symbols from <code>.symtab</code> or even section names from the table above. ELF binary format aims to make its structures compact and of a fixed size, so all strings are stored in one place and the respective data structures just reference them as an offset in either <code>.shstrtab</code> or <code>.strtab</code> sections instead of storing the full string locally.</p></li></ul>
    <div>
      <h4>The <code>.symtab</code> section</h4>
      <a href="#the-symtab-section">
        
      </a>
    </div>
    <p>At this point, we know that the code we want to import and execute is located in the <code>obj.o</code>'s <code>.text</code> section. But we have two functions, <code>add5</code> and <code>add10</code>, remember? At this level the <code>.text</code> section is just a byte blob - how do we know where each of these functions is located? This is where the <code>.symtab</code> (the "symbol table") comes in handy. It is so important that it has its own dedicated parameter in <a href="https://man7.org/linux/man-pages/man1/readelf.1.html">readelf</a>:</p>
            <pre><code>$ readelf --symbols obj.o

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS obj.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     8: 0000000000000000    15 FUNC    GLOBAL DEFAULT    1 add5
     9: 000000000000000f    15 FUNC    GLOBAL DEFAULT    1 add10</code></pre>
            <p>Let's ignore the other entries for now and just focus on the last two lines, because they conveniently have <code>add5</code> and <code>add10</code> as their symbol names. And indeed, this is the info about our functions. Apart from the names, the symbol table provides us with some additional metadata:</p><ul><li><p>The <code>Ndx</code> column tells us the index of the section, where the symbol is located. We can cross-check it with the section table above and confirm that indeed these functions are located in <code>.text</code> (section with the index <code>1</code>).</p></li><li><p><code>Type</code> being set to <code>FUNC</code> confirms that these are indeed functions.</p></li><li><p><code>Size</code> tells us the size of each function, but this information is not very useful in our context. The same goes for <code>Bind</code> and <code>Vis</code>.</p></li><li><p>Probably the most useful piece of information is <code>Value</code>. The name is misleading, because it is actually an offset from the start of the containing section in this context. That is, the <code>add5</code> function starts just from the beginning of <code>.text</code> and <code>add10</code> is located from 15th byte and onwards.</p></li></ul><p>So now we have all the pieces on how to parse an ELF file and find the functions we need.</p>
    <div>
      <h3>Finding and executing a function from an object file</h3>
      <a href="#finding-and-executing-a-function-from-an-object-file">
        
      </a>
    </div>
    <p>Given what we have learned so far, let's define a plan on how to proceed to import and execute a function from an object file:</p><ol><li><p>Find the ELF sections table and <code>.shstrtab</code> section (we need <code>.shstrtab</code> later to lookup sections in the section table by name).</p></li><li><p>Find the <code>.symtab</code> and <code>.strtab</code> sections (we need <code>.strtab</code> to lookup symbols by name in <code>.symtab</code>).</p></li><li><p>Find the <code>.text</code> section and copy it into RAM with executable permissions.</p></li><li><p>Find <code>add5</code> and <code>add10</code> function offsets from the <code>.symtab</code>.</p></li><li><p>Execute <code>add5</code> and <code>add10</code> functions.</p></li></ol><p>Let's start by adding some more global variables and implementing the <code>parse_obj</code> function:</p><p><i>loader.c</i>:</p>
            <pre><code>...

/* sections table */
static const Elf64_Shdr *sections;
static const char *shstrtab = NULL;

/* symbols table */
static const Elf64_Sym *symbols;
/* number of entries in the symbols table */
static int num_symbols;
static const char *strtab = NULL;

...

static void parse_obj(void)
{
    /* the sections table offset is encoded in the ELF header */
    sections = (const Elf64_Shdr *)(obj.base + obj.hdr-&gt;e_shoff);
    /* the index of `.shstrtab` in the sections table is encoded in the ELF header
     * so we can find it without actually using a name lookup
     */
    shstrtab = (const char *)(obj.base + sections[obj.hdr-&gt;e_shstrndx].sh_offset);

...
}

...</code></pre>
            <p>Now that we have references to both the sections table and the <code>.shstrtab</code> section, we can lookup other sections by their name. Let's create a helper function for that:</p><p><i>loader.c</i>:</p>
            <pre><code>...

static const Elf64_Shdr *lookup_section(const char *name)
{
    size_t name_len = strlen(name);

    /* number of entries in the sections table is encoded in the ELF header */
    for (Elf64_Half i = 0; i &lt; obj.hdr-&gt;e_shnum; i++) {
        /* sections table entry does not contain the string name of the section
         * instead, the `sh_name` parameter is an offset in the `.shstrtab`
         * section, which points to a string name
         */
        const char *section_name = shstrtab + sections[i].sh_name;
        size_t section_name_len = strlen(section_name);

        if (name_len == section_name_len &amp;&amp; !strcmp(name, section_name)) {
            /* we ignore sections with 0 size */
            if (sections[i].sh_size)
                return sections + i;
        }
    }

    return NULL;
}

...</code></pre>
            <p>Using our new helper function, we can now find the <code>.symtab</code> and <code>.strtab</code> sections:</p><p><i>loader.c</i>:</p>
            <pre><code>...

static void parse_obj(void)
{
...

    /* find the `.symtab` entry in the sections table */
    const Elf64_Shdr *symtab_hdr = lookup_section(".symtab");
    if (!symtab_hdr) {
        fputs("Failed to find .symtab\n", stderr);
        exit(ENOEXEC);
    }

    /* the symbols table */
    symbols = (const Elf64_Sym *)(obj.base + symtab_hdr-&gt;sh_offset);
    /* number of entries in the symbols table = table size / entry size */
    num_symbols = symtab_hdr-&gt;sh_size / symtab_hdr-&gt;sh_entsize;

    const Elf64_Shdr *strtab_hdr = lookup_section(".strtab");
    if (!strtab_hdr) {
        fputs("Failed to find .strtab\n", stderr);
        exit(ENOEXEC);
    }

    strtab = (const char *)(obj.base + strtab_hdr-&gt;sh_offset);
    
...
}

...</code></pre>
            <p>Next, let's focus on the <code>.text</code> section. We noted earlier in our plan that it is not enough to just locate the <code>.text</code> section in the object file, like we did with other sections. We would need to copy it over to a different location in RAM with executable permissions. There are several reasons for that, but these are the main ones:</p><ul><li><p>Many CPU architectures either don't allow execution of the machine code, which is <a href="https://en.wikipedia.org/wiki/Page_(computer_memory)">unaligned in memory</a> (4 kilobytes for x86 systems), or they execute it with a performance penalty. However, the <code>.text</code> section in an ELF file is not guaranteed to be positioned at a page aligned offset, because the on-disk version of the ELF file aims to be compact rather than convenient.</p></li><li><p>We may need to modify some bytes in the <code>.text</code> section to perform relocations (we don't need to do it in this case, but will be dealing with relocations in future posts). If, for example, we forget to use the <code>MAP_PRIVATE</code> flag, when mapping the ELF file, our modifications may propagate to the underlying file and corrupt it.</p></li><li><p>Finally, different sections, which are needed at runtime, like <code>.text</code>, <code>.data</code>, <code>.bss</code> and <code>.rodata</code>, require different memory permission bits: the <code>.text</code> section memory needs to be both readable and executable, but not writable (it is considered a bad security practice to have memory both writable and executable). The <code>.data</code> and <code>.bss</code> sections need to be readable and writable to support global variables, but not executable. The <code>.rodata</code> section should be readonly, because its purpose is to hold constant data. To support this, each section must be allocated on a page boundary as we can only set memory permission bits on whole pages and not custom ranges. Therefore, we need to create new, page aligned memory ranges for these sections and copy the data there.</p></li></ul><p>To create a page aligned copy of the <code>.text</code> section, first we actually need to know the page size. Many programs usually just hardcode the page size to 4096 (4 kilobytes), but we shouldn't rely on that. While it's accurate for most x86 systems, other CPU architectures, like arm64, might have a different page size. So hard coding a page size may make our program non-portable. Let's find the page size and store it in another global variable:</p><p><i>loader.c</i>:</p>
            <pre><code>...

static uint64_t page_size;

static inline uint64_t page_align(uint64_t n)
{
    return (n + (page_size - 1)) &amp; ~(page_size - 1);
}

...

static void parse_obj(void)
{
...

    /* get system page size */
    page_size = sysconf(_SC_PAGESIZE);

...
}

...</code></pre>
            <p>Notice, we have also added a convenience function <code>page_align</code>, which will round up the passed in number to the next page aligned boundary. Next, back to the <code>.text</code> section. As a reminder, we need to:</p><ol><li><p>Find the <code>.text</code> section metadata in the sections table.</p></li><li><p>Allocate a chunk of memory to hold the <code>.text</code> section copy.</p></li><li><p>Actually copy the <code>.text</code> section to the newly allocated memory.</p></li><li><p>Make the <code>.text</code> section executable, so we can later call functions from it.</p></li></ol><p>Here is the implementation of the above steps:</p><p><i>loader.c</i>:</p>
            <pre><code>...

/* runtime base address of the imported code */
static uint8_t *text_runtime_base;

...

static void parse_obj(void)
{
...

    /* find the `.text` entry in the sections table */
    const Elf64_Shdr *text_hdr = lookup_section(".text");
    if (!text_hdr) {
        fputs("Failed to find .text\n", stderr);
        exit(ENOEXEC);
    }

    /* allocate memory for `.text` copy rounding it up to whole pages */
    text_runtime_base = mmap(NULL, page_align(text_hdr-&gt;sh_size), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (text_runtime_base == MAP_FAILED) {
        perror("Failed to allocate memory for .text");
        exit(errno);
    }

    /* copy the contents of `.text` section from the ELF file */
    memcpy(text_runtime_base, obj.base + text_hdr-&gt;sh_offset, text_hdr-&gt;sh_size);

    /* make the `.text` copy readonly and executable */
    if (mprotect(text_runtime_base, page_align(text_hdr-&gt;sh_size), PROT_READ | PROT_EXEC)) {
        perror("Failed to make .text executable");
        exit(errno);
    }
}

...</code></pre>
            <p>Now we have all the pieces we need to locate the address of a function. Let's write a helper for it:</p><p><i>loader.c</i>:</p>
            <pre><code>...

static void *lookup_function(const char *name)
{
    size_t name_len = strlen(name);

    /* loop through all the symbols in the symbol table */
    for (int i = 0; i &lt; num_symbols; i++) {
        /* consider only function symbols */
        if (ELF64_ST_TYPE(symbols[i].st_info) == STT_FUNC) {
            /* symbol table entry does not contain the string name of the symbol
             * instead, the `st_name` parameter is an offset in the `.strtab`
             * section, which points to a string name
             */
            const char *function_name = strtab + symbols[i].st_name;
            size_t function_name_len = strlen(function_name);

            if (name_len == function_name_len &amp;&amp; !strcmp(name, function_name)) {
                /* st_value is an offset in bytes of the function from the
                 * beginning of the `.text` section
                 */
                return text_runtime_base + symbols[i].st_value;
            }
        }
    }

    return NULL;
}

...</code></pre>
            <p>And finally we can implement the <code>execute_funcs</code> function to import and execute code from an object file:</p><p><i>loader.c</i>:</p>
            <pre><code>...

static void execute_funcs(void)
{
    /* pointers to imported add5 and add10 functions */
    int (*add5)(int);
    int (*add10)(int);

    add5 = lookup_function("add5");
    if (!add5) {
        fputs("Failed to find add5 function\n", stderr);
        exit(ENOENT);
    }

    puts("Executing add5...");
    printf("add5(%d) = %d\n", 42, add5(42));

    add10 = lookup_function("add10");
    if (!add10) {
        fputs("Failed to find add10 function\n", stderr);
        exit(ENOENT);
    }

    puts("Executing add10...");
    printf("add10(%d) = %d\n", 42, add10(42));
}

...</code></pre>
            <p>Let's compile our loader and make sure it works as expected:</p>
            <pre><code>$ gcc -o loader loader.c 
$ ./loader 
Executing add5...
add5(42) = 47
Executing add10...
add10(42) = 52</code></pre>
            <p>Voila! We have successfully imported code from <code>obj.o</code> and executed it. Of course, the example above is simplified: the code in the object file is self-contained, does not reference any global variables or constants, and does not have any external dependencies. In future posts we will look into more complex code and how to handle such cases.</p>
    <div>
      <h4>Security considerations</h4>
      <a href="#security-considerations">
        
      </a>
    </div>
    <p>Processing external inputs, like parsing an ELF file from the disk above, should be handled with care. The code from <i>loader.c</i> omits a lot of bounds checking and additional ELF integrity checks, when parsing the object file. The code is simplified for the purposes of this post, but most likely not production ready, as it can probably be exploited by specifically crafted malicious inputs. Use it only for educational purposes!</p><p>The complete source code from this post can be found <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-03-obj-file/1">here</a>.</p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <guid isPermaLink="false">73aVJfyo4dMAfJku0Q859K</guid>
            <dc:creator>Ignat Korchagin</dc:creator>
        </item>
        <item>
            <title><![CDATA[Diving into /proc/[pid]/mem]]></title>
            <link>https://blog.cloudflare.com/diving-into-proc-pid-mem/</link>
            <pubDate>Tue, 27 Oct 2020 12:00:00 GMT</pubDate>
            <description><![CDATA[ A few months ago, after reading about Cloudflare doubling its intern class, I quickly dusted off my CV and applied for an internship. Long story short: now, a couple of months later, I found myself staring at Linux kernel code and adding a pretty cool feature to gVisor. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>A few months ago, after reading about <a href="/cloudflare-doubling-size-of-2020-summer-intern-class/">Cloudflare doubling its intern class size</a>, I quickly dusted off my CV and applied for an internship. Long story short: now, a couple of months later, I found myself staring into Linux kernel code and adding a pretty cool feature <a href="https://gvisor.dev/">to gVisor, a Linux container runtime</a>.</p><p>My internship was under the Emerging Technologies and Incubation group on a project involving gVisor. A co-worker contacted my team about not being able to read the debug symbols of stack traces inside the sandbox. For example, when the isolated process crashed, this is what we saw in the logs:</p>
            <pre><code>*** Check failure stack trace: ***
    @     0x7ff5f69e50bd  (unknown)
    @     0x7ff5f69e9c9c  (unknown)
    @     0x7ff5f69e4dbd  (unknown)
    @     0x7ff5f69e55a9  (unknown)
    @     0x5564b27912da  (unknown)
    @     0x7ff5f650ecca  (unknown)
    @     0x5564b27910fa  (unknown)</code></pre>
            <p>Obviously, this wasn't very useful. I eagerly volunteered to fix this stack unwinding code - how hard could it be?</p><p>After some debugging, we found that the logging library used in the project opened <code>/proc/self/mem</code> to look for ELF headers at the start of each memory-mapped region. This was necessary to calculate an offset to find the correct addresses for debug symbols.</p><p>It turns out this mechanism is rather common. The stack unwinding code is often run in weird contexts - like a SIGSEGV handler - so it would not be appropriate to dig over real memory addresses back and forth to read the ELF. This could trigger another SIGSEGV. And SIGSEGV inside a SIGSEGV handler means either termination via the default handler for a segfault or recursing into the same handler again and again (if one sets <code>SA_NODEFER</code>) leading to a stack overflow.</p><p>However, inside gVisor, each call of <code>open()</code> on <code>/proc/self/mem</code> resulted in <code>ENOENT</code>, because the entire <code>/proc/self/mem</code> file was missing. In order to provide a robust sandbox, gVisor has to carefully reimplement the Linux kernel interfaces. This particular <code>/proc</code> file was simply unimplemented in the virtual file system of Sentry, one of gVisor's sandboxing components.<a href="/author/marek-majkowski/">Marek</a> asked the devs on the project chat and got confirmation - they would be happy to accept a patch implementing this file.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4r2jNRjbWTgK866HBQjSKe/2a32421d3b661d496a54dde61721b45b/image1-39.png" />
            
            </figure><p>The easy way out would have been to make a small, local patch to the unwinder behavior, yet I found myself diving into the Linux kernel trying to figure how the <code>mem</code> file worked in an attempt to implement it in Sentry's VFS.</p>
    <div>
      <h2>What does <code>/proc/[pid]/mem</code> do?</h2>
      <a href="#what-does-proc-pid-mem-do">
        
      </a>
    </div>
    <p>The file itself is quite powerful, because it allows raw access to the virtual address space of a process. <a href="https://man7.org/linux/man-pages/man5/proc.5.html">According to manpages</a>, the documented file operations are <code>open()</code>, <code>read()</code> and <code>lseek()</code>. Typical use cases are debugging tasks or dumping process memory.</p>
    <div>
      <h2>Opening the file</h2>
      <a href="#opening-the-file">
        
      </a>
    </div>
    <p>When a process wants to open the file, the kernel does the file permissions check, looks up the associated operations for <code>mem</code> and invokes a method called <code>proc_mem_open</code>. It retrieves the associated task and <a href="https://elixir.bootlin.com/linux/v5.9/source/include/linux/sched/mm.h#L119">calls a method named <code>mm_access</code></a>.</p>
            <pre><code>/*
 * Grab a reference to a task's mm, if it is not already going away
 * and ptrace_may_access with the mode parameter passed to it
 * succeeds.
 */</code></pre>
            <p>Seems relatively straightforward, right? The special thing about <code>mm_access</code> is that it verifies the permissions the current task has regarding the task to which the memory belongs. If the current task and target task do not share the same memory manager, the kernel <a href="https://elixir.bootlin.com/linux/v5.9/source/kernel/ptrace.c#L293">invokes a method named <code>__ptrace_may_access</code></a>.</p>
            <pre><code>/*
 * May we inspect the given task?
 * This check is used both for attaching with ptrace
 * and for allowing access to sensitive information in /proc.
 *
 * ptrace_attach denies several cases that /proc allows
 * because setting up the necessary parent/child relationship
 * or halting the specified task is impossible.
 *
 */</code></pre>
            <p><a href="https://man7.org/linux/man-pages/man5/proc.5.html">According to the manpages</a>, a process which would like to read from an unrelated <code>/proc/[pid]/mem</code> file should have access mode <a href="https://man7.org/linux/man-pages/man2/ptrace.2.html"><code>PTRACE_MODE_ATTACH_FSCREDS</code></a>. This check does not verify that a process is attached via <code>PTRACE_ATTACH</code>, but rather if it has the permission to attach with the specified credentials mode.</p>
    <div>
      <h2>Access checks</h2>
      <a href="#access-checks">
        
      </a>
    </div>
    <p>After skimming through the function, you will see that a process is allowed access if the current task belongs to the same thread group as the target task, or denied access (depending on whether <code>PTRACE_MODE_FSCREDS</code> or <code>PTRACE_MODE_REALCREDS</code> is set, we will use either the file-system UID / GID, which is typically the same as the effective UID/GID, or the real UID / GID) if none of the following conditions are met:</p><ul><li><p>the current task's credentials (UID, GID) match up with the credentials (real, effective and saved set-UID/GID) of the target process</p></li><li><p>the current task has <code>CAP_SYS_PTRACE</code> inside the user namespace of the target process</p></li></ul><p>In the next check, access is denied if the current task has neither <code>CAP_SYS_PTRACE</code> inside the user namespace of the target task, nor the target's dumpable attribute is set to <code>SUID_DUMP_USER</code>. <a href="https://man7.org/linux/man-pages/man2/prctl.2.html">The dumpable attribute</a> is typically required to allow producing core dumps.</p><p>After these three checks, we also go through the commoncap Linux Security Module (and other LSMs) to verify our access mode is fine. LSMs you may know are SELinux and AppArmor. The commoncap LSM performs the checks on the basis of effective or permitted process capabilities (depending on the mode being <code>FSCREDS</code> or <code>REALCREDS</code>), allowing access if</p><ul><li><p>the capabilities of the current task are a superset of the capabilities of the target task, or</p></li><li><p>the current task has <code>CAP_SYS_PTRACE</code> in the target task's user namespace</p></li></ul><p>In conclusion, one has access (with only commoncap LSM checks active) if:</p><ul><li><p>the current task is in the same task group as the target task, or</p></li><li><p>the current task has <code>CAP_SYS_PTRACE</code> in the target task's user namespace, or</p></li><li><p>the credentials of the current and target task match up in the given credentials mode, the target task is dumpable, they run in the same user namespace and the target task's capabilities are a subset of the current task's capabilities</p></li></ul><p>I highly recommend reading through the <a href="https://www.man7.org/linux/man-pages/man2/ptrace.2.html">ptrace manpages</a> to dig deeper into the different modes, options and checks.</p>
    <div>
      <h2>Reading from the file</h2>
      <a href="#reading-from-the-file">
        
      </a>
    </div>
    <p>Since all the access checks occur when opening the file, reading from it is quite straightforward. When one invokes <code>read()</code> on a <code>mem</code> file, <a href="https://elixir.bootlin.com/linux/v5.9/source/fs/proc/base.c#L835">it calls up <code>mem_rw</code></a> (which actually can do both reading and writing).</p><p>To avoid using lots of memory, <code>mem_rw</code> performs the copy in a loop and buffers the data in an intermediate page. <code>mem_rw</code> has a hidden superpower, that is, it uses <code>FOLL_FORCE</code> to avoid permission checks on user-owned pages (handling pages marked as non-readable/non-writable readable and writable).</p><p><code>mem_rw</code> has other specialties, such as its error handling. Some interesting cases are:</p><ul><li><p>if the target task has exited after opening the file descriptor, performing <code>read()</code> will always succeed with reading 0 bytes</p></li><li><p>if the initial copy from the target task's memory to the intermediate page fails, it does not always return an error but only if no data has been read</p></li></ul><p>You can also perform <code>lseek</code> on the file excluding <code>SEEK_END</code>.</p>
    <div>
      <h2>How it works in gVisor</h2>
      <a href="#how-it-works-in-gvisor">
        
      </a>
    </div>
    <p>Luckily, gVisor already implemented <code>ptrace_may_access</code> as <code>kernel.task.CanTrace</code>, so one can avoid reimplementing all the ptrace access logic. However, <a href="https://cs.opensource.google/gvisor/gvisor/+/master:pkg/sentry/kernel/ptrace.go;l=105;bpv=0;bpt=1">the implementation in gVisor</a> is less complicated due to the lack of support for <code>PTRACE_MODE_FSCREDS</code> (which is <a href="https://gvisor.dev/issue/260">still an open issue</a>).</p><p>When a new file descriptor is <code>open()</code>ed, the <code>GetFile</code> method of the virtual Inode is invoked, therefore this is where the access check naturally happens. After a successful access check, the <a href="https://pkg.go.dev/gvisor.dev/gvisor/pkg/sentry/fs#File">method returns a <code>fs.File</code></a>. The <code>fs.File</code> implements all the file operations you would expect such as <code>Read()</code> and <code>Write()</code>. gVisor also provides tons of primitives for quickly building a working file structure so that one does not have to reimplement a generic <code>lseek()</code> for example.</p><p>In case a task invokes a <code>Read()</code> call onto the <code>fs.File</code>, the <code>Read</code> method retrieves the memory manager of the file’s Task.<a href="https://pkg.go.dev/gvisor.dev/gvisor/pkg/sentry/mm#MemoryManager">Accessing the task's memory manager</a> is a breeze with comfortable <code>CopyIn</code> and <code>CopyOut</code> methods, with interfaces similar to <code>io.Writer</code> and <code>io.Reader</code>.</p><p>After implementing all of this, we finally got a useful stack trace.</p>
            <pre><code>*** Check failure stack trace: ***
    @     0x7f190c9e70bd  google::LogMessage::Fail()
    @     0x7f190c9ebc9c  google::LogMessage::SendToLog()
    @     0x7f190c9e6dbd  google::LogMessage::Flush()
    @     0x7f190c9e75a9  google::LogMessageFatal::~LogMessageFatal()
    @     0x55d6f718c2da  main
    @     0x7f190c510cca  __libc_start_main
    @     0x55d6f718c0fa  _start</code></pre>
            
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>A comprehensive victory! The <code>/proc/&lt;pid&gt;/mem</code> file is an important mechanism that gives insight into contents of process memory. It is essential to stack unwinders to do their work in case of complicated and unforeseeable failures. Because the process memory contains highly-sensitive information, data access to the file is determined by a complex set of poorly documented rules. With a bit of effort, you can emulate <code>/proc/[PID]/mem</code> inside gVisor’s sandbox, where the process only has access to the subset of procfs that has been implemented by the gVisor authors and, as a result, you can have access to an easily readable stack trace in case of a crash.</p><p><a href="https://github.com/google/gvisor/pull/4060">Now I can't wait to get the PR merged into gVisor.</a></p> ]]></content:encoded>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Linux]]></category>
            <guid isPermaLink="false">5p725SUdmDWpdefn3j7WPy</guid>
            <dc:creator>Lennart Espe</dc:creator>
        </item>
        <item>
            <title><![CDATA[Raking the floods: my intern project using eBPF]]></title>
            <link>https://blog.cloudflare.com/building-rakelimit/</link>
            <pubDate>Fri, 18 Sep 2020 11:00:00 GMT</pubDate>
            <description><![CDATA[ SYN-cookies help mitigating SYN-floods for TCP, but how can we protect services from similar attacks that use UDP? We designed an algorithm and a library to fill this gap, and it’s open source! ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2A1vrFJotzsKPMJxmJdOON/81b2292df9631836d592585149fbef25/rakelimit.jpg" />
            
            </figure><p>Cloudflare has sophisticated DDoS attack mitigation systems with multiple layers to provide defense in depth. Some of these layers analyse large-scale traffic patterns to detect and mitigate attacks. Other layers are more protocol- and application-specific, in order to stop attacks that might be hard to detect from overall traffic patterns. In some cases, the best place to detect and stop an attack is in the service itself.</p><p>During <a href="/cloudflare-doubling-size-of-2020-summer-intern-class/">my internship at Cloudflare</a> this summer, I’ve developed a new open-source framework to help UDP services protect themselves from attacks. This framework incorporates Cloudflare’s experience in running UDP-based services like Spectrum and the 1.1.1.1 resolver.</p>
    <div>
      <h3>Goals of the framework</h3>
      <a href="#goals-of-the-framework">
        
      </a>
    </div>
    <p>First of all, let's discuss what it actually means to protect an UDP service. We want to ensure that an attacker cannot drown out legitimate traffic. To achieve this we identify floods and limit them while leaving legitimate traffic untouched.</p><p>The idea to mitigate such attacks is straight forward: first identify a group of packets that is related to an attack, and then apply a rate limit on this group. Such groups are determined based on the attributes available to us in the packet, such as addresses and ports.</p><p>We then drop packets in the group. We only want to drop as much traffic as necessary to comply with our set rate limit. Completely ignoring a set of packets just because it is slightly above the rate limit is not an option, as it may contain legitimate traffic.</p><p>This ensures both that our service stays responsive but also that legitimate packets experience as little impact as possible.</p><p>While rate limiting is a somewhat straightforward procedure, determining groups is a bit harder, for a number of reasons.</p>
    <div>
      <h3>Finding needles in the haystack</h3>
      <a href="#finding-needles-in-the-haystack">
        
      </a>
    </div>
    <p>The problem in determining groups in packets is that we have barely any context. We consider four things as useful attributes as attack signatures: the source address and port as well as the destination address and port. While that already is not a lot, it gets worse: the source address and port may not even be accurate. Packets can be spoofed, in which case an attacker hides their own address. That means only keeping a rate per source address may not provide much value, as it could simply be spoofed.</p><p>But there is another problem: keeping one rate per address does not scale. When bringing IPv6 into the equation and its <a href="https://www.ripe.net/about-us/press-centre/understanding-ip-addressing#:~:text=For%20IPv4%2C%20this%20pool%20is,basic%20unit%20for%20storing%20information.">whopping address space</a> it becomes clear it’s not going to work.</p><p>To solve these issues we turned to the academic world and found what we were looking for, the problem of <i>Heavy Hitters.</i> <i>Heavy Hitters</i> are elements of a datastream that appear frequently, and can be expressed relative to the overall elements of the stream. We can define for example that an element is considered to be a <i>Heavy Hitter</i> if its frequency exceeds, say, 10% of the overall count. To do so we naively could suggest to simply maintain a counter per element, but due to the space limitations this will not scale. Instead probabilistic algorithms such as a <a href="http://dimacs.rutgers.edu/~graham/pubs/papers/cm-full.pdf">CountMin sketch</a> or the <a href="https://www.cse.ust.hk/~raywong/comp5331/References/EfficientComputationOfFrequentAndTop-kElementsInDataStreams.pdf">SpaceSaving algorithm</a> can be used. These provide an estimated count instead of a precise one, but are capable of doing this with constant memory requirements, and in our case we will just save rates into the CountMin sketch instead of counts. So no matter how many unique elements we have to track, the memory consumption is the same.</p><p>We now have a way of finding the needle in the haystack, and it does have constant memory requirements, solving our problem. However, reality isn’t that simple. What if an attack is not just originating from a single port but many? Or what if a reflection attack is hitting our service, resulting in random source addresses but a single source port? Maybe a full /24 subnet is sending us a flood? We can not just keep a rate per combination we see, as it would ignore all these patterns.</p>
    <div>
      <h3>Grouping the groups: How to organize packets</h3>
      <a href="#grouping-the-groups-how-to-organize-packets">
        
      </a>
    </div>
    <p>Luckily the academic world has us covered again, with the concept of <i>Hierarchical Heavy Hitters.</i> It extends the <i>Heavy Hitter</i> concept by using the underlying hierarchy in the elements of the stream. For example, an IP address can be naturally grouped into several subnets:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7IPwA0tN0c6pOFMK5B2AT8/9101b971c3a69277a79b03a473e936ec/0B429C7C-869C-4517-9B95-C90600943486.png" />
            
            </figure><p>In this case we defined that we consider the fully-specified address, the /24 subnet and the /0 wildcard. We start at the left with the fully specified address, and each step walking towards the top we consider less information from it. We call these less-specific addresses generalisations, and measure how specific a generalisation is by assigning a level. In our example, the address 192.0.2.123 is at level 0, while 192.0.2.0/24 is at level 1, etc.</p><p>If we want to create a structure which can hold this information for every packet, it could look like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5lqAfAxLDrXwIgtQJ1Hm0/b37c644442d0f0e91ef38725929cb5ef/F4B2AA4A-4868-4E56-891A-6C19E0CACBA4.png" />
            
            </figure><p>We maintain a CountMin-sketch per subnet and then apply Heavy Hitters. When a new packet arrives and we need to determine if it is allowed to pass we simply check the rates of the corresponding elements in every node. If no rate exceeds the rate limit that we set, e.g. 25 packets per second (<i>pps</i>), it is allowed to pass.</p><p>The structure could now keep track of a single attribute, but we would waste a lot of context around packets! So instead of letting it go to waste, we use the two-dimensional approach for addresses proposed in the paper <a href="https://arxiv.org/abs/1102.5540">Hierarchical Heavy Hitters with SpaceSaving algorithm</a>, and extend it further to also incorporate ports into our structure. Ports do not have a natural hierarchy such as addresses, so they can only be in two states: either <i>specified</i> (e.g. 8080) or <i>wildcard</i>.</p><p>Now our structure looks like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/EowltLQdppI0JmX9TtKFU/f20d98ae5469b518897e4d9c621f5ab9/5D94D469-B2F3-48CD-918C-202B8C426B19.png" />
            
            </figure><p>Now let’s talk about the algorithm we use to traverse the structure and determine if a packet should be allowed to pass. The paper <i>Hierarchical Heavy Hitters with SpaceSaving algorithm</i> provides two methods that can be used on the data structure: one that updates elements and increases their counters, and one that provides all elements that currently are <i>Heavy Hitters</i>. This is actually not necessary for our use-case, as we are only interested if the element, or packet, we are looking at right now would be a <i>Heavy Hitter</i> to decide if it can pass or not.</p><p>Secondly, our goal is to prevent any Heavy Hitters from passing, thus leaving the structure with no _Heavy Hitter_s whatsoever. This is a great property, as it allows us to simplify the algorithm substantially, and it looks like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4gXxGnRtWTU6jorXm6538i/4c9c62fc80edffcf2ac2a4b2e2918292/A41D5CB1-5C6B-4378-B496-7B38E22DE0F7.png" />
            
            </figure><p>As you may notice, we update every node of a level and maintain the maximum rate we see. After each level we calculate a probability that determines if a packet should be passed to the next level, based on the maximum rate we saw on that level and a set rate limit. Each node essentially filters the traffic for the following, less specific level.</p><p>I actually left out a small detail: a packet is not dropped if any rate exceeds the limit, but instead is kept with the probability <i>rate limit</i>/<i>maximum rate seen</i>. The reason is that if we just drop all packets if the rates exceed the limit, we would drop the whole traffic, not just a subset to make it comply with our set rate limit.</p><p>Since we now still update more specific nodes even if a node reaches a rate limit, the rate limit will converge towards the underlying pattern of the attack as much as possible. That means other traffic will be impacted as minimally as possible, and that with no manual intervention whatsoever!</p>
    <div>
      <h3>BPF to the rescue: building a Go library</h3>
      <a href="#bpf-to-the-rescue-building-a-go-library">
        
      </a>
    </div>
    <p>As we want to use this algorithm to mitigate floods, we need to spend as little computation and overhead as possible before we decide if a packet should be dropped or not. As so often, we looked into the BPF toolbox and found what we need: <i>Socketfilters</i>. As our colleague Marek put it: <a href="/cloudflare-architecture-and-how-bpf-eats-the-world/">“It seems, no matter the question - BPF is the answer.”</a>.</p><p><i>Socketfilters</i> are pieces of code that can be attached to a single socket and get executed before a packet will be passed from kernel to userspace. This is ideal for a number of reasons. First, when the kernel runs the socket filter code, it gives it all the information from the packet we need, and other mitigations such as firewalls have been executed. Second the code is executed <i>per socket</i>, so every application can activate it as needed, and also set appropriate rate limits. It may even use different rate limits for different sockets. The third reason is privileges: we do not need to be root to attach the code to a socket. We can execute code in the kernel as a normal user!</p><p>BPF also has a number of limitations which have been already covered on this blog in the past, so we will focus on one that’s specific to our project: floating-point numbers.</p><p>To calculate rates we need floating-point numbers to provide an accurate estimate. BPF, and the whole kernel for that matter, does not support these. Instead we implemented a fixed-point representation, which uses a part of the available bits for the fractional part of a rational number and the remaining bits for the integer part. This allows us to represent floats within a certain range, but there is a catch when doing arithmetic: while subtraction and addition of two fixed-points work well, multiplication and division requires double the number of bits to ensure there will not be any loss in precision. As we use 64 bits for our fixed-point values, there is no larger data type available to ensure this does not happen. Instead of calculating the result with exact precision, we convert one of the arguments into an integer. That results in the loss of the fractional part, but as we deal with large rates that does not pose any issue, and helps us to work around the bit limitation as intermediate results fit into the available 64 bits. Whenever fixed-point arithmetic is necessary the precision of intermediate results has to be carefully considered.</p><p>There are many more details to the implementation, but instead of covering every single detail in this blog post lets just look at the code.</p><p>We open sourced rakelimit over on Github at <a href="https://github.com/cloudflare/rakelimit">cloudflare/rakelimit</a>! It is a full-blown Go library that can be enabled on any UDP socket, and is easy to configure.</p><p>The development is still in early stages and this is a first prototype, but we are excited to continue and push the development with the community! And if you still can’t get enough, look at our talk from this year's <a href="https://linuxplumbersconf.org/event/7/contributions/677/">Linux Plumbers Conference</a>.</p> ]]></content:encoded>
            <category><![CDATA[eBPF]]></category>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[UDP]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">5v73ZaARMTKhq3UGeDWoMn</guid>
            <dc:creator>Jonas Otten</dc:creator>
        </item>
        <item>
            <title><![CDATA[When Bloom filters don't bloom]]></title>
            <link>https://blog.cloudflare.com/when-bloom-filters-dont-bloom/</link>
            <pubDate>Mon, 02 Mar 2020 13:00:00 GMT</pubDate>
            <description><![CDATA[ Last month finally I had an opportunity to use Bloom filters. I became fascinated with the promise of this data structure, but I quickly realized it had some drawbacks. This blog post is the tale of my brief love affair with Bloom filters. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4bQ9cbvVLCJTUntwCHSGSp/570583980831b19e4da88411fdff5eda/bloom-filter_2x.png" />
            
            </figure><p>I've known about <a href="https://en.wikipedia.org/wiki/Bloom_filter">Bloom filters</a> (named after Burton Bloom) since university, but I haven't had an opportunity to use them in anger. Last month this changed - I became fascinated with the promise of this data structure, but I quickly realized it had some drawbacks. This blog post is the tale of my brief love affair with Bloom filters.</p><p>While doing research about <a href="/the-root-cause-of-large-ddos-ip-spoofing/">IP spoofing</a>, I needed to examine whether the source IP addresses extracted from packets reaching our servers were legitimate, depending on the geographical location of our data centers. For example, source IPs belonging to a legitimate Italian ISP should not arrive in a Brazilian datacenter. This problem might sound simple, but in the ever-evolving landscape of the internet this is far from easy. Suffice it to say I ended up with many large text files with data like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4EyhhPLD0IymvVMr3R8pMz/2c30f18b77fdee9184c438f80e94781b/Screenshot-from-2020-03-01-23-57-10.png" />
            
            </figure><p>This reads as: the IP 192.0.2.1 was recorded reaching Cloudflare data center number 107 with a legitimate request. This data came from many sources, including our active and passive probes, logs of certain domains we own (like cloudflare.com), public sources (like BGP table), etc. The same line would usually be repeated across multiple files.</p><p>I ended up with a gigantic collection of data of this kind. At some point I counted 1 billion lines across all the harvested sources. I usually write bash scripts to pre-process the inputs, but at this scale this approach wasn't working. For example, removing duplicates from this tiny file of a meager 600MiB and 40M lines, took... about an eternity:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7lzqpR8gHJRr6XC4fbcepJ/91185ef0b6036ecd484bd791f5a72651/Screenshot-from-2020-03-01-23-25-19a.png" />
            
            </figure><p>Enough to say that deduplicating lines using the usual bash commands like 'sort' in various configurations (see '--parallel', '--buffer-size' and '--unique') was not optimal for such a large data set.</p>
    <div>
      <h2>Bloom filters to the rescue</h2>
      <a href="#bloom-filters-to-the-rescue">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/vR5EB9TdKmVJDjStuvpwL/fe51959f24694cc5c072f3263aa42ab0/Bloom_filter.png" />
            
            </figure><p><a href="https://en.wikipedia.org/wiki/Bloom_filter#/media/File:Bloom_filter.svg">Image</a> by <a href="https://commons.wikimedia.org/wiki/User:David_Eppstein">David Eppstein</a> Public Domain</p><p>Then I had a brainwave - it's not necessary to sort the lines! I just need to remove duplicated lines - using some kind of "set" data structure should be much faster. Furthermore, I roughly know the cardinality of the input file (number of unique lines), and I can live with some data points being lost - using a probabilistic data structure is fine!</p><p>Bloom-filters are a perfect fit!</p><p>While you should go and read <a href="https://en.wikipedia.org/wiki/Bloom_filter#Algorithm_description">Wikipedia on Bloom Filters</a>, here is how I look at this data structure.</p><p>How would you implement a "<a href="https://en.wikipedia.org/wiki/Set_(abstract_data_type)">set</a>"? Given a perfect hash function, and infinite memory, we could just create an infinite bit array and set a bit number 'hash(item)' for each item we encounter. This would give us a perfect "set" data structure. Right? Trivial. Sadly, hash functions have collisions and infinite memory doesn't exist, so we have to compromise in our reality. But we can calculate and manage the probability of collisions. For example, imagine we have a good hash function, and 128GiB of memory. We can calculate the probability of the second item added to the bit array colliding would be 1 in 1099511627776. The probability of collision when adding more items worsens as we fill up the bit array.</p><p>Furthermore, we could use more than one hash function, and end up with a denser bit array. This is exactly what Bloom filters optimize for. A Bloom filter is a bunch of math on top of the four variables:</p><ul><li><p>'n' - The number of input elements (cardinality)</p></li><li><p>'m' - Memory used by the bit-array</p></li><li><p>'k' - Number of hash functions counted for each input</p></li><li><p>'p' - Probability of a false positive match</p></li></ul><p>Given the 'n' input cardinality and the 'p' desired probability of false positive, the Bloom filter math returns the 'm' memory required and 'k' number of hash functions needed.</p><p>Check out this excellent visualization by Thomas Hurst showing how parameters influence each other:</p><ul><li><p><a href="https://hur.st/bloomfilter/">https://hur.st/bloomfilter/</a></p></li></ul>
    <div>
      <h2>mmuniq-bloom</h2>
      <a href="#mmuniq-bloom">
        
      </a>
    </div>
    <p>Guided by this intuition, I set out on a journey to add a new tool to my toolbox - 'mmuniq-bloom', a probabilistic tool that, given input on STDIN, returns only unique lines on STDOUT, hopefully much faster than 'sort' + 'uniq' combo!</p><p>Here it is:</p><ul><li><p><a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2020-02-mmuniq/mmuniq-bloom.c">'mmuniq-bloom.c'</a></p></li></ul><p>For simplicity and speed I designed 'mmuniq-bloom' with a couple of assumptions. First, unless otherwise instructed, it uses 8 hash functions k=8. This seems to be a close to optimal number for the data sizes I'm working with, and the hash function can quickly output 8 decent hashes. Then we align 'm', number of bits in the bit array, to be a power of two. This is to avoid the pricey % modulo operation, which compiles down to slow assembly 'div'. With power-of-two sizes we can just do bitwise AND. (For a fun read, see <a href="https://stackoverflow.com/questions/41183935/why-does-gcc-use-multiplication-by-a-strange-number-in-implementing-integer-divi">how compilers can optimize some divisions by using multiplication by a magic constant</a>.)</p><p>We can now run it against the same data file we used before:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7eWA2sCxdTwbHW0JVE4dLm/ffffd6f6823305f41a15d0091d1acaef/image11.png" />
            
            </figure><p>Oh, this is so much better! 12 seconds is much more manageable than 2 minutes before. But hold on... The program is using an optimized data structure, relatively limited memory footprint, optimized line-parsing and good output buffering... 12 seconds is still eternity compared to 'wc -l' tool:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/10yS38GPKuBTqMMd4ZJVSe/199b9ceea61eb91700012362ef92e0ab/image5.png" />
            
            </figure><p>What is going on? I understand that counting lines by 'wc' is <i>easier</i> than figuring out unique lines, but is it really worth the 26x difference? Where does all the CPU in 'mmuniq-bloom' go?</p><p>It must be my hash function. 'wc' doesn't need to spend all this CPU performing all this strange math for each of the 40M lines on input. I'm using a pretty non-trivial 'siphash24' hash function, so it surely burns the CPU, right? Let's check by running the code computing hash function but <i>not</i> doing any Bloom filter operations:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4cmgeZbT0nJNh9bwRC4gEH/b5a71c8c573d506f20f6b6bc01173028/image2.png" />
            
            </figure><p>This is strange. Counting the hash function indeed costs about 2s, but the program took 12s in the previous run. The Bloom filter alone takes 10 seconds? How is that possible? It's such a simple data structure...</p>
    <div>
      <h2>A secret weapon - a profiler</h2>
      <a href="#a-secret-weapon-a-profiler">
        
      </a>
    </div>
    <p>It was time to use a proper tool for the task - let's fire up a profiler and see where the CPU goes. First, let's fire an 'strace' to confirm we are not running any unexpected syscalls:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/29N25pGnOTso9WBxn4SckO/4a8bbb0dccf4dfb5fd2a248625d29bd9/image14.png" />
            
            </figure><p>Everything looks good. The 10 calls to 'mmap' each taking 4ms (3971 us) is intriguing, but it's fine. We pre-populate memory up front with 'MAP_POPULATE' to save on page faults later.</p><p>What is the next step? Of course Linux's 'perf'!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/632ygHAtmgUaNH18WsUPAG/b9f3990786d96bf84b2bc28d5a55f0e3/image10.png" />
            
            </figure><p>Then we can see the results:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/61GXvk0ujwFsP0vEDyrD6c/ab4ec96b0e748f5dd8e6e496d1b499b4/image6.png" />
            
            </figure><p>Right, so we indeed burn 87.2% of cycles in our hot code. Let's see where exactly. Doing 'perf annotate process_line --source' quickly shows something I didn't expect.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3i10E5RjlO3vvJTuA751wv/da7db1a7614e3936218206689767e752/image3.png" />
            
            </figure><p>You can see 26.90% of CPU burned in the 'mov', but that's not all of it! The compiler correctly inlined the function, and unrolled the loop 8-fold. Summed up that 'mov' or 'uint64_t v = *p' line adds up to a great majority of cycles!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1sTjVPwEz6BILccJz8pdDa/2e3435805a1e092460dcb916f4d6ecb2/image4.png" />
            
            </figure><p>Clearly 'perf' must be mistaken, how can such a simple line cost so much? We can repeat the benchmark with any other profiler and it will show us the same problem. For example, I like using 'google-perftools' with kcachegrind since they emit eye-candy charts:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7fWWh8EZelfOMfwA5XMT16/4ded280402c936f2a6f67e2930115f5e/Screenshot-from-2020-03-02-00-08-23.png" />
            
            </figure><p>The rendered result looks like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2p5hkIX3zVAO7IFFWEVZuF/14f1f9505b91e15c904dab7309a11907/image13.png" />
            
            </figure><p>Allow me to summarise what we found so far.</p><p>The generic 'wc' tool takes 0.45s CPU time to process 600MiB file. Our optimized 'mmuniq-bloom' tool takes 12 seconds. CPU is burned on one 'mov' instruction, dereferencing memory....</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1eRwMPBq6BEAyWB0g10EDo/3802664ab1b47d94b96845f487338a08/6784957048_4661ea7dfc_c.jpg" />
            
            </figure><p><a href="https://flickr.com/photos/jonicdao/6784957048">Image</a> by <a href="https://flickr.com/photos/jonicdao/">Jose Nicdao</a> CC BY/2.0</p><p>Oh! I how could I have forgotten. Random memory access <i>is</i> slow! It's very, very, very slow!</p><p>According to the general rule <a href="http://highscalability.com/blog/2011/1/26/google-pro-tip-use-back-of-the-envelope-calculations-to-choo.html">"latency numbers every programmer should know about"</a>, one RAM fetch is about 100ns. Let's do the math: 40 million lines, 8 hashes counted for each line. Since our Bloom filter is 128MiB, on <a href="/gen-x-performance-tuning/">our older hardware</a> it doesn't fit into L3 cache! The hashes are uniformly distributed across the large memory range - each hash generates a memory miss. Adding it together that's...</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/ORPcRAqG2H2xqeEEdGbmh/ef6968c82bfe0aa44706a4f36e59bb1c/Screenshot-from-2020-03-02-00-34-29.png" />
            
            </figure><p>That suggests 32 seconds burned just on memory fetches. The real program is faster, taking only 12s. This is because, although the Bloom filter data does not completely fit into L3 cache, it still gets some benefit from caching. It's easy to see with 'perf stat -d':</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7pgVS7zKpVhueO7rAhQDRI/5145db41e7b06f5875d1da4adfa92142/image9.png" />
            
            </figure><p>Right, so we should have had at least 320M LLC-load-misses, but we had only 280M. This still doesn't explain why the program was running only 12 seconds. But it doesn't really matter. What matters is that the number of cache misses is a real problem and we can only fix it by reducing the number of memory accesses. Let's try tuning Bloom filter to use only one hash function:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/30BFuINOqYvVgCCdYXCzUB/0893742e7bc41b923af6e67f53629049/image12.png" />
            
            </figure><p>Ouch! That really hurt! The Bloom filter required 64 GiB of memory to get our desired false positive probability ratio of 1-error-per-10k-lines. This is terrible!</p><p>Also, it doesn't seem like we improved much. It took the OS 22 seconds to prepare memory for us, but we still burned 11 seconds in userspace. I guess this time any benefits from hitting memory less often were offset by lower cache-hit probability due to drastically increased memory size. In previous runs we required only 128MiB for the Bloom filter!</p>
    <div>
      <h2>Dumping Bloom filters altogether</h2>
      <a href="#dumping-bloom-filters-altogether">
        
      </a>
    </div>
    <p>This is getting ridiculous. To get the same false positive guarantees we either must use many hashes in Bloom filter (like 8) and therefore many memory operations, or we can have 1 hash function, but enormous memory requirements.</p><p>We aren't really constrained by available memory, instead we want to optimize for reduced memory accesses. All we need is a data structure that requires at most 1 memory miss per item, and use less than 64 Gigs of RAM...</p><p>While we could think of more sophisticated data structures like <a href="https://en.wikipedia.org/wiki/Cuckoo_filter">Cuckoo filter</a>, maybe we can be simpler. How about a good old simple hash table with linear probing?</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6PVz5hd2DqyiraxgMJ7KIp/37706f6ffcc1cd52f544d626381deaeb/linear-probing.png" />
            
            </figure><p><a href="https://www.sysadmins.lv/blog-en/array-search-hash-tables-behind-the-scenes.aspx">Image</a> by <a href="https://www.sysadmins.lv/about.aspx">Vadims Podāns</a></p>
    <div>
      <h2>Welcome mmuniq-hash</h2>
      <a href="#welcome-mmuniq-hash">
        
      </a>
    </div>
    <p>Here you can find a tweaked version of mmuniq-bloom, but using hash table:</p><ul><li><p><a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2020-02-mmuniq/mmuniq-hash.c">'mmuniq-hash.c'</a></p></li></ul><p>Instead of storing bits as for the Bloom-filter, we are now storing 64-bit hashes from the <a href="https://idea.popcount.org/2013-01-24-siphash/">'siphash24' function</a>. This gives us much stronger probability guarantees, with probability of false positives much better than one error in 10k lines.</p><p>Let's do the math. Adding a new item to a hash table containing, say 40M, entries has '40M/2^64' chances of hitting a hash collision. This is about one in 461 billion - a reasonably low probability. But we are not adding one item to a pre-filled set! Instead we are adding 40M lines to the initially empty set. As per <a href="https://en.wikipedia.org/wiki/Birthday_problem">birthday paradox</a> this has much higher chances of hitting a collision at some point. A decent approximation is 'n^2/2m', which in our case is '(40M<sup>2)/(2*(2</sup>64))'. This is a chance of one in 23000. In other words, assuming we are using good hash function, every one in 23 thousand random sets of 40M items, will have a hash collision. This practical chance of hitting a collision is non-negligible, but it's still better than a Bloom filter and totally acceptable for my use case.</p><p>The hash table code runs faster, has better memory access patterns and better false positive probability than the Bloom filter approach.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7i3tnYhlVqJ7NEfutgywVD/dafe27be80727cd61533f548457bc4a3/image7.png" />
            
            </figure><p>Don't be scared about the "hash conflicts" line, it just indicates how full the hash table was. We are using linear probing, so when a bucket is already used, we just pick up the next empty bucket. In our case we had to skip over 0.7 buckets on average to find an empty slot in the table. This is fine and, since we iterate over the buckets in linear order, we can expect the memory to be nicely prefetched.</p><p>From the previous exercise we know our hash function takes about 2 seconds of this. Therefore, it's fair to say 40M memory hits take around 4 seconds.</p>
    <div>
      <h2>Lessons learned</h2>
      <a href="#lessons-learned">
        
      </a>
    </div>
    <p>Modern CPUs are really good at sequential memory access when it's possible to predict memory fetch patterns (see <a href="https://en.wikipedia.org/wiki/Cache_prefetching#Methods_of_hardware_prefetching">Cache prefetching</a>). Random memory access on the other hand is very costly.</p><p>Advanced data structures are very interesting, but beware. Modern computers require cache-optimized algorithms. When working with large datasets, not fitting L3, prefer optimizing for reduced number loads, over optimizing the amount of memory used.</p><p>I guess it's fair to say that Bloom filters are great, as long as they fit into the L3 cache. The moment this assumption is broken, they are terrible. This is not news, Bloom filters optimize for memory usage, not for memory access. For example, see <a href="https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf">the Cuckoo Filters paper</a>.</p><p>Another thing is the ever-lasting discussion about hash functions. Frankly - in most cases it doesn't matter. The cost of counting even complex hash functions like 'siphash24' is small compared to the cost of random memory access. In our case simplifying the hash function will bring only small benefits. The CPU time is simply spent somewhere else - waiting for memory!</p><p>One colleague often says: "You can assume modern CPUs are infinitely fast. They run at infinite speed until they <a href="http://www.di-srv.unisa.it/~vitsca/SC-2011/DesignPrinciplesMulticoreProcessors/Wulf1995.pdf">hit the memory wall</a>".</p><p>Finally, don't follow my mistakes - everyone should start profiling with 'perf stat -d' and look at the "Instructions per cycle" (IPC) counter. If it's below 1, it generally means the program is stuck on waiting for memory. Values above 2 would be great, it would mean the workload is mostly CPU-bound. Sadly, I'm yet to see high values in the workloads I'm dealing with...</p>
    <div>
      <h2>Improved mmuniq</h2>
      <a href="#improved-mmuniq">
        
      </a>
    </div>
    <p>With the help of my colleagues I've prepared a further improved version of the 'mmuniq' hash table based tool. See the code:</p><ul><li><p><a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2020-02-mmuniq/mmuniq.c">'mmuniq.c'</a></p></li></ul><p>It is able to dynamically resize the hash table, to support inputs of unknown cardinality. Then, by using batching, it can effectively use the 'prefetch' CPU hint, speeding up the program by 35-40%. Beware, sprinkling the code with 'prefetch' rarely works. Instead, I specifically changed the flow of algorithms to take advantage of this instruction. With all the improvements I got the run time down to 2.1 seconds:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6cnwoob2q1SVG27I7zqals/87621808c31bd4707e08e816a4a58480/Screenshot-from-2020-03-01-23-52-18.png" />
            
            </figure>
    <div>
      <h2>The end</h2>
      <a href="#the-end">
        
      </a>
    </div>
    <p>Writing this basic tool which tries to be faster than 'sort | uniq' combo revealed some hidden gems of modern computing. With a bit of work we were able to speed it up from more than two minutes to 2 seconds. During this journey we learned about random memory access latency, and the power of cache friendly data structures. Fancy data structures are exciting, but in practice reducing random memory loads often brings better results.</p> ]]></content:encoded>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Optimization]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Tools]]></category>
            <guid isPermaLink="false">3CPWTXjZJXbtWVNIawBWsd</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
        <item>
            <title><![CDATA[Join Cloudflare & Moz at our next meetup, Serverless in Seattle!]]></title>
            <link>https://blog.cloudflare.com/join-cloudflare-moz-at-our-next-meetup-serverless-in-seattle/</link>
            <pubDate>Mon, 24 Jun 2019 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare is organizing a meetup in Seattle on Tuesday, June 25th and we hope you can join. We’ll be bringing together members of the developers community and Cloudflare users for an evening of discussion about serverless compute and the infinite number of use cases for deploying code at the edge.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Photo by <a href="https://unsplash.com/@jetcityninja?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">oakie</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></p><p>Cloudflare is organizing a <a href="https://www.cloudflare.com/events/seattle-customer-meetup-june2019/">meetup in Seattle</a> on Tuesday, June 25th and we hope you can join. We’ll be bringing together members of the developers community and Cloudflare users for an evening of discussion about serverless compute and the infinite number of use cases for deploying code at the edge.</p><p>To kick things off, our guest speaker <a href="https://moz.com/about/team/devin">Devin Ellis</a> will share how <a href="https://moz.com/"><b>Moz</b></a> <b>uses Cloudflare</b> <a href="https://www.cloudflare.com/products/cloudflare-workers/"><b>Workers</b></a> <b>to reduce time to first byte 30-70% by</b> <a href="https://www.cloudflare.com/learning/cdn/caching-static-and-dynamic-content/"><b>caching dynamic content</b></a> <b>at the edge.</b> Kirk Schwenkler, Solutions Engineering Lead at Cloudflare, will facilitate this discussion and share his perspective on how to grow and secure businesses at scale.</p><p>Next up, Developer Advocate <a href="https://dev.to/signalnerve">Kristian Freeman</a> will take you through a live demo of Workers and highlight <a href="https://dev.to/cloudflareworkers/a-brief-guide-to-what-s-new-with-cloudflare-workers-di8">new features</a> of the platform. This will be an interactive session where you can try out Workers for free and develop your own applications using our new command-line tool.</p><p>Food and drinks will be served til close so grab your laptop and a friend and come on by!</p><p><a href="https://www.cloudflare.com/events/seattle-customer-meetup-june2019/"><b>View Event Details &amp; Register Here</b></a></p><p>Agenda:</p><p>

<ul>
    <li><strong>5:00 pm</strong> Doors open, food and drinks
    </li><li><strong>5:30 pm</strong> Customer use case by Devin and Kirk
	</li><li><strong>6:00 pm</strong> Workers deep dive with Kristian
    </li><li><strong>6:30 - 8:30 pm</strong> Networking, food and drinks    
</li></ul>


</p> ]]></content:encoded>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Cloudflare Workers KV]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Cloudflare Meetups]]></category>
            <category><![CDATA[MeetUp]]></category>
            <category><![CDATA[Events]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">kiRSgU1smLNWrHFcDBuId</guid>
            <dc:creator>Giuliana DeAngelis</dc:creator>
        </item>
        <item>
            <title><![CDATA[Inside the Entropy]]></title>
            <link>https://blog.cloudflare.com/inside-the-entropy/</link>
            <pubDate>Mon, 17 Jun 2019 13:00:00 GMT</pubDate>
            <description><![CDATA[ Generating random outcomes is an essential part of everyday life; from lottery drawings and constructing competitions, to performing deep cryptographic computations.  ]]></description>
            <content:encoded><![CDATA[ <p></p><blockquote><p>Randomness, randomness everywhere;Nor any verifiable entropy.</p></blockquote><p>Generating random outcomes is an essential part of everyday life; from lottery drawings and constructing competitions, to performing deep cryptographic computations. To use randomness, we must have some way to 'sample' it. This requires interpreting some natural phenomenon (such as a fair dice roll) as an event that generates some random output. From a computing perspective, we interpret random outputs as bytes that we can then use in algorithms (such as drawing a lottery) to achieve the functionality that we want.</p><p>The sampling of randomness securely and efficiently is a critical component of all modern computing systems. For example, nearly all public-key cryptography relies on the fact that algorithms can be seeded with bytes generated from genuinely random outcomes.</p><p>In scientific experiments, a random sampling of results is necessary to ensure that data collection measurements are not skewed. Until now, generating random outputs in a way that we can verify that they are indeed random has been very difficult; typically involving taking a variety of statistical measurements.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/CEsiU1gZNLRG4VZ8pKenE/4fe5ae39fa2c63683bf7db2540ad266a/image9-2.png" />
            
            </figure><p>During Crypto week, Cloudflare is releasing a new <a href="/league-of-entropy">public randomness beacon</a> as part of the launch of the <a href="https://leagueofentropy.com">League of Entropy</a>. The League of Entropy is a network of beacons that produces <i>distributed</i>, <i>publicly verifiable</i> random outputs for use in applications where the nature of the randomness must be publicly audited. The underlying cryptographic architecture is based on the <a href="https://github.com/dedis/drand">drand project</a>.</p><p>Verifiable randomness is essential for ensuring trust in various institutional decision-making processes such as <a href="/league-of-entropy">elections and lotteries</a>. There are also cryptographic applications that require verifiable randomness. In the land of decentralized consensus mechanisms, the <a href="https://dfinity.org/static/dfinity-consensus-0325c35128c72b42df7dd30c22c41208.pdf">DFINITY approach</a> uses random seeds to decide the outcome of leadership elections. In this setting, it is essential that the randomness is publicly verifiable so that the outcome of the leadership election is trustworthy. Such a situation arises more generally in <a href="https://en.wikipedia.org/wiki/Sortition">Sortitions</a>: an election where leaders are selected as a random individual (or subset of individuals) from a larger set.</p><p>In this blog post, we will give a technical overview behind the cryptography used in the distributed randomness beacon, and how it can be used to generate publicly verifiable randomness. We believe that distributed randomness beacons have a huge amount of utility in realizing the <a href="/welcome-to-crypto-week-2019/">Internet of the Future</a>; where we will be able to rely on distributed, decentralized solutions to problems of a global-scale.</p>
    <div>
      <h2>Randomness &amp; entropy</h2>
      <a href="#randomness-entropy">
        
      </a>
    </div>
    <p>A source of randomness is measured in terms of the amount of <i>entropy</i> it provides. Think about the entropy provided by a random output as a score to indicate how “random” the output actually is. The notion of information entropy was concretised by the famous scientist Claude Shannon in his paper <a href="https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication">A Mathematical Theory of Communication</a>, and is sometimes known as <a href="https://en.wikipedia.org/wiki/Entropy_(information_theory)"><i>Shannon Entropy</i></a>.</p><p>A common way to think about random outputs is: a sequence of bits derived from some random outcome. For the sake of an argument, consider a fair 8-sided dice roll with sides marked 0-7. The outputs of the dice can be written as the bit-strings <code>000,001,010,...,111</code>. Since the dice is fair, any of these outputs is equally likely. This is means that each of the bits is equally likely to be <code>0</code> or <code>1</code>. Consequently, interpreting the output of the dice roll as a random output then derives randomness with <code>3</code> bits of entropy.</p><p>More generally, if a perfect source of randomness guarantees strings with <code>n</code> bits of entropy, then it generates bit-strings where each bit is equally likely to be <code>0</code> or <code>1</code>. This allows us to predict the value of any bit with maximum probability <code>1/2</code>. If the outputs are sampled from such a perfect source, we consider them <i>uniformly distributed</i>. If we sample the outputs from a source where one bit is predictable with higher probability, then the string has <code>n-1</code> bits of entropy. To go back to the dice analogy, rolling a 6-sided dice provides less than <code>3</code> bits of entropy because the possible outputs are <code>000,001,010,011,100,101</code> and so the 2nd and 3rd bits are more likely to be to set to <code>0</code> than to <code>1</code>.</p><p>It is possible to mix entropy sources using specifically designed mixing functions to retrieve something with even greater entropy. The maximum resulting entropy is the sum of the entropy taken from the number of entropic sources used as input.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4LcFWOh6MsFEqmYrGB6PXa/f87eb05da963db50a5f8a0a24d260d76/combined-entropy-_2x.png" />
            
            </figure>
    <div>
      <h4>Sampling randomness</h4>
      <a href="#sampling-randomness">
        
      </a>
    </div>
    <p>To sample randomness, let’s first identify the appropriate sources. There are many natural phenomena that one can use:</p><ul><li><p>atmospheric noise;</p></li><li><p>radioactive decay;</p></li><li><p>turbulent motion; like that generated in Cloudflare’s wall of <a href="/lavarand-in-production-the-nitty-gritty-technical-details/">lava lamps(!)</a>.</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2nJtxum8JhhrkxOyplTTka/e96eaea45650c205a68cda95c4ee9b8a/pasted-image-0--1-.png" />
            
            </figure><p>Unfortunately, these phenomena require very specific measuring tools, which are prohibitively expensive to install in mainstream consumer electronics. As such, most personal computing devices usually use external usage characteristics for seeding specific generator functions that output randomness as and when the system requires it. These characteristics include keyboard typing patterns and speed and mouse movement – since such usage patterns are based on the human user, it is assumed they provide sufficient entropy as a randomness source. An example of a random number generator that takes entropy from these characteristics is the Linux-based <a href="https://en.wikipedia.org/wiki/RdRand">RDRAND</a> function.</p><p>Naturally, it is difficult to tell whether a system is <i>actually</i> returning random outputs by only inspecting the outputs. There are statistical tests that detect whether a series of outputs is not uniformly distributed, but these tests cannot ensure that they are unpredictable. This means that it is hard to detect if a given system has had its randomness generation compromised.</p>
    <div>
      <h2>Distributed randomness</h2>
      <a href="#distributed-randomness">
        
      </a>
    </div>
    <p>It’s clear we need alternative methods for sampling randomness so that we can provide guarantees that trusted mechanisms, such as elections and lotteries, take place in secure tamper-resistant environments. The <a href="https://github.com/dedis/drand/">drand</a> project was started by researchers at <a href="https://www.epfl.ch/about/">EPFL</a> to address this problem. The drand charter is to provide an easily configurable randomness beacon running at geographically distributed locations around the world. The intention is for each of these beacons to generate portions of randomness that can be combined into a single random string that is publicly verifiable.</p><p>This functionality is achieved using <i>threshold cryptography</i>. Threshold cryptography seeks to derive solutions for standard cryptographic problems by combining information from multiple distributed entities. The notion of the threshold means that if there are <code>n</code> entities, then any <code>t</code> of the entities can combine to construct some cryptographic object (like a ciphertext, or a digital signature). These threshold systems are characterised by a setup phase, where each entity learns a <i>share</i> of data. They will later use this share of data to create a combined cryptographic object with a subset of the other entities.</p>
    <div>
      <h3>Threshold randomness</h3>
      <a href="#threshold-randomness">
        
      </a>
    </div>
    <p>In the case of a distributed randomness protocol, there are <code>n</code> <i>randomness beacons</i> that broadcast random values sampled from their initial data share, and the current state of the system. This data share is created during a trusted setup phase, and also takes in some internal random value that is generated by the beacon itself.</p><p>When a user needs randomness, they send requests to some number <code>t</code> of beacons, where <code>t &lt; n</code>, and combine these values using a specific procedure. The result is a random value that can be verified and used for public auditing mechanisms.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7BeauvWICHvAH9uX1tCqaY/47a57124c026459500347cf14757f818/pasted-image-0--2-.png" />
            
            </figure><p>Consider what happens if some proportion <code>c/n</code> of the randomness beacons are <i>corrupted</i> at any one time. The nature of a threshold cryptographic system is that, as long as <code>c &lt; t</code>, then the end result still remains random.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5NM7oB6KqjsC5ys55cVEGP/9165d5ad0c235240b6e455cf08e62f1e/pasted-image-0--3-.png" />
            
            </figure><p>If <code>c</code> exceeds <code>t</code> then the random values produced by the system become predictable and the notion of randomness is lost. In summary, the distributed randomness procedure provides verifiably random outputs with sufficient entropy only when <code>c &lt; t</code>.</p><p>By distributing the beacons independent of each other and in geographically disparate locations, the probability that <code>t</code> locations can be corrupted at any one time is extremely low. The minimum choice of <code>t</code> is equal to <code>n/2</code>.</p>
    <div>
      <h2>How does it actually work?</h2>
      <a href="#how-does-it-actually-work">
        
      </a>
    </div>
    <p>What we described above sounds a bit like magic<sup>tm</sup>. Even if <code>c = t-1</code>, then we can ensure that the output is indeed random and unpredictable! To make it clearer how this works, let’s dive a bit deeper into the underlying cryptography.</p><p>Two core components of drand are: a <i>distributed key generation</i> (DKG) procedure, and a <i>threshold signature scheme</i>. These core components are used in setup and randomness generation procedures, respectively. In just a bit, we’ll outline how drand uses these components (without navigating too deeply into the onerous mathematics).</p>
    <div>
      <h3>Distributed key generation</h3>
      <a href="#distributed-key-generation">
        
      </a>
    </div>
    <p>At a high-level, the DKG procedure creates a distributed secret key that is formed of <code>n</code> different key pairs <code>(vk_i, sk_i)</code>, each one being held by the entity <code>i</code> in the system. These key pairs will eventually be used to instantiate a <code>(t,n)</code>-threshold signature scheme (we will discuss this more later). In essence, <code>t</code> of the entities will be able to combine to construct a valid signature on any message.</p><p>To think about how this might work, consider a distributed key generation scheme that creates <code>n</code> distributed keys that are going to be represented by pizzas. Each pizza is split into <code>n</code> slices and one slice from each is secretly passed to one of the participants. Each entity receives one slice from each of the different pizzas (<code>n</code> in total) and combines these slices to form their own pizza. Each combined pizza is unique and secret for each entity, representing their own key pair.</p>
    <div>
      <h4>Mathematical intuition</h4>
      <a href="#mathematical-intuition">
        
      </a>
    </div>
    <p>Mathematically speaking, and rather than thinking about pizzas, we can describe the underlying phenomenon by reconstructing lines or curves on a graph. We can take two coordinates on a <code>(x,y)</code> plane and immediately (and uniquely) define a line with the equation <code>y = ax+b</code>. For example, the points <code>(2,3)</code> and <code>(4,7)</code> immediately define a line with gradient <code>(7-3)/(4/2) = 2</code> so <code>a=2</code>. You can then derive the <code>b</code> coefficient as <code>-1</code> by evaluating either of the coordinates in the equation <code>y = 2x + b</code>. By <i>uniquely</i>, we mean that only the line <code>y = 2x -1</code> satisfies the two coordinates that are chosen; no other choice of <code>a</code> or <code>b</code> fits.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2htl50xQeT4euGS3VR6rxf/de0f4b27b223bd88f4fc90ebd204367e/line2-2-.png" />
            
            </figure><p>The curve <code>ax+b</code> has degree <code>1</code>, where the degree of the equation refers to the highest order multiplication of unknown variables in the equation. That might seem like mathematical jargon, but the equation above contains only one term <code>ax</code>, which depends on the unknown variable <code>x</code>. In this specific term, the  <i>exponent</i> (or <i>power</i>) of <code>x</code> is <code>1</code>, and so the degree of the entire equation is also <code>1</code>.</p><p>Likewise, by taking three sets of coordinates pairs in the same plane, we uniquely define a quadratic curve with an equation that approximately takes the form <code>y = ax^2 + bx + c</code> with the coefficients <code>a,b,c</code> uniquely defined by the chosen coordinates. The process is a bit more involved than the above case, but it essentially starts in the same way using three coordinate pairs <code>(x_1, y_1)</code>, <code>(x_2, y_2)</code> and <code>(x_3, y_3)</code>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/24FGvRaMCx5lUA2umjk6wi/4e76792bba003072606d6196c0febdc2/line3.png" />
            
            </figure><p>By a quadratic curve, we mean a curve of degree <code>2</code>. We can see that this curve has degree <code>2</code> because it contains two terms <code>ax^2</code> and <code>bx</code> that depend on <code>x</code>. The highest order term is the <code>ax^2</code> term with an exponent of <code>2</code>, so this curve has degree <code>2</code> (ignore the term <code>bx</code> which has a smaller power).</p><p>What we are ultimately trying to show is that this approach scales for curves of degree <code>n</code> (of the form <code>y = a_n x^n + … a_1 x + a_0</code>). So, if we take <code>n+1</code> coordinates on the <code>(x,y)</code> plane, then we can uniquely reconstruct the curve of this form entirely. Such degree <code>n</code> equations are also known as <i>polynomials</i> of degree <code>n</code>.</p><p>In order to generalise the approach to general degrees we need some kind of formula. This formula should take <code>n+1</code> pairs of coordinates and return a polynomial of degree <code>n</code>. Fortunately, such a formula exists without us having to derive it ourselves, it is known as the <a href="https://en.wikipedia.org/wiki/Lagrange_polynomial#Definition"><i>Lagrange interpolation polynomial</i></a>. Using the formula in the link, we can reconstruct any <code>n</code> degree polynomial using <code>n+1</code> unique pairs of coordinates.</p><p>Going back to pizzas temporarily, it will become clear in the next section how this Lagrange interpolation procedure essentially describes the dissemination of one slice (corresponding to <code>(x,y)</code> coordinates) taken from a single pizza (the entire <code>n-1</code> degree polynomial) among <code>n</code> participants. Running this procedure <code>n</code> times in parallel allows each entity to construct their entire pizza (or the eventual key pair).</p>
    <div>
      <h4>Back to key generation</h4>
      <a href="#back-to-key-generation">
        
      </a>
    </div>
    <p>Intuitively, in the DKG procedure we want to distribute <code>n</code> key pairs among <code>n</code> participants. This effectively means running <code>n</code> parallel instances of a <code>t</code>-out-of-<code>n</code> <a href="https://en.wikipedia.org/wiki/Shamir's_Secret_Sharing">Shamir Secret Sharing</a> scheme. This secret sharing scheme is built entirely upon the polynomial interpolation technique that we described above.</p><p>In a single instance, we take the secret key to be the first coefficient of a polynomial of degree <code>t-1</code> and the public key is a published value that depends on this secret key, but does not reveal the actual coefficient. Think of RSA, where we have a number <code>N = pq</code> for secret large prime numbers <code>p,q</code>, where <code>N</code> is public but does not reveal the actual factorisation. Notice that if the polynomial is reconstructed using the interpolation technique above, then we immediately learn the secret key, because the first coefficient will be made explicit.</p><p>Each secret sharing scheme publishes shares, where each share is a different evaluation of the polynomial (dependent on the entity <code>i</code> receiving the key share). These evaluations are essentially coordinates on the <code>(x,y)</code> plane.</p><p>By running <code>n</code> parallel instances of the secret sharing scheme, each entity receives <code>n</code> shares and then combines all of these to form their overall key pair <code>(vk_i, sk_i)</code>.</p><p>The DKG procedure uses <code>n</code> parallel secret sharing procedures along with <a href="https://link.springer.com/chapter/10.1007/3-540-46766-1_9">Pedersen commitments</a> to distribute the key pairs. We explain in the next section how this procedure is part of the procedure for provisioning randomness beacons.</p><p>In summary, it is important to remember that <b>each party</b> in the DKG protocol generates a random secret key from the <code>n</code> shares that they receive, and they compute the corresponding public key from this. We will now explain how each entity uses this key pair to perform the cryptographic procedure that is used by the drand protocol.</p>
    <div>
      <h3>Threshold signature scheme</h3>
      <a href="#threshold-signature-scheme">
        
      </a>
    </div>
    <p>Remember: a standard signature scheme considers a key-pair <code>(vk,sk)</code>, where <code>vk</code> is a public verification key and <code>sk</code> is a private signing key. So, messages <code>m</code> signed with <code>sk</code> can be verified with <code>vk</code>. The security of the scheme ensures that it is difficult for anybody who does not hold <code>sk</code> to compute a valid signature for any message <code>m</code>.</p><p>A <i>threshold signature scheme</i> allows a set of users holding distributed key-pairs <code>(vk_i,sk_i)</code> to compute intermediate signatures <code>u_i</code> on a given message <code>m</code>.</p><p>Given knowledge of some number <code>t</code> of intermediate signatures <code>u_i</code>, a valid signature <code>u</code> on the message <code>m</code> can be reconstructed under the combined secret key <code>sk</code>. The public key <code>vk</code> can also be inferred using knowledge of the public keys <code>vk_i</code>, and then this public key can be used to verify <code>u</code>.</p><p>Again, think back to reconstructing the degree <code>t-1</code> curves on graphs with <code>t</code> known coordinates. In this case, the coordinates correspond to the intermediate signatures <code>u_i</code>, and the signature <code>u</code> corresponds to the entire curve. For the actual signature schemes, the mathematics are much more involved than in the DKG procedure, but the principal is the same.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2SpuFg5fE6Trs3KhVfGeQq/829504847821500097e2b7474a83037d/threshold-sig-3-.png" />
            
            </figure>
    <div>
      <h3>drand protocol</h3>
      <a href="#drand-protocol">
        
      </a>
    </div>
    <p>The <code>n</code> beacons that will take part in the drand project are identified. In the trusted setup phase, the DKG protocol from above is run, and each beacon effectively creates a key pair <code>(vk_i, sk_i)</code> for a threshold signature scheme. In other words, this key pair will be able to generate intermediate signatures that can be combined to create an entire signature for the system.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ZkOUnhX8QiVnhPou3nC9/c7657ac1ec50d7156fee239f69e57e28/DKG-6-.png" />
            
            </figure><p>For each round (occurring once a minute, for example), the beacons agree on a signature <code>u</code> evaluated over a message containing the previous round’s signature and the current round’s number. This signature <code>u</code> is the result of combining the intermediate signatures <code>u_i</code> over the same message. Each intermediate signature <code>u_i</code> is created by each of the beacons using their secret <code>sk_i</code>.</p><p>Once this aggregation completes, each beacon displays the signature for the current round, along with the previous signature and round number. This allows any client to publicly verify the signature over this data to verify that the beacons honestly aggregate. This provides a chain of verifiable signatures, extending back to the first round of output. In addition, there are threshold signature schemes that output signatures that are indistinguishable from random sequences of bytes. Therefore, these signatures can be used directly as verifiable randomness for the applications we discussed previously.</p>
    <div>
      <h3>What does drand use?</h3>
      <a href="#what-does-drand-use">
        
      </a>
    </div>
    <p>To instantiate the required threshold signature scheme, drand uses the <code>(t,n)</code>-<a href="https://www.iacr.org/archive/pkc2003/25670031/25670031.pdf">BLS signature scheme</a> of Boneh, Lynn and Shacham. In particular, we can instantiate this scheme in the elliptic curve setting using  <a href="https://github.com/dfinity/bn">Barreto-Naehrig</a> curves. Moreover, the BLS signature scheme outputs sufficiently large signatures that are randomly distributed, giving them enough entropy to be sources of randomness. Specifically the signatures are randomly distributed over 64 bytes.</p><p>BLS signatures use a specific form of mathematical operation known as a <i>cryptographic pairing</i>. Pairings can be computed in certain elliptic curves, including the Barreto-Naehrig curve configurations. A detailed description of pairing operations is beyond the scope of this blog post; though it is important to remember that these operations are integral to how BLS signatures work.</p><p>Concretely speaking, all drand cryptographic operations are carried out using a library built on top of Cloudflare's implementation of the <a href="https://github.com/cloudflare/bn256/tree/lattices">bn256 curve</a>. The Pedersen DKG protocol follows the design of <a href="https://link.springer.com/article/10.1007/s00145-006-0347-3">Gennaro et al.</a>.</p>
    <div>
      <h3>How does it work?</h3>
      <a href="#how-does-it-work">
        
      </a>
    </div>
    <p>The randomness beacons are synchronised in rounds. At each round, a beacon produces a new signature <code>u_i</code> using its private key <code>sk_i</code> on the previous signature generated and the round ID. These signatures are usually broadcast on the URL <code>drand.&lt;host&gt;.com/api/public</code>. These signatures can be verified using the keys <code>vk_i</code> and over the same data that is signed. By signing the previous signature and the current round identifier, this establishes a chain of trust for the randomness beacon that can be traced back to the original signature value.</p><p>The randomness can be retrieved by combining the signatures from each of the beacons using the threshold property of the scheme. This reconstruction of the signature <code>u</code> from each intermediate signature <code>u_i</code> is done internally by the League of Entropy nodes. Each beacon broadcasts the entire signature <code>u</code>, that can be accessed over the HTTP endpoint above.</p>
    <div>
      <h2>The drand beacon</h2>
      <a href="#the-drand-beacon">
        
      </a>
    </div>
    <p>As we mentioned at the start of this blog post, Cloudflare has launched our <a href="/league-of-entropy">distributed randomness beacon</a>. This beacon is part of a network of beacons from different institutions around the globe that form the <a href="https://leagueofentropy.com">League of  Entropy</a>.</p><p>The Cloudflare beacon uses <a href="/lavarand-in-production-the-nitty-gritty-technical-details/">LavaRand</a> as its internal source of randomness for the DKG. Other League of Entropy drand beacons have their own sources of randomness.</p>
    <div>
      <h3>Give me randomness!</h3>
      <a href="#give-me-randomness">
        
      </a>
    </div>
    <blockquote><p>The below API endpoints are obsolete. Please see <a href="https://drand.love">https://drand.love</a> for the most up-to-date documentation.</p></blockquote><p>The drand beacon allows you to retrieve the latest random value from the League of Entropy using a simple HTTP request:</p>
            <pre><code>curl https://drand.cloudflare.com/api/public</code></pre>
            <p>The response is a JSON blob of the form:</p>
            <pre><code>{
    "round": 7,
    "previous": &lt;hex-encoded-previous-signature&gt;,
    "randomness": {
        "gid": 21,
        "point": &lt;hex-encoded-new-signature&gt;
    }
}</code></pre>
            <p>where, <code>randomness.point</code> is the signature <code>u</code> aggregated among the entire set of beacons.</p><p>The signature is computed as an evaluation of the message, and is comprised of the signature of the previous round, <code>previous</code>, the current round number, <code>round</code>, and the aggregated secret key of the system. This signature can be verified using the entire public key <code>vk</code> of the Cloudflare beacon, learned using another HTTP request:</p>
            <pre><code>curl https://drand.cloudflare.com/api/public</code></pre>
            <p>There are eight collaborators in the League of Entropy. You can learn the current round of randomness (or the system’s public key) by querying these beacons on the HTTP endpoints listed above.</p><ul><li><p><a href="https://drand.cloudflare.com:443">https://drand.cloudflare.com:443</a></p></li><li><p><a href="https://random.uchile.cl:8080">https://random.uchile.cl:8080</a></p></li><li><p><a href="https://drand.cothority.net:7003">https://drand.cothority.net:7003</a></p></li><li><p><a href="https://drand.kudelskisecurity.com:443">https://drand.kudelskisecurity.com:443</a></p></li><li><p><a href="https://drand.lbarman.ch:443">https://drand.lbarman.ch:443</a></p></li><li><p><a href="https://drand.nikkolasg.xyz:8888">https://drand.nikkolasg.xyz:8888</a></p></li><li><p><a href="https://drand.protocol.ai:8080">https://drand.protocol.ai:8080</a></p></li><li><p><a href="https://drand.zerobyte.io:8888">https://drand.zerobyte.io:8888</a></p></li></ul>
    <div>
      <h2>Randomness &amp; the future</h2>
      <a href="#randomness-the-future">
        
      </a>
    </div>
    <p>Cloudflare will continue to take an active role in the drand project, both as a contributor and by running a randomness beacon with the League of Entropy. The League of Entropy is a worldwide joint effort of individuals and academic institutions. We at Cloudflare believe it can help us realize the mission of helping Build a Better Internet. For more information on Cloudflare's participation in the League of Entropy, visit <a href="https://leagueofentropy.com">https://leagueofentropy.com</a> or read <a href="/league-of-entropy">Dina's blog post</a>.</p><p>Cloudflare would like to thank all of their collaborators in the League of Entropy; from EPFL, UChile, Kudelski Security and Protocol Labs. This work would not have been possible without the work of those who contributed to the <a href="https://github.com/dedis/drand">open-source drand project</a>. We would also like to thank and appreciate the work of Gabbi Fisher, Brendan McMillion, and Mahrud Sayrafi in launching the Cloudflare randomness beacon.</p> ]]></content:encoded>
            <category><![CDATA[Crypto Week]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Cryptography]]></category>
            <category><![CDATA[Entropy]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">6yDv8PkyP9X3dUvYYh3MHZ</guid>
            <dc:creator>Alex Davidson</dc:creator>
        </item>
        <item>
            <title><![CDATA[Building a To-Do List with Workers and KV]]></title>
            <link>https://blog.cloudflare.com/building-a-to-do-list-with-workers-and-kv/</link>
            <pubDate>Tue, 21 May 2019 13:30:00 GMT</pubDate>
            <description><![CDATA[ In this tutorial, we’ll build a todo list application in HTML, CSS and JavaScript, with a twist: all the data should be stored inside of the newly-launched Workers KV, and the application itself should be served directly from Cloudflare’s edge network, using Cloudflare Workers. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>In this tutorial, we’ll build a todo list application in HTML, CSS and JavaScript, with a twist: all the data should be stored inside of the newly-launched Workers KV, and the application itself should be served directly from Cloudflare’s edge network, using <a href="https://www.cloudflare.com/products/cloudflare-workers/">Cloudflare Workers</a>.</p><p>To start, let’s break this project down into a couple different discrete steps. In particular, it can help to focus on the constraint of working with Workers KV, as handling data is generally the most complex part of building an application:</p><ol><li><p>Build a todos data structure</p></li><li><p>Write the todos into Workers KV</p></li><li><p>Retrieve the todos from Workers KV</p></li><li><p>Return an HTML page to the client, including the todos (if they exist)</p></li><li><p>Allow creation of new todos in the UI</p></li><li><p>Allow completion of todos in the UI</p></li><li><p>Handle todo updates</p></li></ol><p>This task order is pretty convenient, because it’s almost perfectly split into two parts: first, understanding the Cloudflare/API-level things we need to know about Workers <i>and</i> KV, and second, actually building up a user interface to work with the data.</p>
    <div>
      <h3>Understanding Workers</h3>
      <a href="#understanding-workers">
        
      </a>
    </div>
    <p>In terms of implementation, a great deal of this project is centered around KV - although that may be the case, it’s useful to break down <i>what</i> Workers are exactly.</p><p>Service Workers are background scripts that run in your browser, alongside your application. Cloudflare Workers are the same concept, but super-powered: your Worker scripts run on Cloudflare’s edge network, in-between your application and the client’s browser. This opens up a huge amount of opportunity for interesting integrations, especially considering the network’s massive scale around the world. Here’s some of the use-cases that I think are the most interesting:</p><ol><li><p>Custom security/filter rules to block bad actors before they ever reach the origin</p></li><li><p>Replacing/augmenting your website’s content based on the request content (i.e. user agents and other headers)</p></li><li><p>Caching requests to improve performance, or using Cloudflare KV to optimize high-read tasks in your application</p></li><li><p>Building an application <i>directly</i> on the edge, removing the dependence on origin servers entirely</p></li></ol><p>For this project, we’ll lean heavily towards the latter end of that list, building an application that clients communicate with, served on Cloudflare’s edge network. This means that it’ll be globally available, with low-latency, while still allowing the ease-of-use in building applications directly in JavaScript.</p>
    <div>
      <h3>Setting up a canvas</h3>
      <a href="#setting-up-a-canvas">
        
      </a>
    </div>
    <p>To start, I wanted to approach this project from the bare minimum: no frameworks, JS utilities, or anything like that. In particular, I was most interested in writing a project from scratch and serving it directly from the edge. Normally, I would deploy a site to something like <a href="https://pages.github.com/">GitHub Pages</a>, but avoiding the need for an origin server altogether seems like a really powerful (and performant idea) - let’s try it!</p><p>I also considered using <a href="https://todomvc.com/">TodoMVC</a> as the blueprint for building the functionality for the application, but even the <a href="http://todomvc.com/examples/vanillajs/#/">Vanilla JS</a> version is a pretty impressive amount of <a href="https://github.com/tastejs/todomvc/tree/gh-pages/examples/vanillajs">code</a>, including a number of Node packages - it wasn’t exactly a concise chunk of code to just dump into the Worker itself.</p><p>Instead, I decided to approach the beginnings of this project by building a simple, blank HTML page, and including it inside of the Worker. To start, we’ll sketch something out locally, like this:</p>
            <pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width,initial-scale=1"&gt;
    &lt;title&gt;Todos&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Todos&lt;/h1&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
            <p>Hold on to this code - we’ll add it later, inside of the Workers script. For the purposes of the tutorial, I’ll be serving up this project at <a href="http://todo.kristianfreeman.com/">todo.kristianfreeman.com</a>. My personal website was already <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">hosted on Cloudflare</a>, and since I’ll be serving, it was time to create my first Worker.</p>
    <div>
      <h3>Creating a worker</h3>
      <a href="#creating-a-worker">
        
      </a>
    </div>
    <p>Inside of my Cloudflare account, I hopped into the Workers tab and launched the Workers editor.</p><p>This is one of my favorite features of the editor - working with your actual website, understanding <i>how</i> the worker will interface with your existing project.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/121XS5g0iERXCdVwilld5G/8fe0b9a7e7b869aaf2b5d5bba3c51d98/image4-2.png" />
            
            </figure><p>The process of writing a Worker should be familiar to anyone who’s used the fetch library before. In short, the default code for a Worker hooks into the <code>fetch</code> event, passing the request of that event into a custom function, <code>handleRequest</code>:</p>
            <pre><code>addEventListener('fetch', event =&gt; {
  event.respondWith(handleRequest(event.request))
})</code></pre>
            <p>Within <code>handleRequest</code>, we make the actual request, using <code>fetch</code>, and return the response to the client. In short, we have a place to intercept the response body, but by default, we let it pass-through:</p>
            <pre><code>async function handleRequest(request) {
  console.log('Got request', request)
  const response = await fetch(request)
  console.log('Got response', response)
  return response
}</code></pre>
            <p>So, given this, where do we begin actually <i>doing stuff</i> with our worker?</p><p>Unlike the default code given to you in the Workers interface, we want to skip fetching the incoming request: instead, we’ll construct a new <code>Response</code>, and serve it directly from the edge:</p>
            <pre><code>async function handleRequest(request) {
  const response = new Response("Hello!")
  return response
}</code></pre>
            <p>Given that very small functionality we’ve added to the worker, let’s deploy it. Moving into the “Routes” tab of the Worker editor, I added the route <code>https://todo.kristianfreeman.com/*</code> and attached it to the cloudflare-worker-todos script.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/29QYuFrFiwZKVwZHkWN90v/851c0e9b95c03badc9eccbee41079a20/image5.png" />
            
            </figure><p>Once attached, I deployed the worker, and voila! Visiting todo.kristianfreeman.com in-browser gives me my simple “Hello!” response back.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/Boo3xWgZdHEDHgpUgIrKy/594ae6a988d40a13253af74937d9a964/Screen-Shot-2019-05-15-at-10.12.04-AM.png" />
            
            </figure>
    <div>
      <h3>Writing data to KV</h3>
      <a href="#writing-data-to-kv">
        
      </a>
    </div>
    <p>The next step is to populate our todo list with actual data. To do this, we’ll make use of Cloudflare’s Workers KV - it’s a simple key-value store that you can access inside of your Worker script to read (and write, although it’s less common) data.</p><p>To get started with KV, we need to set up a “namespace”. All of our cached data will be stored inside that namespace, and given just a bit of configuration, we can access that namespace inside the script with a predefined variable.</p><p>I’ll create a new namespace in the Workers dashboard, called <code>KRISTIAN_TODOS</code>, and in the Worker editor, I’ll expose the namespace by binding it to the variable <code>KRISTIAN_TODOS</code>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4i4hCpAgNXFTWxg8X2CXW2/8f67cbecd052f177ca02ce089b511e65/image1-6.png" />
            
            </figure><p>Given the presence of <code>KRISTIAN_TODOS</code> in my script, it’s time to understand the KV API. At time of writing, a KV namespace has three primary methods you can use to interface with your cache: <code>get</code>, <code>put</code>, and <code>delete</code>. Pretty straightforward!</p><p>Let’s start storing data by defining an initial set of data, which we’ll put inside of the cache using the put method. I’ve opted to define an object, <code>defaultData</code>, instead of a simple array of todos: we may want to store metadata and other information inside of this cache object later on. Given that data object, I’ll use <code>JSON.stringify</code> to put a simple string into the cache:</p>
            <pre><code>async function handleRequest(request) {
  // ...previous code
  
  const defaultData = { 
    todos: [
      {
        id: 1,
        name: 'Finish the Cloudflare Workers blog post',
          completed: false
      }
    ] 
  }
  KRISTIAN_TODOS.put("data", JSON.stringify(defaultData))
}
</code></pre>
            <p>The Worker KV data store is <i>eventually</i> consistent: writing to the cache means that it will become available <i>eventually</i>, but it’s possible to attempt to read a value back from the cache immediately after writing it, only to find that the cache hasn’t been updated yet.</p><p>Given the presence of data in the cache, and the assumption that our cache is eventually consistent, we should adjust this code slightly: first, we should actually read from the cache, parsing the value back out, and using it as the data source if exists. If it doesn’t, we’ll refer to <code>defaultData</code>, setting it as the data source <i>for now</i> (remember, it should be set in the future… <i>eventually</i>), while also setting it in the cache for future use. After breaking out the code into a few functions for simplicity, the result looks like this:</p>
            <pre><code>const defaultData = { 
  todos: [
    {
      id: 1,
      name: 'Finish the Cloudflare Workers blog post',
      completed: false
    }
  ] 
}

const setCache = data =&gt; KRISTIAN_TODOS.put("data", data)
const getCache = () =&gt; KRISTIAN_TODOS.get("data")

async function getTodos(request) {
  // ... previous code
  
  let data;
  const cache = await getCache()
  if (!cache) {
    await setCache(JSON.stringify(defaultData))
    data = defaultData
  } else {
    data = JSON.parse(cache)
  }
}</code></pre>
            
    <div>
      <h3>Rendering data from KV</h3>
      <a href="#rendering-data-from-kv">
        
      </a>
    </div>
    <p>Given the presence of data in our code, which is the cached data object for our application, we should actually take this data and make it available on screen.</p><p>In our Workers script, we’ll make a new variable, <code>html</code>, and use it to build up a static HTML template that we can serve to the client. In <code>handleRequest</code>, we can construct a new <code>Response</code> (with a <code>Content-Type</code> header of <code>text/html</code>), and serve it to the client:</p>
            <pre><code>const html = `
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width,initial-scale=1"&gt;
    &lt;title&gt;Todos&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Todos&lt;/h1&gt;
  &lt;/body&gt;
&lt;/html&gt;
`

async function handleRequest(request) {
  const response = new Response(html, {
    headers: { 'Content-Type': 'text/html' }
  })
  return response
}</code></pre>
            
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6JYK6WXof6rGxmk6ovyH27/77f4df33d945cf673df4510bf650b16b/Screen-Shot-2019-05-15-at-10.06.57-AM.png" />
            
            </figure><p>We have a static HTML site being rendered, and now we can begin populating it with data! In the body, we’ll add a <code>ul</code> tag with an id of <code>todos</code>:</p>
            <pre><code>&lt;body&gt;
  &lt;h1&gt;Todos&lt;/h1&gt;
  &lt;ul id="todos"&gt;&lt;/ul&gt;
&lt;/body&gt;</code></pre>
            <p>Given that body, we can also add a script <i>after</i> the body that takes a todos array, loops through it, and for each todo in the array, creates a <code>li</code> element and appends it to the todos list:</p>
            <pre><code>&lt;script&gt;
  window.todos = [];
  var todoContainer = document.querySelector("#todos");
  window.todos.forEach(todo =&gt; {
    var el = document.createElement("li");
    el.innerText = todo.name;
    todoContainer.appendChild(el);
  });
&lt;/script&gt;</code></pre>
            <p>Our static page can take in <code>window.todos</code>, and render HTML based on it, but we haven’t actually passed in any data from KV. To do this, we’ll need to make a couple changes.</p><p>First, our <code>html</code> <i>variable</i> will change to a <i>function</i>. The function will take in an argument, <code>todos</code>, which will populate the <code>window.todos</code> variable in the above code sample:</p>
            <pre><code>const html = todos =&gt; `
&lt;!doctype html&gt;
&lt;html&gt;
  &lt;!-- ... --&gt;
  &lt;script&gt;
    window.todos = ${todos || []}
    var todoContainer = document.querySelector("#todos");
    // ...
  &lt;script&gt;
&lt;/html&gt;
`</code></pre>
            <p>In <code>handleRequest</code>, we can use the retrieved KV data to call the <code>html</code> function, and generate a <code>Response</code> based on it:</p>
            <pre><code>async function handleRequest(request) {
  let data;
  
  // Set data using cache or defaultData from previous section...
  
  const body = html(JSON.stringify(data.todos))
  const response = new Response(body, {
    headers: { 'Content-Type': 'text/html' }
  })
  return response
}</code></pre>
            <p>The finished product looks something like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/579BL1kiP7vJc6bxWcDD82/057188acb0323d3764e76419b13e7469/image3-3.png" />
            
            </figure>
    <div>
      <h3>Adding todos from the UI</h3>
      <a href="#adding-todos-from-the-ui">
        
      </a>
    </div>
    <p>At this point, we’ve built a Cloudflare Worker that takes data from Cloudflare KV and renders a static page based on it. That static page reads the data, and generates a todo list based on that data. Of course, the piece we’re missing is <i>creating</i> todos, from inside the UI. We know that we can add todos using the KV API - we could simply update the cache by saying <code>KRISTIAN_TODOS.put(newData)</code>, but how do we update it from inside the UI?</p><p>It’s worth noting here that Cloudflare’s Workers documentation suggests that any writes to your KV namespace happen via their API - that is, at its simplest form, a cURL statement:</p>
            <pre><code>curl "&lt;https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/values/first-key&gt;" \
  -X PUT \
  -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
  -H "X-Auth-Key: $CLOUDFLARE_AUTH_KEY" \
  --data 'My first value!'</code></pre>
            <p>We’ll implement something similar by handling a second route in our worker, designed to watch for <code>PUT</code> requests to <code>/</code>. When a body is received at that URL, the worker will send the new todo data to our KV store.</p><p>I’ll add this new functionality to my worker, and in <code>handleRequest</code>, if the request method is a <code>PUT</code>, it will take the request body and update the cache:</p>
            <pre><code>addEventListener('fetch', event =&gt; {
  event.respondWith(handleRequest(event.request))
})

const setCache = data =&gt; KRISTIAN_TODOS.put("data", data)

async function updateTodos(request) {
  const body = await request.text()
  const ip = request.headers.get("CF-Connecting-IP")
  const cacheKey = `data-${ip}`;
  try {
    JSON.parse(body)
    await setCache(body)
    return new Response(body, { status: 200 })
  } catch (err) {
    return new Response(err, { status: 500 })
  }
}

async function handleRequest(request) {
  if (request.method === "PUT") {
    return updateTodos(request);
  } else {
    // Defined in previous code block
    return getTodos(request);
  }
}</code></pre>
            <p>The script is pretty straightforward - we check that the request is a <code>PUT</code>, and wrap the remainder of the code in a <code>try/catch</code> block. First, we parse the body of the request coming in, ensuring that it is JSON, before we update the cache with the new data, and return it to the user. If anything goes wrong, we simply return a 500. If the route is hit with an HTTP method <i>other</i> than <code>PUT</code> - that is, <code>GET</code>, <code>DELETE</code>, or anything else - we return a 404.</p><p>With this script, we can now add some “dynamic” functionality to our HTML page to actually hit this route.</p><p>First, we’ll create an input for our todo “name”, and a button for “submitting” the todo.</p>
            <pre><code>&lt;div&gt;
  &lt;input type="text" name="name" placeholder="A new todo"&gt;&lt;/input&gt;
  &lt;button id="create"&gt;Create&lt;/button&gt;
&lt;/div&gt;</code></pre>
            <p>Given that input and button, we can add a corresponding JavaScript function to watch for clicks on the button - once the button is clicked, the browser will <code>PUT</code> to <code>/</code> and submit the todo.</p>
            <pre><code>var createTodo = function() {
  var input = document.querySelector("input[name=name]");
  if (input.value.length) {
    fetch("/", { 
      method: 'PUT', 
      body: JSON.stringify({ todos: todos }) 
    });
  }
};

document.querySelector("#create")
  .addEventListener('click', createTodo);</code></pre>
            <p>This code updates the cache, but what about our local UI? Remember that the KV cache is <i>eventually consistent</i> - even if we were to update our worker to read from the cache and return it, we have no guarantees it’ll actually be up-to-date. Instead, let’s just update the list of todos locally, by taking our original code for rendering the todo list, making it a re-usable function called <code>populateTodos</code>, and calling it when the page loads <i>and</i> when the cache request has finished:</p>
            <pre><code>var populateTodos = function() {
  var todoContainer = document.querySelector("#todos");
  todoContainer.innerHTML = null;
  window.todos.forEach(todo =&gt; {
    var el = document.createElement("li");
    el.innerText = todo.name;
    todoContainer.appendChild(el);
  });
};

populateTodos();

var createTodo = function() {
  var input = document.querySelector("input[name=name]");
  if (input.value.length) {
    todos = [].concat(todos, { 
      id: todos.length + 1, 
      name: input.value,
      completed: false,
    });
    fetch("/", { 
      method: 'PUT', 
      body: JSON.stringify({ todos: todos }) 
    });
    populateTodos();
    input.value = "";
  }
};

document.querySelector("#create")
  .addEventListener('click', createTodo);</code></pre>
            <p>With the client-side code in place, deploying the new Worker should put all these pieces together. The result is an actual dynamic todo list!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3bexkIHx7QhOOnLX7m0T2a/d1cbb132f91d422682e12a169d1e3b1c/image7.gif" />
            
            </figure>
    <div>
      <h3>Updating todos from the UI</h3>
      <a href="#updating-todos-from-the-ui">
        
      </a>
    </div>
    <p>For the final piece of our (very) basic todo list, we need to be able to update todos - specifically, marking them as completed.</p><p>Luckily, a great deal of the infrastructure for this work is already in place. We can currently update the todo list data in our cache, as evidenced by our <code>createTodo</code> function. Performing updates on a todo, in fact, is much more of a client-side task than a Worker-side one!</p><p>To start, let’s update the client-side code for generating a todo. Instead of a <code>ul</code>-based list, we’ll migrate the todo container <i>and</i> the todos themselves into using <code>div</code>s:</p>
            <pre><code>&lt;!-- &lt;ul id="todos"&gt;&lt;/ul&gt; becomes... --&gt;
&lt;div id="todos"&gt;&lt;/div&gt;</code></pre>
            <p>The <code>populateTodos</code> function can be updated to generate a <code>div</code> for each todo. In addition, we’ll move the name of the todo into a child element of that <code>div</code>:</p>
            <pre><code>var populateTodos = function() {
  var todoContainer = document.querySelector("#todos");
  todoContainer.innerHTML = null;
  window.todos.forEach(todo =&gt; {
    var el = document.createElement("div");
    var name = document.createElement("span");
    name.innerText = todo.name;
    el.appendChild(name);
    todoContainer.appendChild(el);
  });
}</code></pre>
            <p>So far, we’ve designed the client-side part of this code to take an array of todos in, and given that array, render out a list of simple HTML elements. There’s a number of things that we’ve been doing that we haven’t quite had a use for, yet: specifically, the inclusion of IDs, and updating the completed value on a todo. Luckily, these things work well together, in order to support actually updating todos in the UI.</p><p>To start, it would be useful to signify the ID of each todo in the HTML. By doing this, we can then refer to the element later, in order to correspond it to the todo in the JavaScript part of our code. <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset"><i>Data attributes</i></a>, and the corresponding dataset method in JavaScript, are a perfect way to implement this. When we generate our <code>div</code> element for each todo, we can simply attach a data attribute called <code>todo</code> to each <code>div</code>:</p>
            <pre><code>window.todos.forEach(todo =&gt; {
  var el = document.createElement("div");
  el.dataset.todo = todo.id
  // ... more setup

  todoContainer.appendChild(el);
});</code></pre>
            <p>Inside our HTML, each <code>div</code> for a todo now has an attached data attribute, which looks like:</p>
            <pre><code>&lt;div data-todo="1"&gt;&lt;/div&gt;
&lt;div data-todo="2"&gt;&lt;/div&gt;</code></pre>
            <p>Now we can generate a checkbox for each todo element. This checkbox will default to unchecked for new todos, of course, but we can mark it as checked as the element is rendered in the window:</p>
            <pre><code>window.todos.forEach(todo =&gt; {
  var el = document.createElement("div");
  el.dataset.todo = todo.id
  
  var name = document.createElement("span");
  name.innerText = todo.name;
  
  var checkbox = document.createElement("input")
  checkbox.type = "checkbox"
  checkbox.checked = todo.completed ? 1 : 0;

  el.appendChild(checkbox);
  el.appendChild(name);
  todoContainer.appendChild(el);
})</code></pre>
            <p>The checkbox is set up to correctly reflect the value of completed on each todo, but it doesn’t yet update when we actually check the box! To do this, we’ll add an event listener on the <code>click</code> event, calling <code>completeTodo</code>. Inside the function, we’ll inspect the checkbox element, finding its parent (the todo <code>div</code>), and using the <code>todo</code> data attribute on it to find the corresponding todo in our data. Given that todo, we can toggle the value of completed, update our data, and re-render the UI:</p>
            <pre><code>var completeTodo = function(evt) {
  var checkbox = evt.target;
  var todoElement = checkbox.parentNode;
  
  var newTodoSet = [].concat(window.todos)
  var todo = newTodoSet.find(t =&gt; 
    t.id == todoElement.dataset.todo
  );
  todo.completed = !todo.completed;
  todos = newTodoSet;
  updateTodos()
}</code></pre>
            <p>The final result of our code is a system that simply checks the <code>todos</code> variable, updates our Cloudflare KV cache with that value, and then does a straightforward re-render of the UI based on the data it has locally.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2dSK1aNSHxnICPPqdBZeS1/4612465de022714c1d7a7cc64e261d55/image8-1.png" />
            
            </figure>
    <div>
      <h3>Conclusions and next steps</h3>
      <a href="#conclusions-and-next-steps">
        
      </a>
    </div>
    <p>With this, we’ve created a pretty remarkable project: an almost entirely static HTML/JS application, transparently powered by Cloudflare KV and Workers, served at the edge. There’s a number of additions to be made to this application, whether you want to implement a better design (I’ll leave this as an exercise for readers to implement - you can see my version at <a href="https://todo.kristianfreeman.com/">todo.kristianfreeman.com</a>), security, speed, etc.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Vif8WsAf5slR8KM3NLeGv/6cd59bcdf0c30a6df7e4bbf9eef916ba/image2-1.png" />
            
            </figure><p>One interesting and fairly trivial addition is implementing per-user caching. Of course, right now, the cache key is simply “data”: anyone visiting the site will share a todo list with any other user. Because we have the request information inside of our worker, it’s easy to make this data user-specific. For instance, implementing per-user caching by generating the cache key based on the requesting IP:</p>
            <pre><code>const ip = request.headers.get("CF-Connecting-IP")
const cacheKey = `data-${ip}`;
const getCache = key =&gt; KRISTIAN_TODOS.get(key)
getCache(cacheKey)</code></pre>
            <p>One more deploy of our Workers project, and we have a full todo list application, with per-user functionality, served at the edge!</p><p>The final version of our Workers script looks like this:</p>
            <pre><code>const html = todos =&gt; `
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width,initial-scale=1"&gt;
    &lt;title&gt;Todos&lt;/title&gt;
    &lt;link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"&gt;&lt;/link&gt;
  &lt;/head&gt;

  &lt;body class="bg-blue-100"&gt;
    &lt;div class="w-full h-full flex content-center justify-center mt-8"&gt;
      &lt;div class="bg-white shadow-md rounded px-8 pt-6 py-8 mb-4"&gt;
        &lt;h1 class="block text-grey-800 text-md font-bold mb-2"&gt;Todos&lt;/h1&gt;
        &lt;div class="flex"&gt;
          &lt;input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-800 leading-tight focus:outline-none focus:shadow-outline" type="text" name="name" placeholder="A new todo"&gt;&lt;/input&gt;
          &lt;button class="bg-blue-500 hover:bg-blue-800 text-white font-bold ml-2 py-2 px-4 rounded focus:outline-none focus:shadow-outline" id="create" type="submit"&gt;Create&lt;/button&gt;
        &lt;/div&gt;
        &lt;div class="mt-4" id="todos"&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;

  &lt;script&gt;
    window.todos = ${todos || []}

    var updateTodos = function() {
      fetch("/", { method: 'PUT', body: JSON.stringify({ todos: window.todos }) })
      populateTodos()
    }

    var completeTodo = function(evt) {
      var checkbox = evt.target
      var todoElement = checkbox.parentNode
      var newTodoSet = [].concat(window.todos)
      var todo = newTodoSet.find(t =&gt; t.id == todoElement.dataset.todo)
      todo.completed = !todo.completed
      window.todos = newTodoSet
      updateTodos()
    }

    var populateTodos = function() {
      var todoContainer = document.querySelector("#todos")
      todoContainer.innerHTML = null

      window.todos.forEach(todo =&gt; {
        var el = document.createElement("div")
        el.className = "border-t py-4"
        el.dataset.todo = todo.id

        var name = document.createElement("span")
        name.className = todo.completed ? "line-through" : ""
        name.innerText = todo.name

        var checkbox = document.createElement("input")
        checkbox.className = "mx-4"
        checkbox.type = "checkbox"
        checkbox.checked = todo.completed ? 1 : 0
        checkbox.addEventListener('click', completeTodo)

        el.appendChild(checkbox)
        el.appendChild(name)
        todoContainer.appendChild(el)
      })
    }

    populateTodos()

    var createTodo = function() {
      var input = document.querySelector("input[name=name]")
      if (input.value.length) {
        window.todos = [].concat(todos, { id: window.todos.length + 1, name: input.value, completed: false })
        input.value = ""
        updateTodos()
      }
    }

    document.querySelector("#create").addEventListener('click', createTodo)
  &lt;/script&gt;
&lt;/html&gt;
`

const defaultData = { todos: [] }

const setCache = (key, data) =&gt; KRISTIAN_TODOS.put(key, data)
const getCache = key =&gt; KRISTIAN_TODOS.get(key)

async function getTodos(request) {
  const ip = request.headers.get('CF-Connecting-IP')
  const cacheKey = `data-${ip}`
  let data
  const cache = await getCache(cacheKey)
  if (!cache) {
    await setCache(cacheKey, JSON.stringify(defaultData))
    data = defaultData
  } else {
    data = JSON.parse(cache)
  }
  const body = html(JSON.stringify(data.todos || []))
  return new Response(body, {
    headers: { 'Content-Type': 'text/html' },
  })
}

async function updateTodos(request) {
  const body = await request.text()
  const ip = request.headers.get('CF-Connecting-IP')
  const cacheKey = `data-${ip}`
  try {
    JSON.parse(body)
    await setCache(cacheKey, body)
    return new Response(body, { status: 200 })
  } catch (err) {
    return new Response(err, { status: 500 })
  }
}

async function handleRequest(request) {
  if (request.method === 'PUT') {
    return updateTodos(request)
  } else {
    return getTodos(request)
  }
}

addEventListener('fetch', event =&gt; {
  event.respondWith(handleRequest(event.request))
})</code></pre>
            <p>You can find the source code for this project, as well as a README with deployment instructions, on <a href="https://github.com/signalnerve/cloudflare-workers-todos">GitHub</a>.</p> ]]></content:encoded>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Cloudflare Workers KV]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">1KZ1qTWOTEOhmuFFXT6xuC</guid>
            <dc:creator>Kristian Freeman</dc:creator>
        </item>
        <item>
            <title><![CDATA[Workers KV — Cloudflare's distributed database]]></title>
            <link>https://blog.cloudflare.com/workers-kv-is-ga/</link>
            <pubDate>Tue, 21 May 2019 13:00:00 GMT</pubDate>
            <description><![CDATA[ Today, we’re excited to announce Workers KV is entering general availability and is ready for production use! ]]></description>
            <content:encoded><![CDATA[ <p>Today, we’re excited to announce Workers KV is entering general availability and is ready for production use!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3188jggqN4vJJchIXvTReV/e9476e1e9e5783948d4255f92bcb2e47/Workers-KV-GA_2x.png" />
            
            </figure>
    <div>
      <h3>What is Workers KV?</h3>
      <a href="#what-is-workers-kv">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/products/workers-kv/">Workers KV</a> is a highly distributed, eventually consistent, key-value store that spans Cloudflare's global edge. It allows you to store billions of key-value pairs and read them with ultra-low latency anywhere in the world. Now you can build entire applications with the performance of a CDN static cache.</p>
    <div>
      <h3>Why did we build it?</h3>
      <a href="#why-did-we-build-it">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/products/cloudflare-workers/">Workers</a> is a platform that lets you run JavaScript on Cloudflare's global edge of 175+ data centers. With only a few lines of code, you can route HTTP requests, modify responses, or even create new responses without an origin server.</p>
            <pre><code>// A Worker that handles a single redirect,
// such a humble beginning...
addEventListener("fetch", event =&gt; {
  event.respondWith(handleOneRedirect(event.request))
})

async function handleOneRedirect(request) {
  let url = new URL(request.url)
  let device = request.headers.get("CF-Device-Type")
  // If the device is mobile, add a prefix to the hostname.
  // (eg. example.com becomes mobile.example.com)
  if (device === "mobile") {
    url.hostname = "mobile." + url.hostname
    return Response.redirect(url, 302)
  }
  // Otherwise, send request to the original hostname.
  return await fetch(request)
}</code></pre>
            <p>Customers quickly came to us with use cases that required a way to store persistent data. Following our example above, it's easy to handle a single redirect, but what if you want to handle <b>billions</b> of them? You would have to hard-code them into your Workers script, fit it all in under 1 MB, and re-deploy it every time you wanted to make a change — yikes! That’s why we built Workers KV.</p>
            <pre><code>// A Worker that can handle billions of redirects,
// now that's more like it!
addEventListener("fetch", event =&gt; {
  event.respondWith(handleBillionsOfRedirects(event.request))
})

async function handleBillionsOfRedirects(request) {
  let prefix = "/redirect"
  let url = new URL(request.url)
  // Check if the URL is a special redirect.
  // (eg. example.com/redirect/&lt;random-hash&gt;)
  if (url.pathname.startsWith(prefix)) {
    // REDIRECTS is a custom variable that you define,
    // it binds to a Workers KV "namespace." (aka. a storage bucket)
    let redirect = await REDIRECTS.get(url.pathname.replace(prefix, ""))
    if (redirect) {
      url.pathname = redirect
      return Response.redirect(url, 302)
    }
  }
  // Otherwise, send request to the original path.
  return await fetch(request)
}</code></pre>
            <p>With only a few changes from our previous example, we scaled from one redirect to billions − that's just a taste of what you can build with Workers KV.</p>
    <div>
      <h3>How does it work?</h3>
      <a href="#how-does-it-work">
        
      </a>
    </div>
    <p>Distributed data stores are often modeled using the <a href="https://en.wikipedia.org/wiki/CAP_theorem">CAP Theorem</a>, which states that distributed systems can only pick between <b>2 out of the 3</b> following guarantees:</p><ul><li><p><b>C</b>onsistency - is my data the same everywhere?</p></li><li><p><b>A</b>vailability - is my data accessible all the time?</p></li><li><p><b>P</b>artition tolerance - is my data resilient to regional outages?</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2q0UXWQCbVcPVUX9nrkB88/2c384717f1db76f9ecdf7065c08b770f/workers-kv-venn-diagram_2x-1.png" />
            
            </figure><p>Workers KV chooses to guarantee <b>A</b>vailability and <b>P</b>artition tolerance. This combination is known as <a href="https://en.wikipedia.org/wiki/Eventual_consistency">eventual consistency</a>, which presents Workers KV with two unique competitive advantages:</p><ul><li><p>Reads are ultra fast (median of 12 ms) since its powered by our caching technology.</p></li><li><p>Data is available across 175+ edge data centers and resilient to regional outages.</p></li></ul><p>Although, there are tradeoffs to eventual consistency. If two clients write different values to the same key at the same time, the last client to write <b>eventually</b> "wins" and its value becomes globally consistent. This also means that if a client writes to a key and that same client reads that same key, the values may be inconsistent for a short amount of time.</p><p>To help visualize this scenario, here's a real-life example amongst three friends:</p><ul><li><p>Suppose Matthew, Michelle, and Lee are planning their weekly lunch.</p></li><li><p>Matthew decides they're going out for sushi.</p></li><li><p>Matthew tells Michelle their sushi plans, Michelle agrees.</p></li><li><p>Lee, not knowing the plans, tells Michelle they're actually having pizza.</p></li></ul><p>An hour later, Michelle and Lee are waiting at the pizza parlor while Matthew is sitting alone at the sushi restaurant — what went wrong? We can chalk this up to eventual consistency, because after waiting for a few minutes, Matthew looks at his updated calendar and <b>eventually</b> finds the new truth, they're going out for pizza instead.</p><p>While it may take minutes in real-life, Workers KV is much faster. It can achieve global consistency in less than 60 seconds. Additionally, when a Worker writes to a key, then <b>immediately</b> reads that same key, it can expect the values to be consistent if both operations came from the same location.</p>
    <div>
      <h3>When should I use it?</h3>
      <a href="#when-should-i-use-it">
        
      </a>
    </div>
    <p>Now that you understand the benefits and tradeoffs of using eventual consistency, how do you determine if it's the right storage solution for your application? Simply put, if you want global availability with ultra-fast reads, Workers KV is right for you.</p><p>However, if your application is <b>frequently</b> writing to the <b>same</b> key, there is an additional consideration. We call it "the Matthew question": Are you okay with the Matthews of the world <b>occasionally</b> going to the wrong restaurant?</p><p>You can imagine use cases (like our redirect Worker example) where this doesn't make any material difference. But if you decide to keep track of a user’s bank account balance, you would not want the possibility of two balances existing at once, since they could purchase something with money they’ve already spent.</p>
    <div>
      <h3>What can I build with it?</h3>
      <a href="#what-can-i-build-with-it">
        
      </a>
    </div>
    <p>Here are a few examples of applications that have been built with KV:</p><ul><li><p>Mass redirects - handle billions of HTTP redirects.</p></li><li><p>User authentication - validate user requests to your API.</p></li><li><p>Translation keys - dynamically localize your web pages.</p></li><li><p>Configuration data - manage who can access your origin.</p></li><li><p>Step functions - sync state data between multiple APIs functions.</p></li><li><p>Edge file store - <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">host</a> large amounts of small files.</p></li></ul><p>We’ve highlighted several of those <a href="/building-with-workers-kv/">use cases</a> in our previous blog post. We also have some more in-depth code walkthroughs, including a recently published blog post on how to build an online <a href="/building-a-to-do-list-with-workers-and-kv/">To-do list with Workers KV</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3oQnAPwVXWgsjCuSXuYL7q/755458cfb741e45f78c468a4729f7fc7/GQ4hrfQ.png" />
            
            </figure>
    <div>
      <h3>What's new since beta?</h3>
      <a href="#whats-new-since-beta">
        
      </a>
    </div>
    <p>By far, our most common request was to make it easier to write data to Workers KV. That's why we're releasing three new ways to make that experience even better:</p>
    <div>
      <h4>1. Bulk Writes</h4>
      <a href="#1-bulk-writes">
        
      </a>
    </div>
    <p>If you want to import your existing data into Workers KV, you don't want to go through the hassle of sending an HTTP request for <b>every</b> key-value pair. That's why we added a <a href="https://api.cloudflare.com/#workers-kv-namespace-write-multiple-key-value-pairs">bulk endpoint</a> to the Cloudflare API. Now you can upload up to 10,000 pairs (up to 100 MB of data) in a single PUT request.</p>
            <pre><code>curl "https://api.cloudflare.com/client/v4/accounts/ \
     $ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/bulk" \
  -X PUT \
  -H "X-Auth-Key: $CLOUDFLARE_AUTH_KEY" \
  -H "X-Auth-Email: $CLOUDFLARE_AUTH_EMAIL" \
  -d '[
    {"key": "built_by",    value: "kyle, alex, charlie, andrew, and brett"},
    {"key": "reviewed_by", value: "joaquin"},
    {"key": "approved_by", value: "steve"}
  ]'</code></pre>
            <p>Let's walk through an example use case: you want to off-load your website translation to Workers. Since you're reading translation keys frequently and only occasionally updating them, this application works well with the eventual consistency model of Workers KV.</p><p>In this example, we hook into <a href="https://crowdin.com/">Crowdin</a>, a popular platform to manage translation data. This Worker responds to a <code>/translate</code> endpoint, downloads all your translation keys, and bulk writes them to Workers KV so you can read it later on our edge:</p>
            <pre><code>addEventListener("fetch", event =&gt; {
  if (event.request.url.pathname === "/translate") {
    event.respondWith(uploadTranslations())
  }
})

async function uploadTranslations() {
  // Ask crowdin for all of our translations.
  var response = await fetch(
    "https://api.crowdin.com/api/project" +
    "/:ci_project_id/download/all.zip?key=:ci_secret_key")
  // If crowdin is responding, parse the response into
  // a single json with all of our translations.
  if (response.ok) {
    var translations = await zipToJson(response)
    return await bulkWrite(translations)
  }
  // Return the errored response from crowdin.
  return response
}

async function bulkWrite(keyValuePairs) {
  return fetch(
    "https://api.cloudflare.com/client/v4/accounts" +
    "/:cf_account_id/storage/kv/namespaces/:cf_namespace_id/bulk",
    {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
        "X-Auth-Key": ":cf_auth_key",
        "X-Auth-Email": ":cf_email"
      },
      body: JSON.stringify(keyValuePairs)
    }
  )
}

async function zipToJson(response) {
  // ... omitted for brevity ...
  // (eg. https://stuk.github.io/jszip)
  return [
    {key: "hello.EN", value: "Hello World"},
    {key: "hello.ES", value: "Hola Mundo"}
  ]
}</code></pre>
            <p>Now, when you want to translate a page, all you have to do is read from Workers KV:</p>
            <pre><code>async function translate(keys, lang) {
  // You bind your translations namespace to the TRANSLATIONS variable.
  return Promise.all(keys.map(key =&gt; TRANSLATIONS.get(key + "." + lang)))
}</code></pre>
            
    <div>
      <h4>2. Expiring Keys</h4>
      <a href="#2-expiring-keys">
        
      </a>
    </div>
    <p>By default, key-value pairs stored in Workers KV last forever. However, sometimes you want your data to auto-delete after a certain amount of time. That's why we're introducing the <code>expiration</code> and <code>expirationTtl</code>options for write operations.</p>
            <pre><code>// Key expires 60 seconds from now.
NAMESPACE.put("myKey", "myValue", {expirationTtl: 60})

// Key expires if the UNIX epoch is in the past.
NAMESPACE.put("myKey", "myValue", {expiration: 1247788800})</code></pre>
            
            <pre><code># You can also set keys to expire from the Cloudflare API.
curl "https://api.cloudflare.com/client/v4/accounts/ \
     $ACCOUNT_ID/storage/kv/namespaces/$NAMESPACE_ID/ \
     values/$KEY?expiration_ttl=$EXPIRATION_IN_SECONDS"
  -X PUT \
  -H "X-Auth-Key: $CLOUDFLARE_AUTH_KEY" \
  -H "X-Auth-Email: $CLOUDFLARE_AUTH_EMAIL" \
  -d "$VALUE"</code></pre>
            <p>Let's say you want to block users that have been flagged as inappropriate from your website, but only for a week. With an expiring key, you can set the expire time and not have to worry about deleting it later.</p><p>In this example, we assume users and IP addresses are one of the same. If your application has authentication, you could use access tokens as the key identifier.</p>
            <pre><code>addEventListener("fetch", event =&gt; {
  var url = new URL(event.request.url)
  // An internal API that blocks a new user IP.
  // (eg. example.com/block/1.2.3.4)
  if (url.pathname.startsWith("/block")) {
    var ip = url.pathname.split("/").pop()
    event.respondWith(blockIp(ip))
  } else {
    // Other requests check if the IP is blocked.
   event.respondWith(handleRequest(event.request))
  }
})

async function blockIp(ip) {
  // Values are allowed to be empty in KV,
  // we don't need to store any extra information anyway.
  await BLOCKED.put(ip, "", {expirationTtl: 60*60*24*7})
  return new Response("ok")
}

async function handleRequest(request) {
  var ip = request.headers.get("CF-Connecting-IP")
  if (ip) {
    var blocked = await BLOCKED.get(ip)
    // If we detect an IP and its blocked, respond with a 403 error.
    if (blocked) {
      return new Response({status: 403, statusText: "You are blocked!"})
    }
  }
  // Otherwise, passthrough the original request.
  return fetch(request)
}</code></pre>
            
    <div>
      <h4>3. Larger Values</h4>
      <a href="#3-larger-values">
        
      </a>
    </div>
    <p>We've increased our size limit on values from <code>64 kB</code> to <code>2 MB</code>. This is quite useful if you need to store buffer-based or file data in Workers KV.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1cYcxKnB6nfE9lUg6aIUZK/4cefcd37832fc703602f0c8aa37c33d6/workers-kc-file-size-update_2x.png" />
            
            </figure><p>Consider this scenario: you want to let your users upload their favorite GIF to their profile without having to store these GIFs as binaries in your database or managing <b>another</b> cloud storage bucket.</p><p>Workers KV is a great fit for this use case! You can create a Workers KV namespace for your users’ GIFs that is fast and reliable wherever your customers are located.</p><p>In this example, users upload a link to their favorite GIF, then a Worker downloads it and stores it to Workers KV.</p>
            <pre><code>addEventListener("fetch", event =&gt; {
  var url = event.request.url
  var arg = request.url.split("/").pop()
  // User sends a URI encoded link to the GIF they wish to upload.
  // (eg. example.com/api/upload_gif/&lt;encoded-uri&gt;)
  if (url.pathname.startsWith("/api/upload_gif")) {
    event.respondWith(uploadGif(arg))
    // Profile contains link to view the GIF.
    // (eg. example.com/api/view_gif/&lt;username&gt;)
  } else if (url.pathname.startsWith("/api/view_gif")) {
    event.respondWith(getGif(arg))
  }
})

async function uploadGif(url) {
  // Fetch the GIF from the Internet.
  var gif = await fetch(decodeURIComponent(url))
  var buffer = await gif.arrayBuffer()
  // Upload the GIF as a buffer to Workers KV.
  await GIFS.put(user.name, buffer)
  return gif
}

async function getGif(username) {
  var gif = await GIFS.get(username, "arrayBuffer")
  // If the user has set one, respond with the GIF.
  if (gif) {
    return new Response(gif, {headers: {"Content-Type": "image/gif"}})
  } else {
    return new Response({status: 404, statusText: "User has no GIF!"})
  }
}</code></pre>
            <p>Lastly, we want to thank all of our beta customers. It was your valuable feedback that led us to develop these changes to Workers KV. Make sure to stay in touch with us, we're always looking ahead for what's next and we love hearing from you!</p>
    <div>
      <h3>Pricing</h3>
      <a href="#pricing">
        
      </a>
    </div>
    <p>We’re also ready to announce our GA pricing. If you're one of our Enterprise customers, your pricing obviously remains unchanged.</p><ul><li><p>$0.50 / GB of data stored, 1 GB included</p></li><li><p>$0.50 / million reads, 10 million included</p></li><li><p>$5 / million write, list, and delete operations, 1 million included</p></li></ul><p>During the beta period, we learned customers don't want to just read values at our edge, they want to write values from our edge too. Since there is high demand for these edge operations, which are more costly, we have started charging non-read operations per month.</p>
    <div>
      <h3>Limits</h3>
      <a href="#limits">
        
      </a>
    </div>
    <p>As mentioned earlier, we increased our value size limit from <code>64 kB</code> to <code>2 MB</code>. We've also removed our cap on the number of keys per namespace — it's now unlimited. Here are our GA limits:</p><ul><li><p>Up to 20 namespaces per account, each with unlimited keys</p></li><li><p>Keys of up to 512 bytes and values of up to 2 MB</p></li><li><p>Unlimited writes per second for different keys</p></li><li><p>One write per second for the same key</p></li><li><p>Unlimited reads per second per key</p></li></ul>
    <div>
      <h3>Try it out now!</h3>
      <a href="#try-it-out-now">
        
      </a>
    </div>
    <p>Now open to all customers, you can start using <a href="https://www.cloudflare.com/products/workers-kv/">Workers KV</a> today from your Cloudflare dashboard under the Workers tab. You can also look at our updated <a href="https://developers.cloudflare.com/workers/kv/">documentation.</a></p><p>We're really excited to see what you all can build with Workers KV!</p> ]]></content:encoded>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Cloudflare Workers KV]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">1btTnYVZRP9LCWLguf60eI</guid>
            <dc:creator>Ashcon Partovi</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare architecture and how BPF eats the world]]></title>
            <link>https://blog.cloudflare.com/cloudflare-architecture-and-how-bpf-eats-the-world/</link>
            <pubDate>Sat, 18 May 2019 15:00:00 GMT</pubDate>
            <description><![CDATA[ Recently at I gave a short talk titled "Linux at Cloudflare". The talk ended up being mostly about BPF. It seems, no matter the question - BPF is the answer.

Here is a transcript of a slightly adjusted version of that talk. ]]></description>
            <content:encoded><![CDATA[ <p>Recently at <a href="https://www.netdevconf.org/0x13/schedule.html">Netdev 0x13</a>, the Conference on Linux Networking in Prague, I gave <a href="https://netdevconf.org/0x13/session.html?panel-industry-perspectives">a short talk titled "Linux at Cloudflare"</a>. The <a href="https://speakerdeck.com/majek04/linux-at-cloudflare">talk</a> ended up being mostly about BPF. It seems, no matter the question - BPF is the answer.</p><p>Here is a transcript of a slightly adjusted version of that talk.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1jvISZgDDA9AnXaBAJzYys/13b124e1f305c9ab4594db66f9123789/01_edge-network-locations-100.jpg" />
            
            </figure><p>At Cloudflare we run Linux on our servers. We operate two categories of data centers: large "Core" data centers, processing logs, analyzing attacks, computing analytics, and the "Edge" server fleet, delivering customer content from 180 locations across the world.</p><p>In this talk, we will focus on the "Edge" servers. It's here where we use the newest Linux features, optimize for performance and care deeply about DoS resilience.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2L3Wbz94VfdflLpsTuIp9D/8b11fa614a4cc1134e4d4df466464425/image-9.png" />
            
            </figure><p>Our edge service is special due to our network configuration - we are extensively using anycast routing. Anycast means that the same set of IP addresses are announced by all our data centers.</p><p>This design has great advantages. First, it guarantees the optimal speed for end users. No matter where you are located, you will always reach the closest data center. Then, anycast helps us to spread out DoS traffic. During attacks each of the locations receives a small fraction of the total traffic, making it easier to ingest and filter out unwanted traffic.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4xiYwbjJRCpt76iDITKowY/9800bb2637bb3f601ccbc7c6eedb6b36/03_edge-network-uniform-software-100-1.jpg" />
            
            </figure><p>Anycast allows us to keep the networking setup uniform across all edge data centers. We applied the same design inside our data centers - our software stack is uniform across the edge servers. All software pieces are running on all the servers.</p><p>In principle, every machine can handle every task - and we run many diverse and demanding tasks. We have a full HTTP stack, the magical <a href="https://www.cloudflare.com/developer-platform/workers/">Cloudflare Workers</a>, two sets of DNS servers - authoritative and resolver, and many other publicly facing applications like <a href="https://www.cloudflare.com/application-services/products/cloudflare-spectrum/">Spectrum</a> and <a href="https://www.cloudflare.com/learning/dns/what-is-1.1.1.1/">Warp</a>.</p><p>Even though every server has all the software running, requests typically cross many machines on their journey through the stack. For example, an HTTP request might be handled by a different machine during each of the 5 stages of the processing.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/268deIgT4XLrgXfhRXxfx1/a5ced85738359d15ee16f9238ac759d8/image-23.png" />
            
            </figure><p>Let me walk you through the early stages of inbound packet processing:</p><p>(1) First, the packets hit our router. The router does ECMP, and forwards packets onto our Linux servers. We use ECMP to spread each target IP across many, at least 16, machines. This is used as a rudimentary load balancing technique.</p><p>(2) On the servers we ingest packets with XDP eBPF. In XDP we perform two stages. First, we run volumetric <a href="https://www.cloudflare.com/learning/ddos/ddos-mitigation/">DoS mitigations</a>, dropping packets belonging to very large layer 3 attacks.</p><p>(3) Then, still in XDP, we perform layer 4 <a href="https://www.cloudflare.com/learning/performance/what-is-load-balancing/">load balancing</a>. All the non-attack packets are redirected across the machines. This is used to work around the ECMP problems, gives us fine-granularity load balancing and allows us to gracefully take servers out of service.</p><p>(4) Following the redirection the packets reach a designated machine. At this point they are ingested by the normal Linux networking stack, go through the usual iptables firewall, and are dispatched to an appropriate network socket.</p><p>(5) Finally packets are received by an application. For example HTTP connections are handled by a "protocol" server, responsible for performing TLS encryption and processing HTTP, HTTP/2 and QUIC protocols.</p><p>It's in these early phases of request processing where we use the coolest new Linux features. We can group useful modern functionalities into three categories:</p><ul><li><p>DoS handling</p></li><li><p>Load balancing</p></li><li><p>Socket dispatch</p></li></ul><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3IlhL5q8CplwN5H1BY0ZZo/7f73d7d4c662113fac18404bcfac96c4/image-25.png" />
            
            </figure><p>Let's discuss DoS handling in more detail. As mentioned earlier, the first step after ECMP routing is Linux's XDP stack where, among other things, we run DoS mitigations.</p><p>Historically our mitigations for volumetric attacks were expressed in classic BPF and iptables-style grammar. Recently we adapted them to execute in the XDP eBPF context, which turned out to be surprisingly hard. Read on about our adventures:</p><ul><li><p><a href="/l4drop-xdp-ebpf-based-ddos-mitigations/">L4Drop: XDP DDoS Mitigations</a></p></li><li><p><a href="/xdpcap/">xdpcap: XDP Packet Capture</a></p></li><li><p><a href="https://netdevconf.org/0x13/session.html?talk-XDP-based-DDoS-mitigation">XDP based DoS mitigation</a> talk by Arthur Fabre</p></li><li><p><a href="https://netdevconf.org/2.1/papers/Gilberto_Bertin_XDP_in_practice.pdf">XDP in practice: integrating XDP into our DDoS mitigation pipeline</a> (PDF)</p></li></ul><p>During this project we encountered a number of eBPF/XDP limitations. One of them was the lack of concurrency primitives. It was very hard to implement things like race-free token buckets. Later we found that <a href="http://vger.kernel.org/lpc-bpf2018.html#session-9">Facebook engineer Julia Kartseva</a> had the same issues. In February this problem has been addressed with the introduction of <code>bpf_spin_lock</code> helper.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2LAXf4Ayxh2sRR3hIsbBja/f8be1df5b19b10954b6a4ad092a177f7/image-26.png" />
            
            </figure><p>While our modern volumetric DoS defenses are done in XDP layer, we still rely on <code>iptables</code> for application layer 7 mitigations. Here, a higher level firewall’s features are useful: connlimit, hashlimits and ipsets. We also use the <code>xt_bpf</code> iptables module to run cBPF in iptables to match on packet payloads. We talked about this in the past:</p><ul><li><p><a href="https://speakerdeck.com/majek04/lessons-from-defending-the-indefensible">Lessons from defending the indefensible</a> (PPT)</p></li><li><p><a href="/introducing-the-bpf-tools/">Introducing the BPF tools</a></p></li></ul><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7MhIUEVsoocz1OSd8FKeYZ/a9e4321a070cd2d49800e978eb50b2d7/image-34.png" />
            
            </figure><p>After XDP and iptables, we have one final kernel side DoS defense layer.</p><p>Consider a situation when our UDP mitigations fail. In such case we might be left with a flood of packets hitting our application UDP socket. This might overflow the socket causing packet loss. This is problematic - both good and bad packets will be dropped indiscriminately. For applications like DNS it's catastrophic. In the past to reduce the harm, we ran one UDP socket per IP address. An unmitigated flood was bad, but at least it didn't affect the traffic to other server IP addresses.</p><p>Nowadays that architecture is no longer suitable. We are running more than 30,000 DNS IP's and running that number of UDP sockets is not optimal. Our modern solution is to run a single UDP socket with a complex eBPF socket filter on it - using the <code>SO_ATTACH_BPF</code> socket option. We talked about running eBPF on network sockets in past blog posts:</p><ul><li><p><a href="/epbf_sockets_hop_distance/">eBPF, Sockets, Hop Distance and manually writing eBPF assembly</a></p></li><li><p><a href="/sockmap-tcp-splicing-of-the-future/">SOCKMAP - TCP splicing of the future</a></p></li></ul><p>The mentioned eBPF rate limits the packets. It keeps the state - packet counts - in an eBPF map. We can be sure that a single flooded IP won't affect other traffic. This works well, though during work on this project we found a rather worrying bug in the eBPF verifier:</p><ul><li><p><a href="/ebpf-cant-count/">eBPF can't count?!</a></p></li></ul><p>I guess running eBPF on a UDP socket is not a common thing to do.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/79bzCglYGH8Vb2hH6R9j39/39aa41a6e11b5cb0dc7f640cd7d7aa72/image-27.png" />
            
            </figure><p>Apart from the DoS, in XDP we also run a layer 4 load balancer layer. This is a new project, and we haven't talked much about it yet. Without getting into many details: in certain situations we need to perform a socket lookup from XDP.</p><p>The problem is relatively simple - our code needs to look up the "socket" kernel structure for a 5-tuple extracted from a packet. This is generally easy - there is a <code>bpf_sk_lookup</code> helper available for this. Unsurprisingly, there were some complications. One problem was the inability to verify if a received ACK packet was a valid part of a three-way handshake when SYN-cookies are enabled. My colleague Lorenz Bauer is working on adding support for this corner case.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6j7ypFSgorN0lWBNY6Nc2m/b0ca29a08e3a1623a5f8c06c213f8d97/image-28.png" />
            
            </figure><p>After DoS and the load balancing layers, the packets are passed onto the usual Linux TCP / UDP stack. Here we do a socket dispatch - for example packets going to port 53 are passed onto a socket belonging to our DNS server.</p><p>We do our best to use vanilla Linux features, but things get complex when you use thousands of IP addresses on the servers.</p><p>Convincing Linux to route packets correctly is relatively easy with <a href="/how-we-built-spectrum">the "AnyIP" trick</a>. Ensuring packets are dispatched to the right application is another matter. Unfortunately, standard Linux socket dispatch logic is not flexible enough for our needs. For popular ports like TCP/80 we want to share the port between multiple applications, each handling it on a different IP range. Linux doesn't support this out of the box. You can call <code>bind()</code> either on a specific IP address or all IP's (with 0.0.0.0).</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2ERTm7jhXbKKfdo3CVmV81/2c8b5986539832c73971269a6bcf0964/image-29.png" />
            
            </figure><p>In order to fix this, we developed a custom kernel patch which adds <a href="http://patchwork.ozlabs.org/patch/602916/">a <code>SO_BINDTOPREFIX</code> socket option</a>. As the name suggests - it allows us to call <code>bind()</code> on a selected IP prefix. This solves the problem of multiple applications sharing popular ports like 53 or 80.</p><p>Then we run into another problem. For our Spectrum product we need to listen on all 65535 ports. Running so many listen sockets is not a good idea (see <a href="/revenge-listening-sockets/">our old war story blog</a>), so we had to find another way. After some experiments we learned to utilize an obscure iptables module - TPROXY - for this purpose. Read about it here:</p><ul><li><p><a href="/how-we-built-spectrum/">Abusing Linux's firewall: the hack that allowed us to build Spectrum</a></p></li></ul><p>This setup is working, but we don't like the extra firewall rules. We are working on solving this problem correctly - actually extending the socket dispatch logic. You guessed it - we want to extend socket dispatch logic by utilizing eBPF. Expect some patches from us.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5eEog6Kt512U7uVmD5DVt8/d8216cc24e674f5f86b1d385bf93dfc5/image-32.png" />
            
            </figure><p>Then there is a way to use eBPF to improve applications. Recently we got excited about doing TCP splicing with SOCKMAP:</p><ul><li><p><a href="/sockmap-tcp-splicing-of-the-future/">SOCKMAP - TCP splicing of the future</a></p></li></ul><p>This technique has a great potential for improving tail latency across many pieces of our software stack. The current SOCKMAP implementation is not quite ready for prime time yet, but the potential is vast.</p><p>Similarly, the new <a href="https://netdevconf.org/2.2/papers/brakmo-tcpbpf-talk.pdf">TCP-BPF aka BPF_SOCK_OPS</a> hooks provide a great way of inspecting performance parameters of TCP flows. This functionality is super useful for our performance team.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1MC8LLNDHLZ4wDYLcbbCHQ/3491b09f9b5eaf796457eb06781f8b98/12_prometheus-ebpf_exporter-100.jpg" />
            
            </figure><p>Some Linux features didn't age well and we need to work around them. For example, we are hitting limitations of networking metrics. Don't get me wrong - the networking metrics are awesome, but sadly they are not granular enough. Things like <code>TcpExtListenDrops</code> and <code>TcpExtListenOverflows</code> are reported as global counters, while we need to know it on a per-application basis.</p><p>Our solution is to use eBPF probes to extract the numbers directly from the kernel. My colleague Ivan Babrou wrote a Prometheus metrics exporter called "ebpf_exporter" to facilitate this. Read on:</p><ul><li><p><a href="/introducing-ebpf_exporter/">Introducing ebpf_exporter</a></p></li><li><p><a href="https://github.com/cloudflare/ebpf_exporter">https://github.com/cloudflare/ebpf_exporter</a></p></li></ul><p>With "ebpf_exporter" we can generate all manner of detailed metrics. It is very powerful and saved us on many occasions.</p><hr />
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1obSUWhzzUQxg8cmDqQ0Lr/15e6419a78802c4d19fc4d21bf161738/image-33.png" />
            
            </figure><p>In this talk we discussed 6 layers of BPFs running on our edge servers:</p><ul><li><p>Volumetric DoS mitigations are running on XDP eBPF</p></li><li><p>Iptables <code>xt_bpf</code> cBPF for application-layer attacks</p></li><li><p><code>SO_ATTACH_BPF</code> for rate limits on UDP sockets</p></li><li><p>Load balancer, running on XDP</p></li><li><p>eBPFs running application helpers like SOCKMAP for TCP socket splicing, and TCP-BPF for TCP measurements</p></li><li><p>"ebpf_exporter" for granular metrics</p></li></ul><p>And we're just getting started! Soon we will be doing more with eBPF based socket dispatch, eBPF running on <a href="https://linux.die.net/man/8/tc">Linux TC (Traffic Control)</a> layer and more integration with cgroup eBPF hooks. Then, our SRE team is maintaining ever-growing list of <a href="https://github.com/iovisor/bcc">BCC scripts</a> useful for debugging.</p><p>It feels like Linux stopped developing new API's and all the new features are implemented as eBPF hooks and helpers. This is fine and it has strong advantages. It's easier and safer to upgrade eBPF program than having to recompile a kernel module. Some things like TCP-BPF, exposing high-volume performance tracing data, would probably be impossible without eBPF.</p><p>Some say "software is eating the world", I would say that: "BPF is eating the software".</p> ]]></content:encoded>
            <category><![CDATA[eBPF]]></category>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Anycast]]></category>
            <category><![CDATA[TCP]]></category>
            <guid isPermaLink="false">5EXsVZKcFTNLXVbrgHx73a</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
        <item>
            <title><![CDATA[eBPF can't count?!]]></title>
            <link>https://blog.cloudflare.com/ebpf-cant-count/</link>
            <pubDate>Fri, 03 May 2019 13:00:00 GMT</pubDate>
            <description><![CDATA[ It is unlikely we can tell you anything new about the extended Berkeley Packet Filter, eBPF for short, if you've read all the great man pages, docs, guides, and some of our blogs out there. But we can tell you a war story, who doesn't like those?  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Grant mechanical calculating machine, public domain <a href="https://en.wikipedia.org/wiki/File:Grant_mechanical_calculating_machine_1877.jpg">image</a></p><p>It is unlikely we can tell you anything new about the extended Berkeley Packet Filter, eBPF for short, if you've read all the great <a href="http://man7.org/linux/man-pages/man2/bpf.2.html">man pages</a>, <a href="https://www.kernel.org/doc/Documentation/networking/filter.txt">docs</a>, <a href="https://cilium.readthedocs.io/en/latest/bpf/">guides</a>, and some of our <a href="https://blog.cloudflare.com/epbf_sockets_hop_distance/">blogs</a> out there.</p><p>But we can tell you a war story, and who doesn't like those? This one is about how eBPF lost its ability to count for a while<a href="#f1"><sup>1</sup></a>.</p><p>They say in our Austin, Texas office that all good stories start with "y'all ain't gonna believe this… tale." This one though, starts with a <a href="https://lore.kernel.org/netdev/CAJPywTJqP34cK20iLM5YmUMz9KXQOdu1-+BZrGMAGgLuBWz7fg@mail.gmail.com/">post</a> to Linux netdev mailing list from <a href="https://twitter.com/majek04">Marek Majkowski</a> after what I heard was a long night:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2z8UE9I87Kpw8ONzxBH3WW/96500c2ee678248af9c22936bb49cdee/ebpf_bug_email_netdev.png" />
            
            </figure><p>Marek's findings were quite shocking - if you subtract two 64-bit timestamps in eBPF, the result is garbage. But only when running as an unprivileged user. From root all works fine. Huh.</p><p>If you've seen Marek's <a href="https://speakerdeck.com/majek04/linux-at-cloudflare">presentation</a> from the Netdev 0x13 conference, you know that we are using BPF socket filters as one of the defenses against simple, volumetric DoS attacks. So potentially getting your packet count wrong could be a Bad Thing™, and affect legitimate traffic.</p><p>Let's try to reproduce this bug with a simplified <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/bpf/filter.c#L63">eBPF socket filter</a> that subtracts two 64-bit unsigned integers passed to it from <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/run_bpf.go#L93">user-space</a> though a BPF map. The input for our BPF program comes from a <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/bpf/filter.c#L44">BPF array map</a>, so that the values we operate on are not known at build time. This allows for easy experimentation and prevents the compiler from optimizing out the operations.</p><p>Starting small, eBPF, what is 2 - 1? View the code <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/run_bpf.go#L93">on our GitHub</a>.</p>
            <pre><code>$ ./run-bpf 2 1
arg0                    2 0x0000000000000002
arg1                    1 0x0000000000000001
diff                    1 0x0000000000000001</code></pre>
            <p>OK, eBPF, what is 2^32 - 1?</p>
            <pre><code>$ ./run-bpf $[2**32] 1
arg0           4294967296 0x0000000100000000
arg1                    1 0x0000000000000001
diff 18446744073709551615 0xffffffffffffffff</code></pre>
            <p>Wrong! But if we ask nicely with sudo:</p>
            <pre><code>$ sudo ./run-bpf $[2**32] 1
[sudo] password for jkbs:
arg0           4294967296 0x0000000100000000
arg1                    1 0x0000000000000001
diff           4294967295 0x00000000ffffffff</code></pre>
            
    <div>
      <h3>Who is messing with my eBPF?</h3>
      <a href="#who-is-messing-with-my-ebpf">
        
      </a>
    </div>
    <p>When computers stop subtracting, you know something big is up. We called for reinforcements.</p><p>Our colleague Arthur Fabre <a href="https://lore.kernel.org/netdev/20190301113901.29448-1-afabre@cloudflare.com/">quickly noticed</a> something is off when you examine the eBPF code loaded into the kernel. It turns out kernel doesn't actually run the eBPF it's supplied - it sometimes rewrites it first.</p><p>Any sane programmer would expect 64-bit subtraction to be expressed as <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/bpf/filter.s#L47">a single eBPF instruction</a></p>
            <pre><code>$ llvm-objdump -S -no-show-raw-insn -section=socket1 bpf/filter.o
…
      20:       1f 76 00 00 00 00 00 00         r6 -= r7
…</code></pre>
            <p>However, that's not what the kernel actually runs. Apparently after the rewrite the subtraction becomes a complex, multi-step operation.</p><p>To see what the kernel is actually running we can use little known <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/bpf/bpftool?h=v5.0">bpftool utility</a>. First, we need to load our BPF</p>
            <pre><code>$ ./run-bpf --stop-after-load 2 1
[2]+  Stopped                 ./run-bpf 2 1</code></pre>
            <p>Then list all BPF programs loaded into the kernel with <code>bpftool prog list</code></p>
            <pre><code>$ sudo bpftool prog list
…
5951: socket_filter  name filter_alu64  tag 11186be60c0d0c0f  gpl
        loaded_at 2019-04-05T13:01:24+0200  uid 1000
        xlated 424B  jited 262B  memlock 4096B  map_ids 28786</code></pre>
            <p>The most recently loaded <code>socket_filter</code> must be our program (<code>filter_alu64</code>). Now we now know its id is 5951 and we can list its bytecode with</p>
            <pre><code>$ sudo bpftool prog dump xlated id 5951
…
  33: (79) r7 = *(u64 *)(r0 +0)
  34: (b4) (u32) r11 = (u32) -1
  35: (1f) r11 -= r6
  36: (4f) r11 |= r6
  37: (87) r11 = -r11
  38: (c7) r11 s&gt;&gt;= 63
  39: (5f) r6 &amp;= r11
  40: (1f) r6 -= r7
  41: (7b) *(u64 *)(r10 -16) = r6
…</code></pre>
            <p>bpftool can also display the JITed code with: <code>bpftool prog dump jited id 5951</code>.</p><p>As you see, subtraction is replaced with a series of opcodes. That is unless you are root. When running from root all is good</p>
            <pre><code>$ sudo ./run-bpf --stop-after-load 0 0
[1]+  Stopped                 sudo ./run-bpf --stop-after-load 0 0
$ sudo bpftool prog list | grep socket_filter
659: socket_filter  name filter_alu64  tag 9e7ffb08218476f3  gpl
$ sudo bpftool prog dump xlated id 659
…
  31: (79) r7 = *(u64 *)(r0 +0)
  32: (1f) r6 -= r7
  33: (7b) *(u64 *)(r10 -16) = r6
…</code></pre>
            <p>If you've spent any time using eBPF, you must have experienced first hand the dreaded eBPF verifier. It's a merciless judge of all eBPF code that will reject any programs that it deems not worthy of running in kernel-space.</p><p>What perhaps nobody has told you before, and what might come as a surprise, is that the very same verifier will actually also <a href="https://elixir.bootlin.com/linux/v4.20.13/source/kernel/bpf/verifier.c#L6421">rewrite and patch up your eBPF code</a> as needed to make it safe.</p><p>The problems with subtraction were introduced by an inconspicuous security fix to the verifier. The patch in question first landed in Linux 5.0 and was backported to 4.20.6 stable and 4.19.19 LTS kernel. <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=979d63d50c0c0f7bc537bf821e056cc9fe5abd38">The over 2000 words long commit message</a> doesn't spare you any details on the attack vector it targets.</p><p>The mitigation stems from <a href="https://nvd.nist.gov/vuln/detail/CVE-2019-7308">CVE-2019-7308</a> vulnerability <a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1711">discovered by Jann Horn at Project Zero</a>, which exploits pointer arithmetic, i.e. adding a scalar value to a pointer, to trigger speculative memory loads from out-of-bounds addresses. Such speculative loads change the CPU cache state and can be used to mount a <a href="https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html">Spectre variant 1 attack</a>.</p><p>To mitigate it the eBPF verifier rewrites any arithmetic operations on pointer values in such a way the result is always a memory location within bounds. The patch demonstrates how arithmetic operations on pointers get rewritten and we can spot a familiar pattern there</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/8irnzqpgIARBl3UdtS30S/5e885701ef2fe3a9426b1e960e48f0d1/bpf_commit.png" />
            
            </figure><p>Wait a minute… What pointer arithmetic? We are just trying to subtract two scalar values. How come the mitigation kicks in?</p><p>It shouldn't. It's a bug. The eBPF verifier keeps track of what kind of values the ALU is operating on, and in this corner case the state was ignored.</p><p>Why running BPF as root is fine, you ask? If your program has <code>CAP_SYS_ADMIN</code> privileges, side-channel mitigations <a href="https://elixir.bootlin.com/linux/v5.0/source/kernel/bpf/verifier.c#L7218">don't</a> <a href="https://elixir.bootlin.com/linux/v5.0/source/kernel/bpf/verifier.c#L3109">apply</a>. As root you already have access to kernel address space, so nothing new can leak through BPF.</p><p>After our report, <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3612af783cf52c74a031a2f11b82247b2599d3cd">the fix</a> has quickly landed in v5.0 kernel and got backported to stable kernels 4.20.15 and 4.19.28. Kudos to Daniel Borkmann for getting the fix out fast. However, kernel upgrades are hard and in the meantime we were left with code running in production that was not doing what it was supposed to.</p>
    <div>
      <h3>32-bit ALU to the rescue</h3>
      <a href="#32-bit-alu-to-the-rescue">
        
      </a>
    </div>
    <p>As one of the eBPF maintainers <a href="https://lore.kernel.org/netdev/af0643e0-08a1-6326-2a80-71892de1bf56@iogearbox.net/">has pointed out</a>, 32-bit arithmetic operations are not affected by the verifier bug. This opens a door for a work-around.</p><p>eBPF registers, <code>r0</code>..<code>r10</code>, are 64-bits wide, but you can also access just the lower 32 bits, which are exposed as subregisters <code>w0</code>..<code>w10</code>. You can operate on the 32-bit subregisters using BPF ALU32 instruction subset. LLVM 7+ can generate eBPF code that uses this instruction subset. Of course, you need to you ask it nicely with trivial <code>-Xclang -target-feature -Xclang +alu32</code> toggle:</p>
            <pre><code>$ cat sub32.c
#include "common.h"

u32 sub32(u32 x, u32 y)
{
        return x - y;
}
$ clang -O2 -target bpf -Xclang -target-feature -Xclang +alu32 -c sub32.c
$ llvm-objdump -S -no-show-raw-insn sub32.o
…
sub32:
       0:       bc 10 00 00 00 00 00 00         w0 = w1
       1:       1c 20 00 00 00 00 00 00         w0 -= w2
       2:       95 00 00 00 00 00 00 00         exit</code></pre>
            <p>The <code>0x1c</code> <a href="https://elixir.bootlin.com/linux/v5.0/source/include/uapi/linux/bpf_common.h#L11">opcode</a> of the instruction #1, which can be broken down as <code>BPF_ALU | BPF_X | BPF_SUB</code> (read more in the <a href="https://www.kernel.org/doc/Documentation/networking/filter.txt">kernel docs</a>), is the 32-bit subtraction between registers we are looking for, as opposed to regular 64-bit subtract operation <code>0x1f = BPF_ALU64 | BPF_X | BPF_SUB</code>, which will get rewritten.</p><p>Armed with this knowledge we can borrow a page from <a href="https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic">bignum arithmetic</a> and subtract 64-bit numbers using just 32-bit ops:</p>
            <pre><code>u64 sub64(u64 x, u64 y)
{
        u32 xh, xl, yh, yl;
        u32 hi, lo;

        xl = x;
        yl = y;
        lo = xl - yl;

        xh = x &gt;&gt; 32;
        yh = y &gt;&gt; 32;
        hi = xh - yh - (lo &gt; xl); /* underflow? */

        return ((u64)hi &lt;&lt; 32) | (u64)lo;
}</code></pre>
            <p>This code compiles as expected on normal architectures, like x86-64 or ARM64, but BPF Clang target plays by its own rules:</p>
            <pre><code>$ clang -O2 -target bpf -Xclang -target-feature -Xclang +alu32 -c sub64.c -o - \
  | llvm-objdump -S -
…  
      13:       1f 40 00 00 00 00 00 00         r0 -= r4
      14:       1f 30 00 00 00 00 00 00         r0 -= r3
      15:       1f 21 00 00 00 00 00 00         r1 -= r2
      16:       67 00 00 00 20 00 00 00         r0 &lt;&lt;= 32
      17:       67 01 00 00 20 00 00 00         r1 &lt;&lt;= 32
      18:       77 01 00 00 20 00 00 00         r1 &gt;&gt;= 32
      19:       4f 10 00 00 00 00 00 00         r0 |= r1
      20:       95 00 00 00 00 00 00 00         exit</code></pre>
            <p>Apparently the compiler decided it was better to operate on 64-bit registers and discard the upper 32 bits. Thus we weren't able to get rid of the problematic <code>0x1f</code> opcode. Annoying, back to square one.</p>
    <div>
      <h3>Surely a bit of IR will do?</h3>
      <a href="#surely-a-bit-of-ir-will-do">
        
      </a>
    </div>
    <p>The problem was in Clang frontend - compiling C to IR. We know that BPF "assembly" backend for LLVM can generate bytecode that uses ALU32 instructions. Maybe if we tweak the Clang compiler's output just a little we can achieve what we want. This means we have to get our hands dirty with the LLVM Intermediate Representation (IR).</p><p>If you haven't heard of LLVM IR before, now is a good time to do some <a href="http://www.aosabook.org/en/llvm.html">reading</a><a href="#f2"><sup>2</sup></a>. In short the LLVM IR is what Clang produces and LLVM BPF backend consumes.</p><p>Time to write IR by hand! Here's a hand-tweaked <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/bpf/sub64_ir.ll#L7">IR variant</a> of our <code>sub64()</code> function:</p>
            <pre><code>define dso_local i64 @sub64_ir(i64, i64) local_unnamed_addr #0 {
  %3 = trunc i64 %0 to i32      ; xl = (u32) x;
  %4 = trunc i64 %1 to i32      ; yl = (u32) y;
  %5 = sub i32 %3, %4           ; lo = xl - yl;
  %6 = zext i32 %5 to i64
  %7 = lshr i64 %0, 32          ; tmp1 = x &gt;&gt; 32;
  %8 = lshr i64 %1, 32          ; tmp2 = y &gt;&gt; 32;
  %9 = trunc i64 %7 to i32      ; xh = (u32) tmp1;
  %10 = trunc i64 %8 to i32     ; yh = (u32) tmp2;
  %11 = sub i32 %9, %10         ; hi = xh - yh
  %12 = icmp ult i32 %3, %5     ; tmp3 = xl &lt; lo
  %13 = zext i1 %12 to i32
  %14 = sub i32 %11, %13        ; hi -= tmp3
  %15 = zext i32 %14 to i64
  %16 = shl i64 %15, 32         ; tmp2 = hi &lt;&lt; 32
  %17 = or i64 %16, %6          ; res = tmp2 | (u64)lo
  ret i64 %17
}</code></pre>
            <p>It may not be pretty but it does produce <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/bpf/sub64_ir.s#L5">desired BPF code</a> when compiled<a href="#f3"><sup>3</sup></a>. You will likely find the <a href="https://llvm.org/docs/LangRef.html">LLVM IR reference</a> helpful when deciphering it.</p><p>And voila! First working solution that produces correct results:</p>
            <pre><code>$ ./run-bpf -filter ir $[2**32] 1
arg0           4294967296 0x0000000100000000
arg1                    1 0x0000000000000001
diff           4294967295 0x00000000ffffffff</code></pre>
            <p>Actually using this hand-written IR function from C is tricky. See <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/build.ninja#L27">our code on GitHub</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6zQLSvXLH19lXCjYnstl2a/f8fb73710fc8e5eda96476006974eea5/LED_DISP-1.JPG.jpeg" />
            
            </figure><p>public domain <a href="https://en.wikipedia.org/wiki/File:LED_DISP.JPG">image</a> by <a href="https://commons.wikimedia.org/wiki/User:Sergei_Frolov">Sergei Frolov</a></p>
    <div>
      <h3>The final trick</h3>
      <a href="#the-final-trick">
        
      </a>
    </div>
    <p>Hand-written IR does the job. The downside is that linking IR modules to your C modules is hard. Fortunately there is a better way. You can persuade Clang to stick to 32-bit ALU ops in generated IR.</p><p>We've already seen the problem. To recap, if we ask Clang to subtract 32-bit integers, it will operate on 64-bit values and throw away the top 32-bits. Putting C, IR, and eBPF side-by-side helps visualize this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/33bbylbcFR7zuF7NwxHcTs/fa9f110a71ab6e5f5cf8f7d70aadd587/sub32_v1.png" />
            
            </figure><p>The trick to get around it is to declare the 32-bit variable that holds the result as <code>volatile</code>. You might already know the <a href="https://en.wikipedia.org/wiki/Volatile_(computer_programming)"><code>volatile</code> keyword</a> if you've written Unix signal handlers. It basically tells the compiler that the value of the variable may change under its feet so it should refrain from reorganizing loads (reads) from it, as well as that stores (writes) to it might have side-effects so changing the order or eliminating them, by skipping writing it to the memory, is not allowed either.</p><p>Using <code>volatile</code> makes Clang emit <a href="https://llvm.org/docs/LangRef.html#volatile-memory-accesses">special loads and/or stores</a> at the IR level, which then on eBPF level translates to writing/reading the value from memory (stack) on every access. While this sounds not related to the problem at hand, there is a surprising side-effect to it:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2fEaCu15LmmeauGv7Vh1Wb/354c4a8aa60da7a7e5797fe0f951508d/sub32_v2.png" />
            
            </figure><p>With volatile access compiler doesn't promote the subtraction to 64 bits! Don't ask me why, although I would love to hear an explanation. For now, consider this a hack. One that does not come for free - there is the overhead of going through the stack on each read/write.</p><p>However, if we play our cards right we just might reduce it a little. We don't actually need the volatile load or store to happen, we just want the side effect. So instead of declaring the value as volatile, which implies that both reads and writes are volatile, let's try to make only the writes volatile with a help of a macro:</p>
            <pre><code>/* Emits a "store volatile" in LLVM IR */
#define ST_V(rhs, lhs) (*(volatile typeof(rhs) *) &amp;(rhs) = (lhs))</code></pre>
            <p>If this macro looks strangely familiar, it's because it does the same thing as <a href="https://elixir.bootlin.com/linux/v5.1-rc5/source/include/linux/compiler.h#L214"><code>WRITE_ONCE()</code> macro</a> in the Linux kernel. Applying it to our example:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3qQ1CrUvUBsJJE09xVqzA1/bc84a1c3fdd5a855c505c56c2273e664/sub32_v3.png" />
            
            </figure><p>That's another <a href="https://github.com/cloudflare/cloudflare-blog/blob/master/2019-04-ebpf-alu32/bpf/filter.c#L143">hacky but working solution</a>. Pick your poison.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/28GXw3wm8YlUgg9nvnBwEx/2939bf7b36758a66685385e16a48cc5f/poison_bottles-2.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by-sa/3.0/">CC BY-SA 3.0</a> <a href="https://commons.wikimedia.org/wiki/File:D-BW-Kressbronn_aB_-_Kl%C3%A4ranlage_067.jpg">image</a> by ANKAWÜ</p><p>So there you have it - from C, to IR, and back to C to hack around a bug in eBPF verifier and be able to subtract 64-bit integers again. Usually you won't have to dive into LLVM IR or assembly to make use of eBPF. But it does help to know a little about it when things don't work as expected.</p><p>Did I mention that 64-bit addition is also broken? Have fun fixing it!</p><hr /><p><sup>1</sup> Okay, it was more like 3 months time until the bug was discovered and fixed.</p><p><sup>2</sup> Some even think that it is <a href="https://idea.popcount.org/2013-07-24-ir-is-better-than-assembly/">better than assembly</a>.</p><p><sup>3</sup> How do we know? The litmus test is to look for statements matching <code>r[0-9] [-+]= r[0-9]</code> in BPF assembly.</p> ]]></content:encoded>
            <category><![CDATA[eBPF]]></category>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">2fXVvP0CJO4Bt4KuJthpbx</guid>
            <dc:creator>Jakub Sitnicki</dc:creator>
        </item>
        <item>
            <title><![CDATA[xdpcap: XDP Packet Capture]]></title>
            <link>https://blog.cloudflare.com/xdpcap/</link>
            <pubDate>Wed, 24 Apr 2019 18:21:59 GMT</pubDate>
            <description><![CDATA[ Our servers manage heaps of network packets, from legit traffic to big DDoS attacks. For top efficiency, we adopted eXpress Data Path (XDP), a Linux kernel tool for swift, low-level packet handling. ]]></description>
            <content:encoded><![CDATA[ <p>Our servers process a lot of network packets, be it legitimate traffic or <a href="/say-cheese-a-snapshot-of-the-massive-ddos-attacks-coming-from-iot-cameras/">large</a> <a href="/how-the-consumer-product-safety-commission-is-inadvertently-behind-the-internets-largest-ddos-attacks/">denial of service</a> <a href="/reflections-on-reflections/">attacks</a>. To do so efficiently, we’ve embraced <a href="http://docs.cilium.io/en/latest/bpf/">eXpress Data Path (XDP)</a>, a Linux kernel technology that provides a high performance mechanism for low level packet processing. We’re using it to <a href="/l4drop-xdp-ebpf-based-ddos-mitigations/">drop DoS attack packets with L4Drop</a>, and also in our new layer 4 load balancer. But there’s a downside to XDP: because it processes packets before the normal Linux network stack sees them, packets redirected or dropped are invisible to regular debugging tools such as <a href="https://www.tcpdump.org/">tcpdump</a>.</p><p>To address this, we built a tcpdump replacement for XDP, xdpcap. We are open sourcing this tool: the <a href="https://github.com/cloudflare/xdpcap">code and documentation are available on GitHub</a>.</p><p>xdpcap uses our classic BPF (cBPF) to eBPF or C compiler, cbpfc, which we are also open sourcing: the <a href="https://github.com/cloudflare/cbpfc">code and documentation are available on GitHub</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1X6o2OMKm5ePt10Xm3Vgpr/deb5e63073ba5b69d08be1e41ba4344b/White_tailed_eagle_raftsund_square_crop.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> <a href="https://commons.wikimedia.org/wiki/File:White_tailed_eagle_raftsund_square_crop.jpg">image</a> by <a href="http://www.christophmueller.org">Christoph Müller</a></p><p>Tcpdump provides an easy way to dump specific packets of interest. For example, to capture all IPv4 DNS packets, one could:</p>
            <pre><code>$ tcpdump ip and udp port 53</code></pre>
            <p>xdpcap reuses the same syntax! xdpcap can write packets to a pcap file:</p>
            <pre><code>$ xdpcap /path/to/hook capture.pcap "ip and udp port 53"
XDPAborted: 0/0   XDPDrop: 0/0   XDPPass: 254/0   XDPTx: 0/0   (received/matched packets)
XDPAborted: 0/0   XDPDrop: 0/0   XDPPass: 995/1   XDPTx: 0/0   (received/matched packets)</code></pre>
            <p>Or write the pcap to stdout, and decode the packets with tcpdump:</p>
            <pre><code>$ xdpcap /path/to/hook - "ip and udp port 53" | sudo tcpdump -r -
reading from file -, link-type EN10MB (Ethernet)
16:18:37.911670 IP 1.1.1.1 &gt; 1.2.3.4.21563: 26445$ 1/0/1 A 93.184.216.34 (56)</code></pre>
            <p>The remainder of this post explains how we built xdpcap, including how <code>/path/to/hook/</code> is used to attach to XDP programs.</p>
    <div>
      <h2>tcpdump</h2>
      <a href="#tcpdump">
        
      </a>
    </div>
    <p>To replicate tcpdump, we first need to understand its inner workings. <a href="/bpf-the-forgotten-bytecode/">Marek Majkowski has previously written a detailed post on the subject</a>. Tcpdump exposes a high level filter language, <a href="https://www.tcpdump.org/manpages/pcap-filter.7.html">pcap-filter</a>, to specify which packets are of interest. Reusing our earlier example, the following filter expression captures all IPv4 UDP packets to or from port 53, likely DNS traffic:</p>
            <pre><code>ip and udp port 53</code></pre>
            <p>Internally, tcpdump uses libpcap to compile the filter to classic BPF (cBPF). cBPF is a simple bytecode language to represent programs that inspect the contents of a packet. A program returns non-zero to indicate that a packet matched the filter, and zero otherwise. The virtual machine that executes cBPF programs is very simple, featuring only two registers, <code>a</code> and <code>x</code>. There is no way of checking the length of the input packet<a href="/xdpcap/#fn1"><sup>[1]</sup></a>; instead any out of bounds packet access will terminate the cBPF program, returning 0 (no match). The full set of opcodes are listed in <a href="https://www.kernel.org/doc/Documentation/networking/filter.txt">the Linux documentation</a>. Returning to our example filter, <code>ip and udp port 53</code> compiles to the following cBPF program, expressed as an annotated flowchart:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7vcV3QJKDR7VK5bbrI8UKh/738d2cb9fe464ec27cc16dd9f4e08926/Screen-Shot-2019-08-27-at-10.43.41-AM.png" />
            
            </figure><p>Example cBPF filter flowchart</p><p>Tcpdump attaches the generated cBPF filter to a raw packet socket using a <code>setsockopt</code> system call with <code>SO_ATTACH_FILTER</code>. The kernel runs the filter on every packet destined for the socket, but only delivers matching packets. Tcpdump displays the delivered packets, or writes them to a pcap capture file for later analysis.</p>
    <div>
      <h2>xdpcap</h2>
      <a href="#xdpcap">
        
      </a>
    </div>
    <p>In the context of XDP, our tcpdump replacement should:</p><ul><li><p>Accept filters in the same filter language as tcpdump</p></li><li><p>Dynamically instrument XDP programs of interest</p></li><li><p>Expose matching packets to userspace</p></li></ul>
    <div>
      <h3>XDP</h3>
      <a href="#xdp">
        
      </a>
    </div>
    <p>XDP uses an extended version of the cBPF instruction set, eBPF, to allow arbitrary programs to run for each packet received by a network card, potentially modifying the packets. A stringent kernel verifier statically analyzes eBPF programs, ensuring that memory bounds are checked for every packet load.</p><p>eBPF programs can return:</p><ul><li><p><code>XDP_DROP</code>: Drop the packet</p></li><li><p><code>XDP_TX</code>: Transmit the packet back out the network interface</p></li><li><p><code>XDP_PASS</code>: Pass the packet up the network stack</p></li></ul><p>eBPF introduces several new features, notably helper function calls, enabling programs to call functions exposed by the kernel. This includes retrieving or setting values in maps, key-value data structures that can also be accessed from userspace.</p>
    <div>
      <h3>Filter</h3>
      <a href="#filter">
        
      </a>
    </div>
    <p>A key feature of tcpdump is the ability to efficiently pick out packets of interest; packets are filtered before reaching userspace. To achieve this in XDP, the desired filter must be converted to eBPF.</p><p>cBPF is already used in our <a href="/l4drop-xdp-ebpf-based-ddos-mitigations/#bpf-support">XDP based DoS mitigation pipeline</a>: cBPF filters are first converted to C by cbpfc, and the result compiled with Clang to eBPF. Reusing this mechanism allows us to fully support libpcap filter expressions:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2cWmovp2qWyqPw96muVV6Y/4bfb47288ad02579c840042950979158/2-1.png" />
            
            </figure><p>Pipeline to convert pcap-filter expressions to eBPF via C using cbpfc</p><p>To remove the Clang runtime dependency, our cBPF compiler, cbpfc, was extended to directly generate eBPF:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6v22s8MPrGXaJIZwTdq6zk/0bc7df11722b408738234116542a7b3e/3-1.png" />
            
            </figure><p>Pipeline to convert pcap-filter expressions directly to eBPF using cbpfc</p><p>Converted to eBPF using cbpfc, <code>ip and udp port 53</code> yields:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3bMYRG5ajPayvdVoTelezY/6f3d6ed62167bd62ff0a4af51cca81ce/Screen-Shot-2019-08-27-at-10.44.20-AM.png" />
            
            </figure><p>Example cBPF filter converted to eBPF with cbpfc flowchart</p><p>The emitted eBPF requires a prologue, which is responsible for loading a pointer to the beginning, and end, of the input packet into registers <code>r6</code>and <code>r7</code> respectively<a href="/xdpcap/#fn2"><sup>[2]</sup></a>.</p><p>The generated code follows a very similar structure to the original cBPF filter, but with:</p><ul><li><p>Bswap instructions to convert big endian packet data to little endian.</p></li><li><p>Guards to check the length of the packet before we load data from it. These are required by the kernel verifier.</p></li></ul><p>The epilogue can use the result of the filter to perform different actions on the input packet.</p><p>As mentioned earlier, we’re open sourcing cbpfc; <a href="https://github.com/cloudflare/cbpfc">the code and documentation are available on GitHub</a>. It can be used to compile cBPF to C, or directly to eBPF, and the generated code is accepted by the kernel verifier.</p>
    <div>
      <h3>Instrument</h3>
      <a href="#instrument">
        
      </a>
    </div>
    <p>Tcpdump can start and stop capturing packets at any time, without requiring coordination from applications. This rules out modifying existing XDP programs to directly run the generated eBPF filter; the programs would have to be modified each time xdpcap is run. Instead, programs should expose a hook that can be used by xdpcap to attach filters at runtime.</p><p>xdpcap’s hook support is built around eBPF tail-calls. XDP programs can yield control to other programs using the tail-call helper. Control is never handed back to the calling program, the return code of the subsequent program is used. For example, consider two XDP programs, foo and bar, with foo attached to the network interface. Foo can tail-call into bar:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4MaJdTMGs41UECBvq7FqhA/e1919c95963cf44419fefd2a14044c87/5.png" />
            
            </figure><p>Flow of XDP program foo tail-calling into program bar</p><p>The program to tail-call into is configured at runtime, using a special eBPF program array map. eBPF programs tail-call into a specific index of the map, the value of which is set by userspace. From our example above, foo’s tail-call map holds a single entry:</p><table><tr><td><p><b>index</b></p></td><td><p><b>program</b></p></td></tr><tr><td><p>0</p></td><td><p>bar</p></td></tr></table><p>A tail-call into an empty index will not do anything, XDP programs always need to return an action themselves after a tail-call should it fail. Once again, this is enforced by the kernel verifier. In the case of program foo:</p>
            <pre><code>int foo(struct xdp_md *ctx) {
    // tail-call into index 0 - program bar
    tail_call(ctx, &amp;map, 0);

    // tail-call failed, pass the packet
    return XDP_PASS;
}</code></pre>
            <p>To leverage this as a hook point, the instrumented programs are modified to always tail-call, using a map that is exposed to xdpcap by <a href="https://facebookmicrosites.github.io/bpf/blog/2018/08/31/object-lifetime.html#bpffs">pinning it to a bpffs</a>. To attach a filter, xdpcap can set it in the map. If no filter is attached, the instrumented program returns the correct action itself.</p><p>With a filter attached to program foo, we have:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/S8T2hX3KZvC28JFvsQFB7/ffdc88d58cc5cfa5e1027cf1045274b6/6.png" />
            
            </figure><p>Flow of XDP program foo tail-calling into an xdpcap filter</p><p>The filter must return the original action taken by the instrumented program to ensure the packet is processed correctly. To achieve this, xdpcap generates one filter program per possible XDP action, each one hard-coded to return that specific action. All the programs are set in the map:</p><table><tr><td><p><b>index</b></p></td><td><p><b>program</b></p></td></tr><tr><td><p>0 (<code>XDP_ABORTED</code>)</p></td><td><p>filter <code>XDP_ABORTED</code></p></td></tr><tr><td><p>1 (<code>XDP_DROP</code>)</p></td><td><p>filter <code>XDP_DROP</code></p></td></tr><tr><td><p>2 (<code>XDP_PASS</code>)</p></td><td><p>filter <code>XDP_PASS</code></p></td></tr><tr><td><p>3 (<code>XDP_TX</code>)</p></td><td><p>filter <code>XDP_TX</code></p></td></tr></table><p>By tail-calling into the correct index, the instrumented program determines the final action:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3LFc3RSQQ10cP2N4GrAvwY/cd0f7bba4755f21dd1483b1307ffcf0b/7.png" />
            
            </figure><p>Flow of XDP program foo tail-calling into xdpcap filters, one for each action</p><p>xdpcap provides a helper function that attempts a tail-call for the given action. Should it fail, the action is returned instead:</p>
            <pre><code>enum xdp_action xdpcap_exit(struct xdp_md *ctx, enum xdp_action action) {
    // tail-call into the filter using the action as an index
    tail_call((void *)ctx, &amp;xdpcap_hook, action);

    // tail-call failed, return the action
    return action;
}</code></pre>
            <p>This allows an XDP program to simply:</p>
            <pre><code>int foo(struct xdp_md *ctx) {
    return xdpcap_exit(ctx, XDP_PASS);
}</code></pre>
            
    <div>
      <h3>Expose</h3>
      <a href="#expose">
        
      </a>
    </div>
    <p>Matching packets, as well as the original action taken for them, need to be exposed to userspace. Once again, such a mechanism is already part of our <a href="/l4drop-xdp-ebpf-based-ddos-mitigations/#packet-sampling">XDP based DoS mitigation pipeline</a>!</p><p>Another eBPF helper, <code>perf_event_output</code>, allows an XDP program to generate a perf event containing, amongst some metadata, the packet. As xdpcap generates one filter per XDP action, the filter program can include the action taken in the metadata. A userspace program can create a perf event ring buffer to receive events into, obtaining both the action and the packet.</p><ol><li><p>This is true of the original cBPF, but Linux implements a number of extensions, one of which allows the length of the input packet to be retrieved. <a href="/xdpcap/#fnref1">↩︎</a></p></li><li><p>This example uses registers <code>r6</code> and <code>r7</code>, but cbpfc can be configured to use any registers. <a href="/xdpcap/#fnref2">↩︎</a></p></li></ol><p></p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">2uU84JuP2Ez1MTF03l8xwY</guid>
            <dc:creator>Arthur Fabre</dc:creator>
        </item>
        <item>
            <title><![CDATA[Eating Dogfood at Scale: How We Build Serverless Apps with Workers]]></title>
            <link>https://blog.cloudflare.com/building-serverless-apps-with-workers/</link>
            <pubDate>Fri, 19 Apr 2019 13:00:00 GMT</pubDate>
            <description><![CDATA[ You’ve had a chance to build a Cloudflare Worker. You’ve tried KV Storage and have a great use case for your Worker. You’ve even demonstrated the usefulness to your product or organization.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>You’ve had a chance to build a <a href="https://developers.cloudflare.com/workers/about/">Cloudflare Worker</a>. You’ve tried <a href="https://developers.cloudflare.com/workers/kv/">KV Storage</a> and have a great use case for your Worker. You’ve even demonstrated the usefulness to your product or organization. Now you need to go from writing a single file in the Cloudflare Dashboard UI Editor to source controlled code with multiple environments deployed using your favorite CI tool.</p><p>Fortunately, we have a powerful and flexible <a href="https://developers.cloudflare.com/workers/api/">API</a> for managing your workers. You can customize your deployment to your heart’s content. Our blog has already featured many things made possible by that API:</p><ul><li><p><a href="/introducing-wrangler-cli/">The Wrangler CLI</a></p></li><li><p><a href="/a-ci/">CI/CD Pipeline</a></p></li><li><p><a href="/deploying-workers-with-github-actions-serverless/">Github Actions</a></p></li><li><p><a href="/create-cloudflare-worker-bootstrap-your-cloudflare-worker/">Worker bootstrap template</a></p></li></ul><p>These tools make deployments easier to configure, but it still takes time to manage. The <a href="https://serverless.com/">Serverless Framework</a> <a href="https://serverless.com/plugins/serverless-cloudflare-workers/">Cloudflare Workers plugin</a> removes that deployment overhead so you can spend more time working on your application and less on your deployment.</p>
    <div>
      <h3>Focus on your application</h3>
      <a href="#focus-on-your-application">
        
      </a>
    </div>
    <p>Here at Cloudflare, we’ve been working to rebuild our Access product to run entirely on Workers. The move will allow Access to take advantage of the resiliency, performance, and flexibility of Workers. We’ll publish a more detailed post about that migration once complete, but the experience required that we retool some of our process to match or existing development experience as much as possible.</p><p>To us this meant:</p><ul><li><p>Git</p></li><li><p>Easily deploy</p></li><li><p>Different environments</p></li><li><p>Unit Testing</p></li><li><p>CI Integration</p></li><li><p>Typescript/Multiple Files</p></li><li><p>Everything Must Be Automated</p></li></ul><p>The Cloudflare Access team looked at three options for automating all of these tools in our pipeline. All of the options will work and could be right for you, but custom scripting can be a chore to maintain and Terraform lacked some extensibility.</p><ol><li><p>Custom Scripting</p></li><li><p><a href="https://www.terraform.io/docs/providers/cloudflare/index.html">Terraform</a></p></li><li><p>Serverless Framework</p></li></ol><p>We decided on the Serverless Framework. Serverless Framework provided a tool to mirror our existing process as closely as possible without too much DevOps overhead. Serverless is extremely simple and doesn’t interfere with the application code. You can get a project set up and deployed in seconds. It’s obviously less work than writing your own custom management scripts. But it also requires less boiler plate than Terraform because the Serverless Framework is designed for the “serverless” niche. However, if you are already using Terraform to manage other Cloudflare products, Terraform might be the best fit.</p>
    <div>
      <h3>Walkthrough</h3>
      <a href="#walkthrough">
        
      </a>
    </div>
    <p>Everything for the project happens in a YAML file called serverless.yml. Let’s go through the features of the configuration file.</p><p>To get started, we need to install serverless from npm and generate a new project.</p>
            <pre><code>npm install serverless -g
serverless create --template cloudflare-workers --path myproject
cd myproject
npm install</code></pre>
            <p>If you are an enterprise client, you want to use the cloudflare-workers-enterprise template as it will set up more than one worker (but don’t worry, you can add more to any template). Also, I’ll touch on this later, but if you want to write your workers in Rust, use the cloudflare-workers-rust template.</p><p>You should now have a project that feels familiar, ready to be added to your favorite source control. In the project should be a serverless.yml file like the following.</p>
            <pre><code>service:
    name: hello-world

provider:
  name: cloudflare
  config:
    accountId: CLOUDFLARE_ACCOUNT_ID
    zoneId: CLOUDFLARE_ZONE_ID

plugins:
  - serverless-cloudflare-workers

functions:
  hello:
    name: hello
    script: helloWorld  # there must be a file called helloWorld.js
    events:
      - http:
          url: example.com/hello/*
          method: GET
          headers:
            foo: bar
            x-client-data: value</code></pre>
            <p>The service block simply contains the name of your service. This will be used in your Worker script names if you do not overwrite them.</p><p>Under provider, name must be ‘cloudflare’  and you need to add your account and zone IDs. You can find them in the Cloudflare Dashboard.</p><p>The plugins section adds the Cloudflare specific code.</p><p>Now for the good part: functions. Each block under functions is a Worker script.</p><p><b>name</b>: (optional) If left blank it will be STAGE-service.name-script.identifier. If I removed name from this file and deployed in production stage, the script would be named production-hello-world-hello.</p><p><b>script</b>: the relative path to the javascript file with the worker script. I like to organize mine in a folder called handlers.</p><p><b>events</b>: Currently Workers only support http events. We call these routes. The example provided says that GET <a href="https://example.com/hello/">https://example.com/hello/</a> will  cause this worker to execute. The headers block is for testing invocations.</p><p>At this point you can deploy your worker!</p>
            <pre><code>CLOUDFLARE_AUTH_EMAIL=you@yourdomain.com CLOUDFLARE_AUTH_KEY=XXXXXXXX serverless deploy</code></pre>
            <p>This is very easy to deploy, but it doesn’t address our requirements. Luckily, there’s just a few simple modifications to make.</p>
    <div>
      <h3>Maturing our YAML File</h3>
      <a href="#maturing-our-yaml-file">
        
      </a>
    </div>
    <p>Here’s a more complex YAML file.</p>
            <pre><code>service:
  name: hello-world

package:
  exclude:
    - node_modules/**
  excludeDevDependencies: false

custom:
  defaultStage: development
  deployVars: ${file(./config/deploy.${self:provider.stage}.yml)}

kv: &amp;kv
  - variable: MYUSERS
    namespace: users

provider:
  name: cloudflare
  stage: ${opt:stage, self:custom.defaultStage}
  config:
    accountId: ${env:CLOUDFLARE_ACCOUNT_ID}
    zoneId: ${env:CLOUDFLARE_ZONE_ID}

plugins:
  - serverless-cloudflare-workers

functions:
  hello:
    name: ${self:provider.stage}-hello
    script: handlers/hello
    webpack: true
    environment:
      MY_ENV_VAR: ${self:custom.deployVars.env_var_value}
      SENTRY_KEY: ${self:custom.deployVars.sentry_key}
    resources: 
      kv: *kv
    events:
      - http:
          url: "${self:custom.deployVars.SUBDOMAIN}.mydomain.com/hello"
          method: GET
      - http:
          url: "${self:custom.deployVars.SUBDOMAIN}.mydomain.com/alsohello*"
          method: GET</code></pre>
            <p>We can add a custom section where we can put custom variables to use later in the file.</p><p><b>defaultStage</b>: We set this to development so that forgetting to pass a stage doesn’t trigger a production deploy. Combined with the <b>stage</b> option under provider we can set the stage for deployment.</p><p><b>deployVars</b>: We use this custom variable to load another YAML file dependent on the stage. This lets us have different values for different stages. In development, this line loads the file <code>./config/deploy.development.yml</code>. Here’s an example file:</p>
            <pre><code>env_var_value: true
sentry_key: XXXXX
SUBDOMAIN: dev</code></pre>
            <p><b>kv</b>: Here we are showing off a feature of YAML. If you assign a name to a block using the ‘&amp;’, you can use it later as a YAML variable. This is very handy in a multi script account. We could have named this variable anything, but we are naming it kv since it holds our Workers Key Value storage settings to be used in our function below.</p><p>Inside of the <b>kv</b> block we're creating a namespace and binding it to a variable available in your Worker. It will ensure that the namespace “users” exists and is bound to MYUSERS.</p>
            <pre><code>kv: &amp;kv
  - variable: MYUSERS
    namespace: users</code></pre>
            <p><b>provider</b>: The only new part of the provider block is <b>stage</b>.</p>
            <pre><code>stage: ${opt:stage, self:custom.defaultStage}</code></pre>
            <p>This line sets stage to either the command line option or custom.defaultStage if opt:stage is blank. When we deploy, we pass —stage=production to serverless deploy.</p><p>Now under our function we have added webpack, resources, and environment.</p><p><b>webpack</b>: If set to true, will simply bundle each handler into a single file for deployment. It will also take a string representing a path to a webpack config file so you can customize it. This is how we add Typescript support to our projects.</p><p><b>resources</b>: This block is used to automate resource creation. In resources we're linking back to the kv block we created earlier.</p><p><i>Side note: If you would like to include WASM bindings in your project, it can be done in a very similar way to how we included Workers KV. For more information on WASM, see the </i><a href="https://serverless.com/plugins/serverless-cloudflare-workers/"><i>documentation</i></a><i>.</i></p><p><b>environment</b>: This is the butter for the bread that is managing configuration for different stages. Here we can specify values to bind to variables to use in worker scripts. Combined with YAML magic, we can store our values in the aforementioned config files so that we deploy different values in different stages. With environments, we can easily tie into our CI tool. The CI tool has our deploy.production.yml. We simply run the following command from within our CI.</p>
            <pre><code>sls deploy --stage=production</code></pre>
            <p>Finally, I added a route to demonstrate that a script can be executed on multiple routes.</p><p>At this point I’ve covered (or hinted) at everything on our original list except Unit Testing. There are a few ways to do this.</p><p>We have a previous blog post about <a href="/unit-testing-worker-functions/">Unit Testing</a> that covers using <a href="https://github.com/dollarshaveclub/cloudworker">cloud worker</a>, a great tool built by <a href="https://www.dollarshaveclub.com/">Dollar Shave Club</a>.</p><p>My team opted to use the classic node frameworks mocha and sinon. Because we are using Typescript, we can build for node or build for v8. You can also make mocha work for non-typescript projects if you use an <a href="https://nodejs.org/api/esm.html">experimental feature that adds import/export support to node</a>.</p>
            <pre><code>--experimental-modules</code></pre>
            <p>We’re excited about moving more and more of our services to Cloudflare Workers, and the Serverless Framework makes that easier to do. If you’d like to learn even more or get involved with the project, see us on <a href="https://github.com/cloudflare/serverless-cloudflare-workers">github.com</a>. For additional information on using Serverless Framework with Cloudflare Workers, check out our <a href="https://developers.cloudflare.com/workers/deploying-workers/serverless/">documentation on the Serverless Framework</a>.</p> ]]></content:encoded>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[API]]></category>
            <category><![CDATA[CLI]]></category>
            <category><![CDATA[GitHub]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">40cVOSqV3lXK8azULKCab7</guid>
            <dc:creator>Jonathan Spies</dc:creator>
        </item>
        <item>
            <title><![CDATA[BoringTun, a userspace WireGuard implementation in Rust]]></title>
            <link>https://blog.cloudflare.com/boringtun-userspace-wireguard-rust/</link>
            <pubDate>Wed, 27 Mar 2019 13:43:27 GMT</pubDate>
            <description><![CDATA[ Today we are happy to release the source code of a project we’ve been working on for the past few months. It is called BoringTun, and is a userspace implementation of the WireGuard® protocol written in Rust. ]]></description>
            <content:encoded><![CDATA[ <p>Today we are happy to release the <a href="https://github.com/cloudflare/boringtun">source code</a> of a project we’ve been working on for the past few months. It is called BoringTun, and is a <a href="https://www.wireguard.com/xplatform/">userspace</a> implementation of the <a href="https://www.wireguard.com/">WireGuard®</a> protocol written in Rust.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/265ROm9gzfd6Fg7Qg5eL22/a321265e139e299f61ec368fb86578eb/boring-tun-logo.png" />
            
            </figure>
    <div>
      <h3>A Bit About WireGuard</h3>
      <a href="#a-bit-about-wireguard">
        
      </a>
    </div>
    <p>WireGuard is relatively new project that attempts to replace old VPN protocols, with a simple, fast, and safe protocol. Unlike legacy VPNs, WireGuard is built around the <a href="http://www.noiseprotocol.org/">Noise Protocol Framework</a> and relies only on a select few, modern, cryptographic primitives: X25519 for public key operations, <a href="/do-the-chacha-better-mobile-performance-with-cryptography/">ChaCha20-Poly1305</a> for authenticated encryption, and Blake2s for message authentication.</p><p>Like <a href="/http-3-from-root-to-tip/">QUIC</a>, WireGuard works over UDP, but its only goal is to securely encapsulate IP packets. As a result, it does not guarantee the delivery of packets, or that packets are delivered in the order they are sent.</p><p>The simplicity of the protocol means it is more robust than old, unmaintainable codebases, and can also be implemented relatively quickly. Despite its relatively young age, WireGuard is <a href="https://arstechnica.com/gadgets/2018/08/wireguard-vpn-review-fast-connections-amaze-but-windows-support-needs-to-happen/">quickly gaining in popularity</a>.</p>
    <div>
      <h3>Starting From Scratch</h3>
      <a href="#starting-from-scratch">
        
      </a>
    </div>
    <p>While evaluating the potential value WireGuard could provide us, we first considered the existing implementations. Currently, there are three usable implementations</p><ul><li><p>The WireGuard kernel module - written in C, it is tightly integrated with the Linux kernel, and is not usable outside of it. Due to its integration with the kernel it provides the best possible performance. It is licensed under the GPL-2.0 license.</p></li><li><p>wireguard-go - this is the only compliant userspace implementation of WireGuard. As its name suggests it is written in Go, a language that we love, and is licensed under the permissive MIT license.</p></li><li><p>TunSafe - written in C++, it does not implement the userspace protocol exactly, but rather a deviation of it. It supports several platforms, but by design it supports only a single peer. TunSafe uses the AGPL-1.0 license.</p></li></ul><p>Whereas we were looking for:</p><ul><li><p><a href="https://en.wikipedia.org/wiki/User_space">Userspace</a></p></li><li><p>Cross-platform - including Linux, Windows, macOS, iOS and Android</p></li><li><p>Fast</p></li></ul><p>Clearly we thought, only one of those fits the bill, and that is wireguard-go. However, benchmarks quickly showed that wireguard-go falls very short of the performance offered by the kernel module. This is because while the Go language is very good for writing servers, it is not so good for raw packet processing, which a VPN essentially does.</p>
    <div>
      <h3>Choosing <a href="https://www.rust-lang.org/">Rust</a></h3>
      <a href="#choosing">
        
      </a>
    </div>
    <p>After we decided to create a userspace WireGuard implementation, there was the small matter of choosing the right language. While C and C++ are both high performance, low level languages, <a href="/incident-report-on-memory-leak-caused-by-cloudflare-parser-bug/">recent history</a> has demonstrated that their memory model was too fragile for a modern cryptography and security-oriented project. Go was shown to be suboptimal for this use case by wireguard-go.</p><p>The obvious answer was Rust. Rust is a modern, safe language that is both as fast as C++ and is arguably safer than Go (it is memory safe and also imposes rules that allow for safer concurrency), while supporting a huge selection of <a href="https://forge.rust-lang.org/platform-support.html">platforms</a>. We also have some of the best Rust talent in the industry working at the company.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4JAfjcdBRke6buHmC9MV0h/a062037c4e17784546c6f974f9dac476/Screen-Shot-2019-03-26-at-4.13.07-PM-2.png" />
            
            </figure><p>In fact, another Rust implementation of WireGuard, wireguard-rs, exists. But wireguard-rs is very immature, and we strongly felt that it would benefit the WireGuard ecosystem if there was a completely independent implementation under a permissive license.</p><p>Thus BoringTun was born.</p><p>The name might sound a bit boring but there's a reason for it: BoringTun creates a tunnel by 'boring' it. And it’s a nod to Google’s <a href="https://boringssl.googlesource.com/boringssl/">BoringSSL</a> which strips the complexity out of OpenSSL. We think WireGuard has the opportunity to do the same for legacy VPN protocols like OpenVPN. And we hope BoringTun can be a valuable tool as part of that ecosystem.</p><p>WireGuard is an incredible tool and we believe it has a chance of being the defacto standard for VPN-like technologies going forward. We're adding our Rust implementation of WireGuard to the ecosystem and hope people find it useful.</p>
    <div>
      <h3>Next steps</h3>
      <a href="#next-steps">
        
      </a>
    </div>
    <p>BoringTun is currently under internal security review, and it is probably not fully ready to be used in mission critical tasks. We will fix issues as we find them, and we also welcome contributions from the community on the projects <a href="https://github.com/cloudflare/boringtun">Github page</a>. The project is licensed under the open source <a href="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</a>.</p><p>Note: WireGuard is a registered trademark of <a href="https://www.zx2c4.com/">Jason A. Donenfeld</a>.</p> ]]></content:encoded>
            <category><![CDATA[Rust]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">4LsskKWd8AfwLuPW5Ej5VS</guid>
            <dc:creator>Vlad Krasnov</dc:creator>
        </item>
    </channel>
</rss>