<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GrantSeltzer</title><link>https://grantseltzer.github.io/</link><description>Recent content on GrantSeltzer</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 01 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://grantseltzer.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>bpf-next llm summaries</title><link>https://grantseltzer.github.io/blog/bpf-next-summarizer/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/bpf-next-summarizer/</guid><description>&lt;p&gt;I try to follow the &lt;a href="https://lore.kernel.org/bpf/"&gt;bpf-next mailing list&lt;/a&gt; closely, but I always miss things. LWN is incredible, I&amp;rsquo;m a long time subscriber, but there&amp;rsquo;s still gaps I&amp;rsquo;d like to fill. So I built a small automated system to summarize the mailing list for me and publish the results &lt;a href="https://grantseltzer.github.io/bpf-next/"&gt;here on my site&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;It works in two stages. First, a GitHub Actions workflow runs every morning at 5am ET. It queries the &lt;a href="https://patchwork.kernel.org/api/"&gt;Patchwork REST API&lt;/a&gt; for recent bpf-next patches and commits the raw patch data to a staging directory in this blog&amp;rsquo;s &lt;a href="https://github.com/grantseltzer/blog"&gt;repository&lt;/a&gt;. An hour later at 6am ET, a &lt;a href="https://docs.anthropic.com/en/docs/claude-code/scheduled-agents"&gt;Claude Code scheduled agent&lt;/a&gt; picks up the staging files, reads the raw patch data, generates structured JSON summaries, writes them to &lt;code&gt;data/bpf_next/daily/YYYY-MM-DD.json&lt;/code&gt;, cleans up the staging files, and pushes. That push triggers CI to rebuild and deploy the site to &lt;a href="https://github.com/grantseltzer/grantseltzer.github.io"&gt;grantseltzer.github.io&lt;/a&gt;. On Mondays the workflow also generates a weekly rollup, and on the 1st of each month a monthly one. Each summary is kept as a dated file so the page serves as a running archive.&lt;/p&gt;</description></item><item><title>Replacing procfs with bpf</title><link>https://grantseltzer.github.io/blog/bpf-iter/</link><pubDate>Sat, 21 Jun 2025 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/bpf-iter/</guid><description>&lt;p&gt;&lt;em&gt;You can find all the code displayed in this post in my repo &lt;a href="https://github.com/grantseltzer/bpf-iter-test"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;The &lt;a href="https://man7.org/linux/man-pages/man5/proc.5.html"&gt;proc file system&lt;/a&gt; provides to users information about the processes on a running linux system via a file system interface. The directory structure is organized such that every process has its own directory. The files in the directory are useful for finding out permissions, state, open files, and more. I wrote a &lt;a href="https://www.grant.pizza/blog/procfs/"&gt;small post&lt;/a&gt; about it in 2019.&lt;/p&gt;</description></item><item><title>Global No-Inline BPF Functions</title><link>https://grantseltzer.github.io/blog/global-noinline/</link><pubDate>Sun, 11 May 2025 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/global-noinline/</guid><description>&lt;p&gt;The &lt;a href="https://docs.ebpf.io/linux/concepts/verifier/"&gt;bpf verifier&lt;/a&gt; is tasked with ensuring that bpf programs that are loaded will predictably halt and run safely. It follows all branches of bpf instructions, counting each instruction as another permutation of the program&amp;rsquo;s state. As it counts, there&amp;rsquo;s a limit of 1 million instructions.&lt;/p&gt;&#10;&lt;p&gt;If you&amp;rsquo;ve been writing bpf programs for a long time or have been looking at outdated examples then you&amp;rsquo;re probably familiar with using the &lt;code&gt;static&lt;/code&gt; modifier and &lt;code&gt;__always_inline&lt;/code&gt; macro.&lt;/p&gt;</description></item><item><title>Building Go Stack Traces from BPF</title><link>https://grantseltzer.github.io/blog/go-stack-traces-bpf/</link><pubDate>Wed, 06 Dec 2023 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/go-stack-traces-bpf/</guid><description>&lt;p&gt;In a couple of my posts from a few years ago (&lt;a href="https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-1"&gt;1&lt;/a&gt;, &lt;a href="https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-2"&gt;2&lt;/a&gt;) I explored the idea of attaching bpf programs to Go functions via uprobes. The second post dived into how to extract values of parameters. This can be seen as part 3 of the series as I&amp;rsquo;m going to demonstrate how to get a stack trace from bpf code. The work described in this post is in contribution to my work at Datadog on the &lt;a href="https://www.datadoghq.com/product/dynamic-instrumentation/"&gt;Dynamic Instrumentation&lt;/a&gt; product, allowing users to hook specific functions and get snapshots of parameter values and stack traces.&lt;/p&gt;</description></item><item><title>How Go slices work</title><link>https://grantseltzer.github.io/blog/how-go-slices-work/</link><pubDate>Thu, 30 Nov 2023 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/how-go-slices-work/</guid><description>&lt;p&gt;I recently ran into a hard to find bug in my Go code when using slices. Since I&amp;rsquo;ve been using Go for over 8 years now, I figured this is something that others will run into and want to share what I had forgotten about how slices work.&lt;/p&gt;&#10;&lt;p&gt;Take a look at the following Go code:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;x := []int{1,2,3}&#10;y := append([]int{}, x...)&#10;z := x&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have three separate slices. What I want to briefly explore is the difference between y, and z. The difference has to do with how slices are implemented by Go. This can sometimes make it hard to track down bugs, so it&amp;rsquo;s important to know.&lt;/p&gt;</description></item><item><title>BPF Attach Cookies</title><link>https://grantseltzer.github.io/blog/bpf-cookies/</link><pubDate>Wed, 09 Aug 2023 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/bpf-cookies/</guid><description>&lt;p&gt;BPF has a helper function called &lt;code&gt;bpf_get_attach_cookie&lt;/code&gt;. It&amp;rsquo;s available in bpf programs like kprobes, uprobes, and tracepoints. It can be very useful for many applications so i&amp;rsquo;ll be exploring how to use it, and going over a few examples from real code i&amp;rsquo;ve written.&lt;/p&gt;&#10;&lt;p&gt;A cookie is just an unsigned 64-bit integer. That&amp;rsquo;s it. You can assign a cookie to a bpf program when you attach it. For example, here&amp;rsquo;s code using the go &lt;code&gt;cilium/ebpf&lt;/code&gt; library to assign a cookie to a uprobe:&lt;/p&gt;</description></item><item><title>Memory Execution Override With ebpf</title><link>https://grantseltzer.github.io/talks/summercon2022/</link><pubDate>Fri, 08 Jul 2022 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/summercon2022/</guid><description/></item><item><title>BPF Map Concurrency Techniques</title><link>https://grantseltzer.github.io/blog/bpf-concurrency/</link><pubDate>Thu, 16 Jun 2022 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/bpf-concurrency/</guid><description>&lt;p&gt;There are times when developing your BPF projects when you need to ensure safe access to shared memory. You may have a counter that you&amp;rsquo;re updating from various different BPF programs and reading in userspace. You may also be updating map values from both userspace and from BPF. In this post i&amp;rsquo;ll demonstrate a couple different techniques for handing these scenarios safely.&lt;/p&gt;&#10;&lt;h2 id="per-cpu-maps"&gt;Per-cpu maps&lt;/h2&gt;&#10;&lt;p&gt;Per-cpu maps are types of maps where each possible CPU has its own copy of underlying memory. Since BPF programs can&amp;rsquo;t be preempted, when you access a value inside one of these maps from your BPF program, you know that it&amp;rsquo;s the only program touching that value. The userspace program can &lt;em&gt;read&lt;/em&gt; these values at any time safely.&lt;/p&gt;</description></item><item><title>Handling errors with CGO</title><link>https://grantseltzer.github.io/blog/cgo-errors/</link><pubDate>Wed, 16 Mar 2022 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/cgo-errors/</guid><description>&lt;p&gt;One of the main projects that I work on is &lt;a href="https://github.com/aquasecurity/libbpfgo"&gt;libbpfgo&lt;/a&gt;. This is a Go wrapper around &lt;a href="https://github.com/libbpf/libbpf"&gt;libbpf&lt;/a&gt;, a userspace library for dealing with bpf objects. The wrapper uses CGO to reference individual functions and data types in libbpf, which is written in C.&lt;/p&gt;&#10;&lt;p&gt;For example, &lt;code&gt;BPFLoadObject()&lt;/code&gt; is a libbpfgo API function which calls &lt;code&gt;bpf_object__load()&lt;/code&gt;, a libbpf API function.&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;func (m *Module) BPFLoadObject() error {&#10;&#9;ret := C.bpf_object__load(m.obj)&#10;&#9;if ret != 0 {&#10;&#9;&#9;return fmt.Errorf(&amp;#34;failed to load BPF object&amp;#34;)&#10;&#9;}&#10;&#10;&#9;return nil&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The goal for libbpfgo is to fully implement the libbpf API (&lt;a href="https://libbpf.readthedocs.io/en/latest/api.html"&gt;which is pretty big&lt;/a&gt;). One complication with this is that libbpf has very inconsistent error handling. Some APIs will return an integer error code directly, some will return a NULL pointer and set the error code in errno, some will return an error code inside of a pointer, and some return an error code which is also in errno. As a result of trying to maintain libbpfgo&amp;rsquo;s error handling sanity, I&amp;rsquo;ve picked up some lessons on how you can use CGO to your advantage.&lt;/p&gt;</description></item><item><title>Portable BPF with CO:RE</title><link>https://grantseltzer.github.io/talks/ebpfdaycncf2021/</link><pubDate>Mon, 11 Oct 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/ebpfdaycncf2021/</guid><description>&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/BF42-cl-8B0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;</description></item><item><title>Basic Guide to Linux Mailing Lists</title><link>https://grantseltzer.github.io/blog/mailing-list-guide/</link><pubDate>Sun, 10 Oct 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/mailing-list-guide/</guid><description>&lt;p&gt;The Linux kernel is the biggest open source project in existence. It has tens of thousands of contributors from all around the world, from many different companies and communities.&lt;/p&gt;&#10;&lt;p&gt;Linux development does not happen in a single github repository, and likely never will. Instead there are many forks of the linux kernel. Development happens in these forks for very specific subsystems, only a fraction of the overall code. Contributors submit relevant patches to the &amp;lsquo;mailing list&amp;rsquo; that is used for each of these forks. The fork maintainers review these patches, and at regular intervals submit groups of patches &amp;lsquo;upstream&amp;rsquo; to more generalized forks. All these patches eventually make their way up to the &amp;lsquo;mainline&amp;rsquo; kernel which a single maintainer presides over. Eventually the forks pull down the changes from other downstream forks.&lt;/p&gt;</description></item><item><title>The libbpf Documentation Site</title><link>https://grantseltzer.github.io/blog/contribute-docs-libbpf/</link><pubDate>Sun, 10 Oct 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/contribute-docs-libbpf/</guid><description>&lt;p&gt;libbpf is the standard implementation of the userspace library for loading and interacting with bpf programs. It defines the bpf ELF file format and CO-RE features. It&amp;rsquo;s a crucial part of the bpf ecosystem and is soon approaching its first major release. With this in mind, it&amp;rsquo;s important to have proper documentation.&lt;/p&gt;&#10;&lt;p&gt;Introducing &lt;a href="https://libbpf.readthedocs.org"&gt;libbpf.readthedocs.org&lt;/a&gt;. By going to the &lt;a href="https://libbpf.readthedocs.io/en/latest/api.html"&gt;API docs&lt;/a&gt; you can see that each libbpf API function, type, enum and macro are listed. This is generated from the libbpf header files. Comments can be placed in code above the relevant API code and displayed on the documentation site.&lt;/p&gt;</description></item><item><title>Go Time #201</title><link>https://grantseltzer.github.io/talks/gotime2/</link><pubDate>Tue, 14 Sep 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/gotime2/</guid><description>&lt;audio data-theme="day" data-src="https://changelog.com/gotime/201/embed" src="https://cdn.changelog.com/uploads/gotime/201/go-time-201.mp3" preload="none" class="changelog-episode" controls&gt;&lt;/audio&gt;&lt;p&gt;&lt;a href="https://changelog.com/gotime/201"&gt;Listen on &lt;a href="https://changelog.com/"&gt;Changelog.com&lt;/a&gt;&lt;/p&gt;&lt;script async src="//cdn.changelog.com/embed.js"&gt;&lt;/script&gt;</description></item><item><title>Compile Once Run Everywhere, the eBPF Dream!</title><link>https://grantseltzer.github.io/talks/ebpfsummit2021/</link><pubDate>Thu, 19 Aug 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/ebpfsummit2021/</guid><description>&lt;p&gt;Skip to 3:11:00 for my talk (or watch the whole thing, it was a great conference!)&lt;/p&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/ZNtVedFsD-k?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;</description></item><item><title>Supporting CO:RE in Tracee</title><link>https://grantseltzer.github.io/blog/tracee-core/</link><pubDate>Fri, 23 Jul 2021 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/tracee-core/</guid><description>&lt;p&gt;If you&amp;rsquo;re used to developing software in a high level language like Go or Java you likely haven&amp;rsquo;t thought about supporting different operating system versions. Sure you want to be able to run on Linux, Macos, or Windows, but that&amp;rsquo;s abstracted away for you.&lt;/p&gt;&#10;&lt;p&gt;When developing eBPF software you must think about hundreds of Linux kernel versions. When your eBPF programs are reading in kernel data structure fields, there&amp;rsquo;s no guarantee of backwards compatibility or stable APIs. Take a look at this example:&lt;/p&gt;</description></item><item><title>Tracing Go Programs with eBPF!</title><link>https://grantseltzer.github.io/talks/gopherconeu2021/</link><pubDate>Thu, 27 May 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/gopherconeu2021/</guid><description>&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/JxZL6ZEBBEg?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;</description></item><item><title>Getting started with bpf and libbpfgo</title><link>https://grantseltzer.github.io/blog/libbpf-beginners-part-one/</link><pubDate>Thu, 18 Mar 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/libbpf-beginners-part-one/</guid><description>&lt;p&gt;In my &lt;a href="https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-1"&gt;previous posts&lt;/a&gt; on the subject of bpf I used a project called BCC to compile, load, and interact with my bpf programs. I, and many other developers, have recently heard about a better way to build ebpf projects called &lt;a href="https://github.com/libbpf/libbpf"&gt;libbpf&lt;/a&gt;. There are a few good resources to use when developing libbpf based programs but getting started can still be a quite overwhelming. The goal of this post is to provide a simple and effective explanation of what libbpf is and how to start using it.&lt;/p&gt;</description></item><item><title>What is vmlinux.h?</title><link>https://grantseltzer.github.io/blog/vmlinux-header/</link><pubDate>Thu, 11 Mar 2021 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/blog/vmlinux-header/</guid><description>&lt;div style="color: gray; font-style: italic; font-size: smaller;"&gt;&#10; &lt;p&gt;&#10;&#10;A version of this post was also uploaded to Aqua's blog &lt;a href="https://blog.aquasec.com/vmlinux.h-ebpf-programs"&gt;here&lt;/a&gt;&#10;&#10;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;If you&amp;rsquo;ve been reading much bpf code recently, you&amp;rsquo;ve probably seen this:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;#include &amp;#34;vmlinux.h&amp;#34;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;vmlinux.h&lt;/code&gt; is generated code. it contains all of the type definitions that your running Linux kernel uses in it&amp;rsquo;s own source code. This is an important concept to wrap your head around so let me explain.&lt;/p&gt;&#10;&lt;p&gt;When you build Linux one of the output artifacts is a file called &lt;code&gt;vmlinux&lt;/code&gt;. It&amp;rsquo;s also typically packaged with major distributions. This is an &lt;a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format"&gt;ELF&lt;/a&gt; binary that contains the compiled kernel inside it.&lt;/p&gt;</description></item><item><title>Parsing Go Binary DWARF Info</title><link>https://grantseltzer.github.io/blog/dwarf/</link><pubDate>Sat, 02 Jan 2021 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/dwarf/</guid><description>&lt;p&gt;In my very first blog post, &lt;a href="https://grantseltzer.github.io/blog/dissecting-go-binaries"&gt;Dissecting Go Binaries&lt;/a&gt;, I began to explore ELF files. That is the default format of executable binaries that Go produces on unix-like operating systems like Linux and MacOS. My most recent project, &lt;a href="https://github.com/grantseltzer/weaver"&gt;weaver&lt;/a&gt;, has me exploring a related object file format that Go leverages, &lt;a href="http://dwarfstd.org/"&gt;DWARF&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;The DWARF specification is, of course, not Go specific. The DWARF object file specification describes the functions, variables, and types of a compiled program. Entries of a DWARF file are organized in a tree structure where each node can have children and siblings. For example, an entry node that describes a function would have children that describe the parameters. An entry node that describes a struct would have children that describe the fields of it.&lt;/p&gt;</description></item><item><title>Tracing Go Programs with eBPF!</title><link>https://grantseltzer.github.io/talks/gophercon2020/</link><pubDate>Fri, 13 Nov 2020 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/gophercon2020/</guid><description>&lt;p&gt;Code can be found &lt;a href="https://www.github.com/grantseltzer/"&gt;here&lt;/a&gt;&lt;/p&gt;&#10;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;&#10;&#9;&#9;&#9;&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/OxLmd7szevI?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;&#10;&#9;&#9;&lt;/div&gt;</description></item><item><title>Go Time #159</title><link>https://grantseltzer.github.io/talks/gotime/</link><pubDate>Tue, 10 Nov 2020 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/gotime/</guid><description>&lt;audio data-theme="day" data-src="https://changelog.com/gotime/159/embed" src="https://cdn.changelog.com/uploads/gotime/159/go-time-159.mp3" preload="none" class="changelog-episode" controls&gt;&lt;/audio&gt;&lt;p&gt;&lt;a href="https://changelog.com/gotime/159"&gt;Listen on &lt;a href="https://changelog.com/"&gt;Changelog.com&lt;/a&gt;&lt;/p&gt;&lt;script async src="//cdn.changelog.com/embed.js"&gt;&lt;/script&gt;</description></item><item><title>Tracing Go Functions with eBPF Part 2</title><link>https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-2/</link><pubDate>Sun, 10 May 2020 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-2/</guid><description>&lt;p&gt;In &lt;a href="https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-1"&gt;part 1&lt;/a&gt; of this series we learned about how to attach uprobes and eBPF programs to specific functions in Go programs. We went through an example where we attached our probe to the handler of a webserver. Everytime the probe was triggered we simply printed out a log saying that the handler was called. This could be adapted to record metrics, perhaps using counters instead of log lines.&lt;/p&gt;&#10;&lt;p&gt;In this post we&amp;rsquo;re going to delve a bit deeper. We&amp;rsquo;re going to use the capabilities that eBPF has for traversing through the memory of the program we&amp;rsquo;re tracing.&lt;/p&gt;</description></item><item><title>Fermentation Experimentation</title><link>https://grantseltzer.github.io/blog/fermentation/</link><pubDate>Thu, 05 Mar 2020 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/fermentation/</guid><description>&lt;p&gt;In the past year I&amp;rsquo;ve decided that I haven&amp;rsquo;t perpetuated enough Brooklyn stereotypes and have taken up fermentation as a hobby. This post goes through a few of the experiments that I&amp;rsquo;ve run with varying success.&lt;/p&gt;&#10;&lt;p&gt;My set up is pretty basic. I have a small cabinet/closet in the corner of my kitchen that i&amp;rsquo;ve designated as the &lt;i&gt;&amp;lsquo;fermentation station&amp;rsquo;&lt;/i&gt;. I have a thermometer but it mostly stays at room temperature. In the winter it gets warmer as it sits directly in front of a radiator which is always on. I also affixed a curtain to avoid direct sunlight as the setup is next to a window.&lt;/p&gt;</description></item><item><title>Tracing Go Functions with eBPF Part 1</title><link>https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-1/</link><pubDate>Fri, 14 Feb 2020 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/tracing-go-functions-with-ebpf-part-1/</guid><description>&lt;p&gt;eBPF is a virtual machine, similar in concept to the JVM, except it&amp;rsquo;s inside the Linux kernel. It lets you write C-like code, compile it, and load the byte code into the kernel. You can then attach hooks to your loaded eBPF program to trigger it to run. Those hooks could be things like system calls, &lt;a href="https://lwn.net/Articles/132196/"&gt;kprobes&lt;/a&gt;, or &lt;a href="https://www.kernel.org/doc/ols/2007/ols2007v1-pages-215-224.pdf"&gt;uprobes&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;There&amp;rsquo;s many use cases for eBPF. Considering eBPF programs have full system visibility there are very few limits on what you can do. You can write an eBPF program which logs every time certain files are modified. You use eBPF to profile performance of your other programs. You can implement host-based networking rules, or use it for &lt;a href="https://www.youtube.com/watch?v=yrrxFZfyEsw"&gt;writing malware&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Using Karn for Seccomp Enforcement</title><link>https://grantseltzer.github.io/blog/karn/</link><pubDate>Wed, 11 Dec 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/karn/</guid><description>&lt;p&gt;&lt;a href="https://github.com/grantseltzer/karn"&gt;Karn&lt;/a&gt; aims to provide for Linux what &lt;a href="https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AboutEntitlements.html"&gt;entitlements&lt;/a&gt; provide for iOS, or what &lt;a href="https://man.openbsd.org/pledge.2"&gt;pledge&lt;/a&gt; provides for OpenBSD. It does this by translating a high level set of intuitive &amp;rsquo;entitlements&amp;rsquo; into complex seccomp profiles.&lt;/p&gt;&#10;&lt;p&gt;For example, A developer using Karn can simply specify that their application needs to make network connections, or exec other processes and karn will handle granting it permission to do those things (and nothing else!).&lt;/p&gt;&#10;&lt;p&gt;So, how does it work?&lt;/p&gt;</description></item><item><title>The Problem with Sandboxing Solutions</title><link>https://grantseltzer.github.io/talks/hushcon2019/</link><pubDate>Fri, 06 Dec 2019 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/hushcon2019/</guid><description/></item><item><title>The Problem with Sandboxing Solutions</title><link>https://grantseltzer.github.io/talks/kubesec2019/</link><pubDate>Mon, 18 Nov 2019 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/talks/kubesec2019/</guid><description/></item><item><title>Linux Procfs</title><link>https://grantseltzer.github.io/blog/procfs/</link><pubDate>Wed, 02 Oct 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/procfs/</guid><description>&lt;p&gt;I love the procfs because it provides an intuitive and easy to use interface for interacting with the kernel. In the same way you&amp;rsquo;d normally use the command line for exploring files, you can control and find out information about currently running processes. All without the need for system calls.&lt;/p&gt;&#10;&lt;p&gt;A procfs is mounted at &lt;code&gt;/proc&lt;/code&gt; by default. If you go into &lt;code&gt;/proc&lt;/code&gt; you&amp;rsquo;ll see something like this:&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://grantseltzer.github.io/procfs/toplevel.png" alt="toplevel"&gt;&lt;/p&gt;&#10;&lt;p&gt;You&amp;rsquo;ll notice a lot of the directories that are just named by numbers. There is one for each individual process. The directory names correspond to the process ID. One directory for each process.&lt;/p&gt;</description></item><item><title>Linux Overlayfs</title><link>https://grantseltzer.github.io/blog/overlayfs/</link><pubDate>Wed, 18 Sep 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/overlayfs/</guid><description>&lt;p&gt;Remember back to when your teacher in grade school would write on sheets of clear plastic, stack them, and display them with an overhead projector? That is exactly how &lt;code&gt;overlayfs&lt;/code&gt; works&amp;hellip; except with filesystems.&lt;/p&gt;&#10;&lt;p&gt;Overlay filesystems allow you to take multiple directory trees and view them as if they were merged together. The added benefit is that changes in the merged view do not affect the underlying directories. There are many use cases for this, mostly related to containers, but more on that at the end.&lt;/p&gt;</description></item><item><title>Debugging Go tests</title><link>https://grantseltzer.github.io/blog/test-build-modes/</link><pubDate>Thu, 15 Aug 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/test-build-modes/</guid><description>&lt;span style="color:grey;font-style: italic;font-size: 14px"&gt;&#10;This post discusses building go test binaries and walking through them with delve&#10;&lt;/span&gt;&#10;&lt;p&gt;I recently was working on debugging a unit test I wrote in Go. I couldn&amp;rsquo;t figure out why one of my test cases was causing a runtime error that never happened when running my actual program. I was using a runtime directive so I suspected there may be some difference between doing a &lt;code&gt;go test&lt;/code&gt; and a &lt;code&gt;go run&lt;/code&gt;. I was looking through Go build mode &lt;a href="https://golang.org/cmd/go/#hdr-Build_modes"&gt;documentation&lt;/a&gt; while wondering if I could step through it with a debugger. Lo and behold you can compile your tests into an ELF executable!&lt;/p&gt;</description></item><item><title>Standardized Streams and Shells</title><link>https://grantseltzer.github.io/blog/standardized-streams-and-shells/</link><pubDate>Tue, 21 May 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/standardized-streams-and-shells/</guid><description>&lt;span style="color:grey;font-style: italic;font-size: 14px"&gt;&#10;In this post we discuss how standardized streams (`stdin`/`stdout`/`stderr`) work on Linux, especially related to shells.&#10;&lt;/span&gt;&#10;&lt;p&gt;Every well known operating system has a concept of standardized streams. These consist of standard input, output, and error. As their name purports, they are the standard places for proccesses to read input, and send output. They&amp;rsquo;re a crucial concept that allows various running processes to easily communicate.&lt;/p&gt;&#10;&lt;p&gt;Standardized streams enable you to string together multiple commands with a pipe (&lt;code&gt;|&lt;/code&gt;) in your shell like this:&lt;/p&gt;</description></item><item><title>Using dynamic libraries in static Go binaries</title><link>https://grantseltzer.github.io/blog/using-dynamic-libraries-in-static-go-binaries/</link><pubDate>Tue, 09 Apr 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/using-dynamic-libraries-in-static-go-binaries/</guid><description>&lt;span style="color:grey;font-style: italic;font-size: 14px"&gt;&#10;This post highlights a linker directive in Go. It allows us to import functions from a dynamic library even when CGO is disabled. I use the example of a contribution I recently made to the net and runtime packages to demonstrate its use case.&#10;&lt;/span&gt;&#10;&lt;p&gt;Go has many little known features that allow you to give instructions to the compiler, linker, and other parts of the toolchain using special comments. Dave Cheney wrote an excellent post on them &lt;a href="https://dave.cheney.net/2018/01/08/gos-hidden-pragmas"&gt;here&lt;/a&gt;. One such &amp;lsquo;pragma&amp;rsquo; as Cheney calls them is &lt;code&gt;//go:cgo_import_dynamic&lt;/code&gt;. This is a linker directive. It tells the linker to pull in a specific function from a dynamic library such as libc.&lt;/p&gt;</description></item><item><title>The Beauty of io.Writer</title><link>https://grantseltzer.github.io/blog/the-beauty-of-io-writer/</link><pubDate>Thu, 04 Apr 2019 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/the-beauty-of-io-writer/</guid><description>&lt;span style="color:grey;font-style: italic;font-size: 14px"&gt;&#10;In this post we explore best practices of defining interfaces in Go. We use `io.Writer` to break down patterns and antipatterns.&#10;&lt;/span&gt;&#10;&lt;p&gt;A perfect example of a properly designed Go interface is &lt;code&gt;io.Writer&lt;/code&gt;:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;type Writer interface {&#10; Write(p []byte) (n int, err error)&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is short, simple, and powerful. The &lt;code&gt;Write&lt;/code&gt; method takes a very generic slice of bytes and writes it to &lt;i&gt;something&lt;/i&gt;.&lt;/p&gt;&#10;&lt;p&gt;In Rob Pike&amp;rsquo;s &lt;a href="https://youtu.be/PAAkCSZUG1c?t=317"&gt;Go Proverbs talk&lt;/a&gt; he talks about how in Go, interfaces are not declared to be satisfied, they&amp;rsquo;re satisfied implicitly. An interface should be a way of classifying types, not a blueprint for declaring them. In practical terms, an interface should not at all care about how it&amp;rsquo;s implemented.&lt;/p&gt;</description></item><item><title>Understanding cgroups</title><link>https://grantseltzer.github.io/blog/understanding-cgroups/</link><pubDate>Tue, 20 Nov 2018 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/understanding-cgroups/</guid><description>&lt;span style="color:grey;font-style: italic;font-size: 14px"&gt;&#10;This post will introduce you to cgroups. The goal is to give a comprehensive enough explanation of cgroups and subsystems to broadly understand what they accomplish and how. The major focus will be on the CPU cgroup. The [second section](#using-cgroups) and [third section](#practically-using-cgroups) will explore using cgroups from the command line.&#10;&lt;/span&gt;&#10;&lt;p&gt;Control groups (or cgroups) are a feature of the Linux kernel by which groups of processes can be monitored and have their resources limited. For example, if you don&amp;rsquo;t want a google chrome process (or it&amp;rsquo;s many child processes) to exceed a gigabyte of RAM or 30% total CPU usage, cgroups would let you do that. They are an extremely powerful tool by which you can guarentee limits on performance, but understanding how they work and how to use them can be a little daunting.&lt;/p&gt;</description></item><item><title>Dissecting Go Binaries</title><link>https://grantseltzer.github.io/blog/dissecting-go-binaries/</link><pubDate>Fri, 14 Sep 2018 03:32:37 +0000</pubDate><guid>https://grantseltzer.github.io/blog/dissecting-go-binaries/</guid><description>&lt;span style="color:grey;font-style: italic;font-size: 14px"&gt;&#10;This post will introduce you to the basic concepts of disassembly and walk through writing a simple disassembler in Go. The goal is to make the whole concept of disassembly as accessible as possible and hopefully give you, the reader, a takeaway or two about how compiled Go binaries work.&#10;&lt;/span&gt;&#10;&lt;!-- Intro --&gt;&#10;&lt;p&gt;Assembly code cannot lie. By reading assembly we become as close as possible to knowing what’s being run on our computer chips. This is exactly why disassembly is important! If you have a binary with malicious intentions, disassembling it will expose them. If you can&amp;rsquo;t figure out a performance bottleneck in your code, you can disassemble it for clarity.&lt;/p&gt;</description></item><item><title/><link>https://grantseltzer.github.io/recipes/bialys/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/recipes/bialys/</guid><description>&lt;h1 id="bialys"&gt;Bialys&lt;/h1&gt;&#10;&lt;p&gt;Bialys are a traditional roll that are fundamental to Ashkenazi Jewsish cuisine. They were a staple at bakeries in New York throughout the 20th century but are hard to find outside of areas with large Ashkenazi populations. Bagels simply get all the glory.&lt;/p&gt;&#10;&lt;p&gt;Whereas bagels are supposed to be tough and chewy, Bialys are soft, light, and have an even airy crumb structure. Instead of having a hole, they have a divet in the center which has caramelized onions.&lt;/p&gt;</description></item><item><title/><link>https://grantseltzer.github.io/recipes/miami-rolls/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/recipes/miami-rolls/</guid><description>&lt;h1 id="miami-rolls--challah"&gt;Miami rolls + Challah&lt;/h1&gt;&#10;&lt;p&gt;Miami rolls are a challah based onion pocket roll. They&amp;rsquo;re very soft, sweet, flavorful, and delicious. Pretty traditional to jewish bakeries in New York. I worked at a bakery all throughout high school and these were my favorite things there. When they closed down in 2020 I tried to get the recipe but the owner wouldn&amp;rsquo;t share it with me. Through 15+ iterations I have engineered a recipe that is exactly how I remember them. This recipe is truly worth sharing to keep the tradition of them alive considering so many classic New York bakeries continue to go out of business. I have no clue why they&amp;rsquo;re named Miami rolls.&lt;/p&gt;</description></item><item><title/><link>https://grantseltzer.github.io/recipes/recipes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/recipes/recipes/</guid><description>&lt;p&gt;Recipes:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="../miami-rolls"&gt;Miami Rolls&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="../bialys"&gt;Bialys&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="../split-pea"&gt;Split Pea Soup&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title/><link>https://grantseltzer.github.io/recipes/rye-bread/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/recipes/rye-bread/</guid><description/></item><item><title/><link>https://grantseltzer.github.io/recipes/split-pea/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/recipes/split-pea/</guid><description>&lt;h1 id="split-pea-soup"&gt;Split Pea Soup&lt;/h1&gt;&#10;&lt;h2 id="ingredients"&gt;Ingredients&lt;/h2&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;2 cups green split peas&#10;7 cups vegetable broth&#10;1 cup coconut milk&#10;1 cup dried potato flakes&#10;2 large yellow onions&#10;2 tbs minced garlic&#10;2 tbs diced fresh ginger&#10;1 bunch of parsely&#10;3 tbs olive oil&#10;&#10;1 tbs herbs de provence&#10;2 tbs curry herb blend&#10;1 tbs salt&#10;2 tbs carraway seed&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="instructions"&gt;Instructions&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Chop the yellow onions. Mince the garlic. Dice the ginger. Chop the parsely.&lt;/p&gt;</description></item><item><title>About Me</title><link>https://grantseltzer.github.io/about/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/about/about/</guid><description>&lt;p&gt;My name is Grant Seltzer Richman. I currently work at Datadog. I have worked as a software engineer at &lt;a href="https://www.aquasec.com/"&gt;Aqua&lt;/a&gt;, &lt;a href="https://www.hioscar.com/"&gt;Oscar Health&lt;/a&gt;, &lt;a href="https://capsule8.com/"&gt;Capsule8&lt;/a&gt;, and &lt;a href="https://www.redhat.com/en"&gt;Red Hat&lt;/a&gt;. My interests include systems programming, cycling, triathlon, security, video games, baseball, and reading. I mostly will be writing blog posts about linux, security, and various hobbies.&lt;/p&gt;&#10;&lt;p&gt;Feel free to reach out if you want to say hi!&lt;/p&gt;</description></item><item><title>Bird Search</title><link>https://grantseltzer.github.io/random/bird-search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://grantseltzer.github.io/random/bird-search/</guid><description>&lt;p&gt;A quick tool I use for birding. If I&amp;rsquo;m searching for a specific species I use this to see where other birders have reported sightings on &lt;a href="https://ebird.org/home"&gt;eBird&lt;/a&gt;. It gives all checklists within the specified parameters.&lt;/p&gt;&#10;&lt;p&gt;Try it yourself! Get an eBird &lt;a href="https://ebird.org/api/keygen"&gt;API Token&lt;/a&gt;. Enter your region, look for the bird of your dreams! Birding is fun!&lt;/p&gt;</description></item></channel></rss>