<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Emanuele Rocca</title>
    <link>https://www.linux.it/~ema/</link>
    <description>Recent content on Emanuele Rocca</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>ema@linux.it (Emanuele Rocca)</managingEditor>
    <webMaster>ema@linux.it (Emanuele Rocca)</webMaster>
    <lastBuildDate>Fri, 13 Dec 2024 16:31:40 +0100</lastBuildDate>
    <atom:link href="https://www.linux.it/~ema/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Murder Mystery: GCC Builds Failing After sbuild Refactoring</title>
      <link>https://www.linux.it/~ema/posts/murder-mystery-gcc-builds-failing-after-sbuild-refactoring/</link>
      <pubDate>Fri, 13 Dec 2024 16:31:40 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/murder-mystery-gcc-builds-failing-after-sbuild-refactoring/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;This is the story of an investigation conducted by Jochen Sprickerhof, Helmut
Grohne, and myself. It was true teamwork, and we would have not reached the
bottom of the issue working individually. We think you will find it as
interesting and fun as we did, so here is a brief writeup. A few of the steps
mentioned here took several days, others just a few minutes. What is described
as a natural progression of events did not always look very obvious at the
moment at all.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Let us go through the Six Stages of Debugging together.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_stage_1_that_cannot_happen&#34;&gt;Stage 1: That cannot happen&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Official Debian GCC builds start failing on multiple architectures in late
November.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The build error happens on the build servers when running the testuite, but we
know this cannot happen. GCC builds are not meant to fail in case of testsuite
failures!  Return codes are not making the build fail, &lt;code&gt;make&lt;/code&gt; is being called
with &lt;code&gt;-k&lt;/code&gt;, it just cannot happen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;A &lt;strong&gt;lot&lt;/strong&gt; of the GCC tests are always failing in fact, and an extensive log of
the results is posted to &lt;a href=&#34;https://lists.debian.org/debian-gcc/&#34;&gt;the debian-gcc
mailing list&lt;/a&gt;, but the packages always build fine regardless.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;On the build daemons,
&lt;a href=&#34;https://buildd.debian.org/status/fetch.php?pkg=gcc-14&amp;amp;arch=amd64&amp;amp;ver=14.2.0-9&amp;amp;stamp=1732815893&amp;amp;raw=0&#34;&gt;build
failures take several hours&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_stage_2_that_does_not_happen_on_my_machine&#34;&gt;Stage 2: That does not happen on my machine&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Building on my machine running Bookworm is just fine. The Build Daemons run
Bookworm and use a Sid chroot for the build environment, just like I am. Same
kernel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Debian packages are built by &lt;a href=&#34;https://buildd.debian.org/&#34;&gt;a network of
autobuilding machines&lt;/a&gt; using a program called
&lt;a href=&#34;https://wiki.debian.org/sbuild&#34;&gt;sbuild&lt;/a&gt;. In my last blog post
&lt;a href=&#34;https://www.linux.it/~ema/posts/building-debian-packages-the-right-way/&#34;&gt;I
mentioned the transition from the schroot backend to a new one based on
unshare&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The only obvious difference between my setup and the Debian buildds is that I
am using sbuild &lt;strong&gt;0.85.0&lt;/strong&gt; from bookworm, and the buildds have &lt;strong&gt;0.86.3~bpo12+1&lt;/strong&gt;
from bookworm-backports. Trying again with &lt;strong&gt;0.86.3~bpo12+1&lt;/strong&gt;, the build fails on
my system too. The build daemons were updated to the bookworm-backports version
of sbuild at some point in late November. Ha.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_stage_3_that_should_not_happen&#34;&gt;Stage 3: That should not happen&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There are quite a few sbuild versions in between 0.85.0  and 0.86.3~bpo12+1,
but looking at recent sbuild bugs shows that
&lt;a href=&#34;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1084956&#34;&gt;sbuild 0.86.0 was
breaking &amp;#34;quite a number of packages&amp;#34;&lt;/a&gt;. Indeed, with 0.86.0 the build still
fails. Trying the version immediately before, 0.85.11, the build finishes
correctly. This took more time than it sounds, one run including the tests
takes several hours. We need a way to shorten this somehow.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The Debian packaging of GCC allows to specify which languages you may want to
skip, and by default it builds Ada, Go, C, C++, D, Fortran, Objective
C, Objective C++, M2, and Rust. When running the tests sequentially,
the build logs stop roughly around the tests of a runtime library for D,
libphobos. So can we still reproduce the failure by skipping everything except
for D? With
&lt;code&gt;DEB_BUILD_OPTIONS=nolang=ada,go,c,c++,fortran,objc,obj-c++,m2,rust&lt;/code&gt;
the build still fails, and it fails faster than before. Several minutes, not
hours. This is progress, and time to file a bug. The report contains massive
spoilers, so no link. :-)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_stage_4_why_does_that_happen&#34;&gt;Stage 4: Why does that happen?&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Something is causing the build to end prematurely. It’s not the OOM killer, and
the kernel does not have anything useful to say in the logs. Can it be that the
D language tests are sending signals to some process, and that is what’s
killing &lt;code&gt;make&lt;/code&gt; ? We start tracing signals sent with &lt;code&gt;bpftrace&lt;/code&gt; by writing the
following script, &lt;code&gt;signals.bt&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;tracepoint:signal:signal_generate {
    printf(&amp;#34;%s PID %d (%s) sent signal %d to PID %d\n&amp;#34;, comm, pid, args-&amp;gt;sig, args-&amp;gt;pid);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;And executing it with &lt;code&gt;sudo bpftrace signals.bt&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The build takes its sweet time, and it fails. Looking at the trace output
there’s a suspicious &lt;code&gt;process.exe&lt;/code&gt; terminating stuff.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;process.exe (PID: 2868133) sent signal 15 to PID 711826&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;That looks interesting, but we have no clue what PID 711826 may be. Let’s change
the script a bit, and trace signals received as well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;tracepoint:signal:signal_generate {
    printf(&amp;#34;PID %d (%s) sent signal %d to %d\n&amp;#34;, pid, comm, args-&amp;gt;sig, args-&amp;gt;pid);
}

tracepoint:signal:signal_deliver {
    printf(&amp;#34;PID %d (%s) received signal %d\n&amp;#34;, pid, comm, args-&amp;gt;sig);
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The working version of sbuild was using &lt;code&gt;dumb-init&lt;/code&gt;, whereas the new one
features
&lt;a href=&#34;https://salsa.debian.org/debian/sbuild/-/commit/e5a5dc7d258e939e62ad73f7b60f0b47507c6565&#34;&gt;a
little init in perl&lt;/a&gt;. We patch the current version of sbuild by making it use
&lt;code&gt;dumb-init&lt;/code&gt; instead, and trace two builds: one with the perl init, one with
&lt;code&gt;dumb-init&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here are the signals observed when building with &lt;code&gt;dumb-init&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;PID 3590011 (process.exe) sent signal 2 to 3590014
PID 3590014 (sleep) received signal 9
PID 3590011 (process.exe) sent signal 15 to 3590063
PID 3590063 (std.process tem) received signal 9
PID 3590011 (process.exe) sent signal 9 to 3590065
PID 3590065 (std.process tem) received signal 9&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;And this is what happens with the new init in perl:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;PID 3589274 (process.exe) sent signal 2 to 3589291
PID 3589291 (sleep) received signal 9
PID 3589274 (process.exe) sent signal 15 to 3589338
PID 3589338 (std.process tem) received signal 9
PID 3589274 (process.exe) sent signal 9 to 3589340
PID 3589340 (std.process tem) received signal 9
PID 3589274 (process.exe) sent signal 15 to 3589341
PID 3589274 (process.exe) sent signal 15 to 3589323
PID 3589274 (process.exe) sent signal 15 to 3589320
PID 3589274 (process.exe) sent signal 15 to 3589274
PID 3589274 (process.exe) received signal 9
PID 3589341 (sleep) received signal 9
PID 3589273 (sbuild-usernsex) sent signal 9 to 3589320
PID 3589273 (sbuild-usernsex) sent signal 9 to 3589323&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There are a few additional SIGTERM being sent when using the perl init, that’s
helpful. At this point we are fairly convinced that &lt;code&gt;process.exe&lt;/code&gt; is worth
additional inspection. The
&lt;a href=&#34;https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libphobos/src/std/process.d;h=494910f35350927a561c98c78f6b19fe20a579a9;hb=HEAD#l1221&#34;&gt;source
code of process.d&lt;/a&gt; shows something interesting:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;1221 @system unittest
1222 {
[...]
1247     auto pid = spawnProcess([&amp;#34;sleep&amp;#34;, &amp;#34;10000&amp;#34;],
[...]
1260     // kill the spawned process with SIGINT
1261     // and send its return code
1262     spawn((shared Pid pid) {
1263         auto p = cast() pid;
1264         kill(p, SIGINT);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;So yes, there’s our &lt;code&gt;sleep&lt;/code&gt; and the SIGINT (signal 2) right in the unit tests
of &lt;code&gt;process.d&lt;/code&gt;, just like we have observed in the bpftrace output.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Can we study the behavior of &lt;code&gt;process.exe&lt;/code&gt; in isolation, separatedly from the
build? Indeed we can. Let’s take the executable from a failed build, and try
running it under /usr/libexec/sbuild-usernsexec.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;First, we prepare a chroot inside a suitable user namespace:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;unshare --map-auto --setuid 0 --setgid 0 mkdir /tmp/rootfs
cd /tmp/rootfs
cat /home/ema/.cache/sbuild/unstable-arm64.tar | unshare --map-auto --setuid 0 --setgid 0 tar xf  -
unshare --map-auto --setuid 0 --setgid 0 mkdir /tmp/rootfs/whatever
unshare --map-auto --setuid 0 --setgid 0 cp process.exe /tmp/rootfs/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now we can run &lt;code&gt;process.exe&lt;/code&gt; on its own using the perl init, and trace signals at will:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;/usr/libexec/sbuild-usernsexec --pivotroot --nonet u:0:100000:65536  g:0:100000:65536 /tmp/rootfs ema /whatever -- /process.exe&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;We can compare the behavior of the perl init vis-a-vis the one using
&lt;code&gt;dumb-init&lt;/code&gt; in milliseconds instead of minutes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_stage_5_oh_i_see&#34;&gt;Stage 5: Oh, I see.&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Why does &lt;code&gt;process.exe&lt;/code&gt; send more SIGTERMs when using the perl init is now the
big question. We have a simple reproducer, so this is where using &lt;code&gt;strace&lt;/code&gt;
becomes possible.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo strace --user ema --follow-forks -o sbuild-dumb-init.strace ./sbuild-usernsexec-dumb-init --pivotroot --nonet u:0:100000:65536  g:0:100000:65536 /tmp/dumbroot ema /whatever -- /process.exe&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;We start comparing &lt;a href=&#34;https://people.debian.org/~ema/sbuild-dumb-init.strace&#34;&gt;the
strace output of dumb-init&lt;/a&gt; with
&lt;a href=&#34;https://people.debian.org/~ema/sbuild-perl-init.strace&#34;&gt;that of perl-init&lt;/a&gt;,
looking in particular for different calls to &lt;code&gt;kill&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here is what &lt;code&gt;process.exe&lt;/code&gt; does under dumb-init:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;3593883 kill(-2, SIGTERM)               = -1 ESRCH (No such process)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;No such process. Under &lt;code&gt;perl-init&lt;/code&gt; instead:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;3593777 kill(-2, SIGTERM &amp;lt;unfinished ...&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The process &lt;strong&gt;is&lt;/strong&gt; there under &lt;code&gt;perl-init&lt;/code&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;That is a kill with negative pid. From the &lt;code&gt;kill(2)&lt;/code&gt; man page:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;It would have been &lt;strong&gt;very&lt;/strong&gt; useful to see this kill with negative pid in the
output of bpftrace, why didn’t we? The tracepoint used,
&lt;code&gt;tracepoint:signal:signal_generate&lt;/code&gt;, shows when signals are actually being
sent, and not the syscall being called. To confirm, one can trace
&lt;code&gt;tracepoint:syscalls:sys_enter_kill&lt;/code&gt; and see the negative PIDs, for example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;PID 312719 (bash) sent signal 2 to -312728&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The obvious question at this point is: why is there no process group 2 when
using &lt;code&gt;dumb-init&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_stage_6_how_did_that_ever_work&#34;&gt;Stage 6: How did that ever work?&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;We know that &lt;code&gt;process.exe&lt;/code&gt; sends a SIGTERM to every process in the process
group with ID 2. To find out what this process group may be, we spawn a shell
with &lt;code&gt;dumb-init&lt;/code&gt; and observe under &lt;code&gt;/proc&lt;/code&gt; PIDs 1, 16, and 17. With &lt;code&gt;perl-init&lt;/code&gt;
we have 1, &lt;strong&gt;2&lt;/strong&gt;, and 17. When running dumb-init, there are a few forks before
launching the program, explaining the difference. Looking at &lt;code&gt;/proc/2/cmdline&lt;/code&gt;
we see that it’s bash, ie. the program we are running under &lt;code&gt;perl-init&lt;/code&gt;. When
building a package, that is &lt;code&gt;dpkg-buildpackage&lt;/code&gt; itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The test is accidentally killing its own process group.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now where does this &lt;code&gt;-2&lt;/code&gt; come from in the test?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;2363     // Special values for _processID.
2364     enum invalid = -1, terminated = -2;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Oh. -2 is used as a special value for PID, meaning &amp;#34;terminated&amp;#34;. And there’s a
call to kill() later on:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;2694     do { s = tryWait(pid); } while (!s.terminated);
[...]
2697     assertThrown!ProcessException(kill(pid));&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;What sets &lt;code&gt;pid&lt;/code&gt; to &lt;code&gt;terminated&lt;/code&gt; you ask?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here is &lt;code&gt;tryWait&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;2568 auto tryWait(Pid pid) @safe
2569 {
2570     import std.typecons : Tuple;
2571     assert(pid !is null, &amp;#34;Called tryWait on a null Pid.&amp;#34;);
2572     auto code = pid.performWait(false);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;And &lt;code&gt;performWait&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;2306         _processID = terminated;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The solution, dear reader, is &lt;a href=&#34;https://github.com/dlang/phobos/pull/10586/files&#34;&gt;not to kill&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;PS: the bug report with spoilers for those interested is
&lt;a href=&#34;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1089007&#34;&gt;#1089007&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Building Debian packages The Right Way</title>
      <link>https://www.linux.it/~ema/posts/building-debian-packages-the-right-way/</link>
      <pubDate>Tue, 26 Nov 2024 09:34:40 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/building-debian-packages-the-right-way/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There is more than one way to do it, but it seems that The Right Way to build
Debian packages today is using &lt;a href=&#34;https://wiki.debian.org/sbuild&#34;&gt;sbuild&lt;/a&gt; with the
&lt;a href=&#34;https://manpages.debian.org/unstable/util-linux/unshare.1.en.html&#34;&gt;unshare&lt;/a&gt;
backend. The most common backend before the rise of unshare was
&lt;a href=&#34;https://manpages.debian.org/unstable/schroot/schroot.1.en.html&#34;&gt;schroot&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The official Debian Build Daemons
&lt;a href=&#34;https://lists.debian.org/debian-devel-announce/2024/11/msg00002.html&#34;&gt;have
recently transitioned to using sbuild with unshare&lt;/a&gt;, providing a strong
motivation to consider making the switch. Additionally the new approach means:
(1) no need to configure schroot, and (2) no need to run the build as root.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here are my notes about moving to the new setup, for future reference and in
case they may be useful to others.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;First I installed the required packages:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;apt install sbuild mmdebstrap uidmap&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Then I created the following script to update my chroots every night:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;#!/bin/bash

for arch in arm64 armhf armel; do
    HOME=/tmp mmdebstrap --quiet --arch=$arch --include=ca-certificates --variant=buildd unstable \
        ~/.cache/sbuild/unstable-$arch.tar http://127.0.0.1:3142/debian
done&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;In the script, I’m calling &lt;code&gt;mmdebstrap&lt;/code&gt; with &lt;code&gt;--quiet&lt;/code&gt; because I don’t want to get
any output on succesful execution. The script is running in cron with email
notifications, and I only want to get a message if something goes south. I’m
setting &lt;code&gt;HOME=/tmp&lt;/code&gt; for a similar reason: the unshare user does not have access
to my actual home directory, and by default dpkg tries to use &lt;code&gt;$HOME/.dpkg.cfg&lt;/code&gt;
as the configuration file. By overriding &lt;code&gt;HOME&lt;/code&gt; I avoid the following message
to standard error:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;dpkg: warning: failed to open configuration file &amp;#39;/home/ema/.dpkg.cfg&amp;#39; for reading: Permission denied&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Then I added the following to my sbuild configuration file (&lt;code&gt;~/.sbuildrc&lt;/code&gt;):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$chroot_mode = &amp;#39;unshare&amp;#39;;
$unshare_tmpdir_template = &amp;#39;/dev/shm/tmp.sbuild.XXXXXXXXXX&amp;#39;;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The first option sets the sbuild backend to unshare, whereas
&lt;code&gt;unshare_tmpdir_template&lt;/code&gt; is needed on Bookworm to ensure that the build process
runs in memory rather than on disk for performance reasons. Starting with
Trixie, &lt;code&gt;/tmp&lt;/code&gt; is by default a tmpfs so the setting won’t be needed anymore.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Packages for different architectures can now be built as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# Tarball used: ~/.cache/sbuild/unstable-arm64.tar
$ sbuild --dist=unstable hello

# Tarball used: ~/.cache/sbuild/unstable-armhf.tar
$ sbuild --dist=unstable --arch=armhf hello&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If you have any comments or suggestions about any of this,
&lt;a href=&#34;https://www.linux.it/~ema/contacts/&#34;&gt;please let me know&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>PGP keys on Yubikey, with a side of Mutt</title>
      <link>https://www.linux.it/~ema/posts/pgp-keys-on-yubikey/</link>
      <pubDate>Fri, 05 Apr 2024 15:22:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/pgp-keys-on-yubikey/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here are my notes about copying PGP keys to external hardware devices such as
Yubikeys. Let me begin by saying that the gpg tools are pretty bad at this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;MAKE A COUPLE OF BACKUPS OF &lt;code&gt;~/.gnupg/&lt;/code&gt; TO DIFFERENT ENCRYPTED USB STICKS
BEFORE YOU START. GPG WILL MESS UP YOUR KEYS. SERIOUSLY.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;For example, would you believe me if I said that &lt;strong&gt;saving&lt;/strong&gt; changes results in
the removal of your private key? Well
&lt;a href=&#34;https://lists.gnupg.org/pipermail/gnupg-users/2016-July/056353.html&#34;&gt;check this
out&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now that you have multiple safe, offline backups of your keys, here are my notes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;apt install yubikey-manager scdaemon&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Plug the Yubikey in, see if it’s recognized properly:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;ykman list
gpg --card-status&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Change the default PIN (123456) and Admin PIN (12345678):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg --card-edit
gpg/card&amp;gt; admin
gpg/card&amp;gt; passwd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Look at the openpgp information and change the maximum number of retries, if
you like. I have seen this failing a couple of times, unplugging the Yubikey
and putting it back in worked.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;ykman openpgp info
ykman openpgp access set-retries 7 7 7&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Copy your keys. MAKE A BACKUP OF &lt;code&gt;~/.gnupg/&lt;/code&gt; BEFORE YOU DO THIS.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg --edit-key $KEY_ID
gpg&amp;gt; keytocard # follow the prompts to copy the first key&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now choose the next key and copy that one too. Repeat till all subkeys are
copied.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg&amp;gt; key 1
gpg&amp;gt; keytocard&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Typing &lt;code&gt;gpg --card-status&lt;/code&gt; you should be able to see all your keys on the
Yubikey now.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_using_the_key_on_another_machine&#34;&gt;Using the key on another machine&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;How do you use your PGP keys on the Yubikey on other systems?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Go to another system, if it does have a &lt;code&gt;~/.gnupg&lt;/code&gt; directory already move it
somewhere else.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;apt install scdaemon&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Import your public key:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg -k
gpg --keyserver pgp.mit.edu --recv-keys $KEY_ID&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Check the fingerprint and if it is indeed your key say you trust it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg --edit-key $KEY_ID
&amp;gt; trust
&amp;gt; 5
&amp;gt; y
&amp;gt; save&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now try &lt;code&gt;gpg --card-status&lt;/code&gt; and &lt;code&gt;gpg --list-secret-keys&lt;/code&gt;, you should be able to
see your keys. Try signing something, it should work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg --output /tmp/x.out --sign /etc/motd
gpg --verify /tmp/x.out&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_using_the_yubikey_with_mutt&#34;&gt;Using the Yubikey with Mutt&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If you’re using mutt with IMAP, there is a very simple trick to safely store
your password on disk. Write down your IMAP password to a file in a safe
location, say &lt;code&gt;~/.mutt_password&lt;/code&gt;. Then encrypt it and remove the plain-text
file:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;gpg --encrypt ~/.mutt_password # This will create ~/.mutt_password.gpg
rm ~/.mutt_password&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Add the following to &lt;code&gt;~/.muttrc&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;set imap_pass=`gpg --decrypt ~/.mutt_password.gpg`&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;With the above, mutt now prompts you to insert the Yubikey and type your PIN in
order to connect to the IMAP server.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Enabling Kernel Settings in Debian</title>
      <link>https://www.linux.it/~ema/posts/enabling-kernel-settings-in-debian/</link>
      <pubDate>Mon, 12 Feb 2024 09:52:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/enabling-kernel-settings-in-debian/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;This time it’s about enabling new kernel config options in the official Debian
kernel packages. A few dependencies are needed to run the various scripts used
by the Debian kernel folks, as well as to build the kernel itself:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;apt install git gpg python3-debian python3-dacite
apt build-dep linux&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;With that in place, fetch the &lt;code&gt;linux&lt;/code&gt; and &lt;code&gt;kernel-team&lt;/code&gt; repos:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;git clone --depth 1 https://salsa.debian.org/kernel-team/linux
git clone --depth 1 https://salsa.debian.org/kernel-team/kernel-team&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;So far you’ve only got the Debian-specific bits. Fetch the actual kernel
sources now. In the likely case that you’re building a stable kernel, run the
following from within the &lt;code&gt;linux&lt;/code&gt; directory:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;debian/bin/genorig.py https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Use the &lt;code&gt;torvalds&lt;/code&gt; repo if you’re building an RC version instead:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;debian/bin/genorig.py https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now generate the upstream tarball as well as &lt;code&gt;debian/control&lt;/code&gt;. The first
command will take a bit, and the second command will fail: but that’s success — just as the output says.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;debian/rules orig
debian/rules debian/control&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now generate patched sources with:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;debian/rules source&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Time to edit the Kconfig and enable/disable whatever setting you wanted to
change. Take a look around the files under &lt;code&gt;debian/config/&lt;/code&gt; to see where your
changes should go. If it’s a setting shared among multiple architectures that
may be &lt;code&gt;debian/config/config&lt;/code&gt;. For x86-specific things, the file is
&lt;code&gt;debian/config/amd64/config&lt;/code&gt;. On aarch64 &lt;code&gt;debian/config/arm64/config&lt;/code&gt;. If in
doubt, you could try asking &lt;code&gt;#debian-kernel&lt;/code&gt; on IRC.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;It may look like you need to figure out where exactly in the file the setting
should be placed. That is not the case. There’s a helpful script fixing things
up for you:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;../kernel-team/utils/kconfigeditor2/process.py .&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The above will fail if you forgot to run &lt;code&gt;debian/rules source&lt;/code&gt;. The
&lt;code&gt;debian/build/source_rt/Kconfig&lt;/code&gt; file is needed by the script:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;Traceback (most recent call last):
  File &amp;#34;/tmp/linux/../kernel-team/utils/kconfigeditor2/process.py&amp;#34;, line 19, in __init__
    menu = fs_menu[featureset or &amp;#39;none&amp;#39;]
           ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
KeyError: &amp;#39;rt&amp;#39;

During handling of the above exception, another exception occurred:
[...]
FileNotFoundError: [Errno 2] No such file or directory: &amp;#39;./debian/build/source_rt/Kconfig&amp;#39;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If that happens, run:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;debian/rules source&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now &lt;code&gt;process.py&lt;/code&gt; should work fine and fix your &lt;code&gt;config&lt;/code&gt; file.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Excellent, now the config is updated and we’re ready to build the kernel. Off
we go:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;export MAKEFLAGS=-j$(nproc)
export DEB_BUILD_PROFILES=&amp;#39;pkg.linux.nokerneldbg pkg.linux.nokerneldbginfo pkg.linux.notools nodoc&amp;#39;
dpkg-buildpackage -b -nc -uc&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Custom Debian Installer and Kernel on a USB stick</title>
      <link>https://www.linux.it/~ema/posts/custom-debian-installer-usb-stick/</link>
      <pubDate>Fri, 06 Oct 2023 11:29:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/custom-debian-installer-usb-stick/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There are many valid reasons to create a custom Debian Installer image. You may
need to pass some special arguments to the kernel, use a different GRUB
version, automate the installation by means of
&lt;a href=&#34;https://wiki.debian.org/DebianInstaller/Preseed&#34;&gt;preseeding&lt;/a&gt;, use a custom
kernel, or modify the installer itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If you have a EFI system, which is probably the case in 2023, there is no need
to learn complex procedures in order to create a custom Debian Installer stick.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The source of many frustrations is that the ISO format for CDs/DVDs is
read-only, but you can just create a VFAT filesystem on a USB stick, copy all
ISO contents onto the stick itself, and modify things at will.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_create_a_writable_usb_stick&#34;&gt;Create a writable USB stick&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;First create a FAT32 filesystem on the removable device and mount it. The
device is &lt;code&gt;sdX&lt;/code&gt; in the example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo parted --script /dev/sdX mklabel msdos
$ sudo parted --script /dev/sdX mkpart primary fat32 0% 100%
$ sudo mkfs.vfat /dev/sdX1
$ sudo mount /dev/sdX1 /mnt/data/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Then copy to the USB stick the installer ISO you would like to modify,
&lt;code&gt;debian-testing-amd64-netinst.iso&lt;/code&gt; here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo kpartx -v -a debian-testing-amd64-netinst.iso

# Mount the first partition on the ISO and copy its contents to the stick
$ sudo mount /dev/mapper/loop0p1 /mnt/cdrom/
$ sudo rsync -av /mnt/cdrom/ /mnt/data/
$ sudo umount /mnt/cdrom

# Same story with the second partition on the ISO
$ sudo mount /dev/mapper/loop0p2 /mnt/cdrom/
$ sudo rsync -av /mnt/cdrom/ /mnt/data/
$ sudo umount /mnt/cdrom

$ sudo kpartx -d debian-testing-amd64-netinst.iso
$ sudo umount /mnt/data&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now try booting from the USB stick just to verify that everything went well and
we can start customizing the image.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_boot_loader_preseeding_installer_hacks&#34;&gt;Boot loader, preseeding, installer hacks&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The easiest things we can change now are the shim, GRUB, and GRUB’s
configuration. The USB stick contains the shim under &lt;code&gt;/EFI/boot/bootx64.efi&lt;/code&gt;,
while GRUB is at &lt;code&gt;/EFI/boot/grubx64.efi&lt;/code&gt;. This means that if you want to test a
different shim / GRUB version, you just replace the relevant files. That’s it.
Take for example &lt;code&gt;/usr/lib/grub/x86_64-efi/monolithic/grubx64.efi&lt;/code&gt; from the
package &lt;code&gt;grub-efi-amd64-bin&lt;/code&gt;, or the signed version from
&lt;code&gt;grub-efi-amd64-signed&lt;/code&gt; and copy them under &lt;code&gt;/EFI/boot/grubx64.efi&lt;/code&gt;. Or perhaps
you want to try out systemd-boot? Then take
&lt;code&gt;/usr/lib/systemd/boot/efi/systemd-bootx64.efi&lt;/code&gt; from the package
&lt;code&gt;systemd-boot-efi&lt;/code&gt;, copy it to &lt;code&gt;/EFI/boot/bootx64.efi&lt;/code&gt; and you’re good to go.
Figuring out the right systemd-boot configuration needed to start the Installer
is left as an exercise.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;By editing &lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt; you can pass arbitrary arguments to the kernel
and the Installer itself. See &lt;a href=&#34;https://www.debian.org/releases/stable/amd64/ch05s03.en.html&#34;&gt;the official
Installation Guide&lt;/a&gt; for a comprehensive list of boot parameters.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;One very commong thing to do is automating the installation using a preseed
file. Add the following to the kernel command line:
&lt;code&gt;preseed/file=/cdrom/preseed.cfg&lt;/code&gt; and create a &lt;code&gt;/preseed.cfg&lt;/code&gt; file on the USB
stick. As a little example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;d-i time/zone select Europe/Rome
d-i passwd/root-password this-is-the-root-password
d-i passwd/root-password-again this-is-the-root-password
d-i passwd/user-fullname string Emanuele Rocca
d-i passwd/username string ema
d-i passwd/user-password password lol-haha-uh
d-i passwd/user-password-again password lol-haha-uh
d-i apt-setup/no_mirror boolean true
d-i popularity-contest/participate boolean true
tasksel tasksel/first multiselect standard&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;See Steve McIntyre’s awesome page with the full list of available settings and
their description: &lt;a href=&#34;https://preseed.einval.com/debian-preseed/&#34; class=&#34;bare&#34;&gt;https://preseed.einval.com/debian-preseed/&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Two noteworthy settings are &lt;code&gt;early_command&lt;/code&gt; and &lt;code&gt;late_command&lt;/code&gt;. They can be
used to execute arbitrary commands and provide thus extreme flexibility! You
can go as far as replacing parts of the installer with a sed command, or maybe
wgetting an entirely different file. This is a fairly easy way to test minor
Installer patches. As an example, I’ve once used this to test a patch to
&lt;code&gt;grub-installer&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;d-i partman/early_command string wget https://people.debian.org/~ema/grub-installer-1035085-1 -O /usr/bin/grub-installer&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Finally, the initrd contains all early stages of the installer. It’s easy to
unpack it, modify whatever component you like, and repack it. Say you want to
change a given udev rule:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ mkdir /tmp/new-initrd
$ cd /tmp/new-initrd
$ zstdcat /mnt/data/install.a64/initrd.gz | sudo cpio -id
$ vi lib/udev/rules.d/60-block.rules
$ find . | cpio -o -H newc | zstd --stdout &amp;gt; /mnt/data/install.a64/initrd.gz&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_custom_udebs&#34;&gt;Custom udebs&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;From a basic architectural standpoint the Debian Installer can be seen as an
initrd that loads a series of special Debian packages called udebs. In the
previous section we have seen how to (ab)use &lt;code&gt;early_command&lt;/code&gt; to replace one of
the scripts used by the Installer, namely &lt;code&gt;grub-installer&lt;/code&gt;. It turns out that
such script is installed by a udeb, so let’s do things right and build a new
Installer ISO with our custom grub udeb.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Fetch the code for the
&lt;a href=&#34;https://salsa.debian.org/installer-team/grub-installer&#34;&gt;grub-installer&lt;/a&gt; udeb,
make your changes and build it with a classic
&lt;code&gt;dpkg-buildpackage -rfakeroot&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Then get the Installer code and install all dependencies:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ git clone https://salsa.debian.org/installer-team/debian-installer/
$ cd debian-installer/
$ sudo apt build-dep .&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now add the &lt;code&gt;grub-installer&lt;/code&gt; udeb to the &lt;code&gt;localudebs&lt;/code&gt; directory and create a
new netboot image:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ cp /path/to/grub-installer_1.198_arm64.udeb build/localudebs/
$ cd build
$ fakeroot make clean_netboot build_netboot&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Give it some time, soon enough you’ll have a brand new ISO to test under
&lt;code&gt;dest/netboot/mini.iso&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_custom_kernel&#34;&gt;Custom kernel&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Perhaps there’s a kernel configuration option you need to enable, or maybe you
need a more recent kernel version than what is available in sid.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The &lt;a href=&#34;https://kernel-team.pages.debian.net/kernel-handbook/&#34;&gt;Debian Linux Kernel
Handbook&lt;/a&gt; has all the details for how to do things properly, but here’s a quick
example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Get the Debian kernel packaging from salsa and generate the upstream tarball:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ git clone https://salsa.debian.org/kernel-team/linux/
$ ./debian/bin/genorig.py https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;For RC kernels use
&lt;a href=&#34;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&#34;&gt;the repo
from Linus&lt;/a&gt; instead of &lt;code&gt;linux-stable&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now do your thing, for instance change a config setting by editing
&lt;code&gt;debian/config/amd64/config&lt;/code&gt;. Don’t worry about where you put it in the file,
there’s a tool from &lt;a href=&#34;https://salsa.debian.org/kernel-team/kernel-team&#34; class=&#34;bare&#34;&gt;https://salsa.debian.org/kernel-team/kernel-team&lt;/a&gt; to fix that:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ /path/to/kernel-team/utils/kconfigeditor2/process.py .&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now build your kernel:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ export MAKEFLAGS=-j$(nproc)
$ export DEB_BUILD_PROFILES=&amp;#39;pkg.linux.nokerneldbg pkg.linux.nokerneldbginfo pkg.linux.notools nodoc&amp;#39;
$ debian/rules orig
$ debian/rules debian/control
$ dpkg-buildpackage -b -nc -uc&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;After some time, if everything went well, you should get a bunch of .deb files
as well as a .changes file, &lt;code&gt;linux_6.6~rc3-1~exp1_arm64.changes&lt;/code&gt; here. To
generate the udebs used by the Installer you need to first get a linux-signed
.dsc file, and then build it — with &lt;code&gt;sbuild&lt;/code&gt; in this example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ /path/to/kernel-team/scripts/debian-test-sign linux_6.6~rc3-1~exp1_arm64.changes
$ sbuild --dist=unstable --extra-package=$PWD linux-signed-arm64_6.6~rc3+1~exp1.dsc&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Excellent, now you should have a ton of .udebs. To build a custom installer
image with this kernel, copy them all under
&lt;code&gt;debian-installer/build/localudebs/&lt;/code&gt; and then run &lt;code&gt;fakeroot make clean_netboot
build_netboot&lt;/code&gt; as described in the previous section. In case you are trying to
use a different kernel version from what is currently in sid, you will have to
install the &lt;code&gt;linux-image&lt;/code&gt; package on the system building the ISO, and change
&lt;code&gt;LINUX_KERNEL_ABI&lt;/code&gt; in &lt;code&gt;build/config/common&lt;/code&gt;. The &lt;code&gt;linux-image&lt;/code&gt; dependency in
&lt;code&gt;debian/control&lt;/code&gt; probably needs to be tweaked as well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;That’s it, the new Installer ISO should boot with your custom kernel!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There is going to be another minor obstacle though, as &lt;code&gt;anna&lt;/code&gt; will
&lt;a href=&#34;https://sources.debian.org/src/anna/1.92/anna.c/?hl=104#L104&#34;&gt;complain&lt;/a&gt; that
your new  kernel cannot be found in the archive. Copy the kernel udebs you have
built onto a vfat formatted USB stick, switch to a terminal, and install them
all with &lt;code&gt;udpkg&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;~ # udpkg -i *.udeb&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now the installation should proceed smoothly.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>UEFI Secure Boot on the Raspberry Pi</title>
      <link>https://www.linux.it/~ema/posts/secure-boot-rpi/</link>
      <pubDate>Thu, 04 May 2023 13:29:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/secure-boot-rpi/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: this post unexpectedly
&lt;a href=&#34;https://news.ycombinator.com/item?id=35815382&#34;&gt;ended up on Hacker News&lt;/a&gt; and I
received a lot of comments. The two most important points being made are (1)
that Secure Boot on the RPi as described here is not actually truly secure. An
attacker who successfully gained root could just mount the firmware partition
and either add their own keys to the EFI variable store or replace the firmware
altogether with a malicious one. (2) The TianCore firmware cannot be used
&lt;em&gt;instead&lt;/em&gt; of the proprietary blob as I mentioned. What truly happens is that
the proprietary blob is loaded onto the VideoCore cores, then TianoCore is
loaded onto the ARM cores. Thanks for the corrections.&lt;/p&gt;
&lt;/div&gt;
&lt;hr/&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;A port of the free software &lt;a href=&#34;https://www.tianocore.org/&#34;&gt;TianoCore&lt;/a&gt; UEFI firmware
can be used instead of the proprietary boot blob to boot the Raspberry Pi.
This allows to install Debian on the RPi with the standard Debian Installer,
and it also makes it possible to use UEFI Secure Boot. Note that Secure Boot
had been broken on arm64 for a while, but it’s now
&lt;a href=&#34;https://www.phoronix.com/news/Debian-ARM64-Secure-Boot-Fix&#34;&gt;working in Bookworm&lt;/a&gt;!.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_debian_installer_uefi_boot&#34;&gt;Debian Installer UEFI boot&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;To begin, you’ll need to download the appropriate firmware files for the
&lt;a href=&#34;https://github.com/pftf/RPi3/releases&#34;&gt;RPi3&lt;/a&gt; or
&lt;a href=&#34;https://github.com/pftf/RPi4/releases&#34;&gt;RPi4&lt;/a&gt;. I’ve got a &lt;strong&gt;Raspberry Pi 3 Model
B+&lt;/strong&gt; myself, so the rest of this document will assume an RPi3 is being
installed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Plug the SD card you are going to use as the RPi storage device into another
system. Say it shows up as &lt;code&gt;/dev/sdf&lt;/code&gt;. Then:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# Create an msdos partition table
$ sudo parted --script /dev/sdf mklabel msdos
# Create, format, and label a 10M fat32 partition
$ sudo parted --script /dev/sdf mkpart primary fat32 0% 10M
$ sudo mkfs.vfat /dev/sdf1
$ sudo fatlabel /dev/sdf1 RPI-FW
# Get the UEFI firmware onto the SD card
$ sudo mount /dev/sdf1 /mnt/data/
$ sudo unzip Downloads/RPi3_UEFI_Firmware_v1.38.zip -d /mnt/data/
$ sudo umount /mnt/data&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;At this point, the SD card can be used to boot the RPi, and you’ll get a UEFI
firmware.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Download the
&lt;a href=&#34;https://cdimage.debian.org/cdimage/bookworm_di_rc2/arm64/iso-cd/&#34;&gt;Bookworm RC 2
release of the installer&lt;/a&gt;, copy it to a USB stick
&lt;a href=&#34;https://www.debian.org/releases/bookworm/arm64/ch04s03.en.html&#34;&gt;as described in
the Installation Guide&lt;/a&gt;, and boot your RPi from the stick. If for some reason
booting from the stick does not happen automatically, enter the firmware
interface with &lt;code&gt;ESC&lt;/code&gt; and choose the USB stick from &lt;code&gt;Boot Manager&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Proceed with the installation as normal, paying attention not to modify the
firmware partition labeled &lt;strong&gt;RPI-FW&lt;/strong&gt;. I initially thought it would be nice to
reuse the firmware partition as ESP partition as well. However, setting the
&lt;code&gt;esp&lt;/code&gt; flag &lt;code&gt;on&lt;/code&gt; makes the RPi unbootable. Either configuring the partition as ESP
in debian-installer, or manually with &lt;code&gt;sudo parted --script /dev/sda set 1 esp
on&lt;/code&gt;, breaks boot. In case you accidentally do that, set it back to &lt;code&gt;off&lt;/code&gt; and
the edk2 firmware will boot again.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;What I suggest doing in terms of partitioning is: (1) leave the 10M
partition created above for the firmware alone, and (2) create another 512M or
so ESP partition for EFI boot.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The installation should go smoothly till the end, but rebooting won’t work.
Doh. This is because of an important gotcha: the Raspberry Pi port of the
TianoCore firmware we are using
&lt;a href=&#34;https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3#nvram&#34;&gt;does
not support setting UEFI variables persistently from a &amp;#34;High Level Operating
System (HLOS)&amp;#34;&lt;/a&gt;, which is the debian-installer in our case. &lt;strong&gt;Persistently&lt;/strong&gt; is
the keyword there: variables can be set and modified regularly — with
&lt;code&gt;efibootmgr&lt;/code&gt; or otherwise, but crucially the modifications do not survive
reboot. However, changes made from the firmware interface itself &lt;strong&gt;are&lt;/strong&gt;
persistent. So enter the firmware with &lt;code&gt;ESC&lt;/code&gt; right after booting the RPi,
select &lt;code&gt;Boot Maintenance Manager&lt;/code&gt; → &lt;code&gt;Boot Options&lt;/code&gt; → &lt;code&gt;Add Boot Option&lt;/code&gt; →
Your SD card → Your ESP partition → &lt;code&gt;EFI&lt;/code&gt; → &lt;code&gt;debian&lt;/code&gt; → &lt;code&gt;shimaa64.efi&lt;/code&gt;.
Choose a creative name for your boot entry (eg: &amp;#34;debian&amp;#34;), save and exit the
firmware interface. Bookworm should be booting fine at this point!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_enabling_secure_boot&#34;&gt;Enabling Secure Boot&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Although the TianoCore firmware does support Secure Boot, there are no keys
enrolled by default. To add the required keys, copy
&lt;a href=&#34;https://people.debian.org/~ema/sb/debian-ca/PK-0001.der&#34;&gt;PK-0001.der&lt;/a&gt;,
&lt;a href=&#34;https://people.debian.org/~ema/sb/debian-ca/DB-0001.der&#34;&gt;DB-0001.der&lt;/a&gt;,
&lt;a href=&#34;https://people.debian.org/~ema/sb/debian-ca/DB-0002.der&#34;&gt;DB-0002.der&lt;/a&gt;,
&lt;a href=&#34;https://people.debian.org/~ema/sb/debian-ca/KEK-0001.der&#34;&gt;KEK-0001.der&lt;/a&gt;, and
&lt;a href=&#34;https://people.debian.org/~ema/sb/debian-ca/KEK-0002.der&#34;&gt;KEK-0002.der&lt;/a&gt;
to a FAT32 formatted USB stick.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here’s a summary of the Subject field for each of the above:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;PK-0001.der.pem
        Subject: O = Debian, CN = Debian UEFI Secure Boot (PK/KEK key), emailAddress = debian-devel@lists.debian.org
DB-0001.der.pem
        Subject: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Windows Production PCA 2011
DB-0002.der.pem
        Subject: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Corporation UEFI CA 2011
KEK-0001.der.pem
        Subject: O = Debian, CN = Debian UEFI Secure Boot (PK/KEK key), emailAddress = debian-devel@lists.debian.org
KEK-0002.der.pem
        Subject: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Corporation KEK CA 2011&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Plug the stick into the RPi, boot and enter the firmware interface with &lt;code&gt;ESC&lt;/code&gt;.
Select &lt;code&gt;Device Manager&lt;/code&gt; → &lt;code&gt;Secure Boot Configuration&lt;/code&gt; → &lt;code&gt;Secure Boot Mode&lt;/code&gt; →
choose &lt;code&gt;Custom Mode&lt;/code&gt; → &lt;code&gt;Custom Secure Boot Options&lt;/code&gt; → &lt;code&gt;PK Options&lt;/code&gt; → &lt;code&gt;Enroll
PK&lt;/code&gt; → choose &lt;strong&gt;PK-0001.der&lt;/strong&gt;. Do the same for &lt;code&gt;DB Options&lt;/code&gt;, this time choose
&lt;strong&gt;DB-0001.der&lt;/strong&gt; and &lt;strong&gt;DB-0002.der&lt;/strong&gt;. As you may have guessed by now, the same must
be done for &lt;code&gt;KEK Options&lt;/code&gt;, but adding &lt;strong&gt;KEK-0001.der&lt;/strong&gt; and &lt;strong&gt;KEK-0002.der&lt;/strong&gt;. Save,
exit, reboot. If everything went well, your RPi now has booted with Secure Boot
enabled.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;See &lt;a href=&#34;https://wiki.debian.org/SecureBoot&#34; class=&#34;bare&#34;&gt;https://wiki.debian.org/SecureBoot&lt;/a&gt; for the details on how to check whether
Secure Boot has been enabled correctly and much more.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>EFI and Secure Boot Notes</title>
      <link>https://www.linux.it/~ema/posts/efi-sb-notes/</link>
      <pubDate>Sun, 26 Mar 2023 07:18:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/efi-sb-notes/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;To create a bootable EFI drive to use with QEMU, first make a disk image and
create a &lt;code&gt;vfat&lt;/code&gt; filesystem on it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ dd if=/dev/zero of=boot.img bs=1M count=512
$ sudo mkfs.vfat boot.img&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;By default, EFI firmwares boot a specific file under &lt;code&gt;/efi/boot/&lt;/code&gt;. The name of
such file depends on the architecture: for example, on 64 bit x86 systems it is
&lt;code&gt;bootx64.efi&lt;/code&gt;, while on ARM it is &lt;code&gt;bootaa64.efi&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Copy &lt;code&gt;/usr/lib/grub/x86_64-efi/monolithic/grubx64.efi&lt;/code&gt; from package
&lt;code&gt;grub-efi-amd64-bin&lt;/code&gt; to &lt;code&gt;/efi/boot/bootx64.efi&lt;/code&gt; on the boot image, and that
should be enough to start GRUB.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# mount boot.img /mnt/
# mkdir -p /mnt/efi/boot/
# cp /usr/lib/grub/x86_64-efi/monolithic/grubx64.efi /mnt/efi/boot/bootx64.efi
# umount /mnt/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now get the x86 firmware from package &lt;code&gt;ovmf&lt;/code&gt; and start &lt;code&gt;qemu&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ cp /usr/share/OVMF/OVMF_CODE.fd /tmp/code.fd
$ qemu-system-x86_64 -drive file=/tmp/code.fd,format=raw,if=pflash -cdrom boot.img&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;GRUB looks fine, but it would be good to have a kernel to boot. Let’s add one
to &lt;code&gt;boot.img&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# mount boot.img /mnt
# cp vmlinuz-6.1.0-7-amd64 /mnt/vmlinuz
# umount /mnt/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Boot with qemu again, but this time pass &lt;code&gt;-m 1G&lt;/code&gt;. The default amount of
memory is not enough to boot.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ qemu-system-x86_64 -drive file=/tmp/code.fd,format=raw,if=pflash -cdrom boot.img -m 1G&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;At the grub prompt, type the following to boot:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;grub&amp;gt; linux /vmlinuz
grub&amp;gt; boot&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The kernel will start and reach the point of trying to mount the root fs. This
is great but it would now be useful to have some sort of shell access in order
to look around. Let’s add an initrd!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# mount boot.img /mnt
# cp initrd.img-6.1.0-7-amd64 /mnt/initrd
# umount /mnt/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There’s the option of starting qemu in console, let’s try that out. Start qemu
with &lt;code&gt;-nographic&lt;/code&gt;, and append &lt;code&gt;console=ttyS0&lt;/code&gt; to the kernel command line
arguments.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ qemu-system-x86_64 -drive file=/tmp/code.fd,format=raw,if=pflash -cdrom boot.img -m 1G -nographic
grub&amp;gt; linux /vmlinuz console=ttyS0
grub&amp;gt; initrd /initrd
grub&amp;gt; boot&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If all went well we are now in the initramfs shell. We can now run commands! At
this point we can see that the system has Secure boot disabled:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;(initramfs) dmesg | grep secureboot
[    0.000000] secureboot: Secure boot disabled&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;In order to boot with Secure boot, we need:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;ulist&#34;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;a signed shim, grub, and kernel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the right EFI variables for Secure boot&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The package &lt;code&gt;shim-signed&lt;/code&gt; provides a shim signed with Microsoft’s key, while
&lt;code&gt;grub-efi-amd64-signed&lt;/code&gt; has GRUB signed with Debian’s key.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The signatures can be shown with &lt;code&gt;sbverify --list&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sbverify --list /usr/lib/shim/shimx64.efi.signed
warning: data remaining[823184 vs 948768]: gaps between PE/COFF sections?
signature 1
image signature issuers:
 - /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
image signature certificates:
 - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows UEFI Driver Publisher
   issuer:  /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
 - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
   issuer:  /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation Third Party Marketplace Root&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Similarly for GRUB and the kernel:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sbverify --list /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed
signature 1
image signature issuers:
 - /CN=Debian Secure Boot CA
image signature certificates:
 - subject: /CN=Debian Secure Boot Signer 2022 - grub2
   issuer:  /CN=Debian Secure Boot CA
$ sbverify --list /mnt/vmlinuz
signature 1
image signature issuers:
 - /CN=Debian Secure Boot CA
image signature certificates:
 - subject: /CN=Debian Secure Boot Signer 2022 - linux
   issuer:  /CN=Debian Secure Boot CA&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Let’s use the signed shim and grub in the boot image:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# mount boot.img /mnt
# cp /usr/lib/shim/shimx64.efi.signed /mnt/efi/boot/bootx64.efi
# cp /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed /mnt/efi/boot/grubx64.efi
# umount /mnt&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;And start QEMU with the appropriate EFI variables for Secure boot:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ cp /usr/share/OVMF/OVMF_VARS.ms.fd /tmp/vars.fd
$ qemu-system-x86_64 -drive file=/tmp/code.fd,format=raw,if=pflash -drive file=/tmp/vars.fd,format=raw,if=pflash -cdrom boot.img -m 1G -nographic&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;We can double-check in the firmware settings if Secure boot is indeed enabled.
At the GRUB prompt, type &lt;code&gt;fwsetup&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;grub&amp;gt; fwsetup&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Check under &amp;#34;Device Manager&amp;#34; → &amp;#34;Secure Boot Configuration&amp;#34; that &amp;#34;Attempt
Secure Boot&amp;#34; is selected, then boot from GRUB as before. If all went well, the
kernel should confirm that we have booted with Secure boot:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;(initramfs) dmesg | grep secureboot
[    0.000000] secureboot: Secure boot enabled&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Disposable Debian VMs with debvm</title>
      <link>https://www.linux.it/~ema/posts/disposable-debian-vms-debvm/</link>
      <pubDate>Wed, 15 Mar 2023 07:18:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/disposable-debian-vms-debvm/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Some notes on using &lt;code&gt;debvm&lt;/code&gt;, an amazing piece of software I’ve started using
only recently.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Create a new virtual machine:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ debvm-create&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;You now have a virtual machine with Debian Sid of your host native
architecture (probably amd64). The image file is called rootfs.ext4. You’ve
got 1G of disk space in the VM.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;You can now just run the VM! You will be automatically logged is as root.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ debvm-run&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Experiment in the VM, run all the sort of tests you have in mind. For example,
one thing I commonly do is verifying that things work in a clean environment,
as opposed to &amp;#34;on my machine&amp;#34;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If anything goes wrong, or if you just want to repeat the test: shutdown the
guest, remove &lt;code&gt;rootfs.ext4&lt;/code&gt;, and start again with &lt;code&gt;debvm-create&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now, especially if you intend creating and recreating VMs multiple times, it
helps to use a local apt mirror as a cache to avoid fetching all the required
packages from the internet over and over again. Install &lt;code&gt;apt-cacher-ng&lt;/code&gt; on
your host machine and point &lt;code&gt;debvm-create&lt;/code&gt; at it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ debvm-create -- http://10.0.3.1:3142/debian&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The additional options after &lt;code&gt;--&lt;/code&gt; are passed to &lt;code&gt;mmdebstrap&lt;/code&gt;. In this case
we’re specifying &lt;a href=&#34;http://10.0.3.1:3142/debian&#34; class=&#34;bare&#34;&gt;http://10.0.3.1:3142/debian&lt;/a&gt; as the URL of our local apt
mirror. It is going to be used both for image creation and as the only entry in
&lt;code&gt;/etc/apt/sources.list&lt;/code&gt; on the guest. This is the reason for using 10.0.3.1,
the IP address of the lxcbr0 interface used by qemu, instead of 127.0.0.1: to
make sure that the &lt;strong&gt;guest&lt;/strong&gt; VM has access to it too.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;For a slightly more advanced example, we now want to:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;ulist&#34;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;run a arm64 VM&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;have more disk space availably, say 2G&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;install additional packages (&lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;locales&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;allow SSH as root with the given public keys, in this example the
&lt;code&gt;authorized_keys&lt;/code&gt; installed on the host&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;start the VM in the background with no console output&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ debvm-create -a arm64 -o sid-arm64.ext4 -z 2G -k ~/.ssh/authorized_keys -- http://10.0.3.1:3142/debian --include curl,locales&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Start the VM:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ debvm-run -i sid-arm64.ext4 -s 2222 -g -- -display none &amp;amp;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;SSH into the guest:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ ssh -o NoHostAuthenticationForLocalhost=yes -p 2222 root@127.0.0.1&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Running Any Distro on Debian</title>
      <link>https://www.linux.it/~ema/posts/running-any-distro-on-debian/</link>
      <pubDate>Sat, 07 Jan 2023 07:18:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/running-any-distro-on-debian/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;All graybeard hackers know that: (1) Docker is silly, and (2) containers are
very useful. This post is about running pretty much any Linux distribution on
top of a Debian host using chroots, which technically speaking aren’t
containers but for my purposes pretty much are. The chroot can be used in a
disposable fashion or it can be instructed to persist any modifications made to
the filesystem. The tools used for this are
&lt;a href=&#34;https://manpages.debian.org/unstable/schroot/schroot.1.en.html&#34;&gt;schroot&lt;/a&gt;,
&lt;a href=&#34;https://manpages.debian.org/unstable/debootstrap/debootstrap.8.en.html&#34;&gt;debootstrap&lt;/a&gt;,
&lt;a href=&#34;https://manpages.debian.org/unstable/rinse/rinse.8.en.html&#34;&gt;rinse&lt;/a&gt;, and
&lt;a href=&#34;https://manpages.debian.org/unstable/alpine-chroot-install/alpine-chroot-install.8.en.html&#34;&gt;alpine-chroot-install&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_schroot&#34;&gt;schroot&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Back in 2005 when Docker was not a thing yet, lots of the things that Gartner
Inc. likes about containers were very much possible with &lt;strong&gt;chroot&lt;/strong&gt;.  For
example, if all you care about is running commands on a different distro
without messing up your own file system, a chroot will do.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Container is just a fancy name for chroot with namespaces FFS.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Anyways, to configure &lt;code&gt;schroot&lt;/code&gt; you need to edit
&lt;strong&gt;/etc/schroot/schroot.conf&lt;/strong&gt;. For example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;[bullseye]
type=directory
directory=/srv/chroots/bullseye

[fedora-36]
type=file
file=/srv/chroots/fedora-36.tar&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The main commands to remember are just two: &lt;code&gt;schroot -c $name&lt;/code&gt; and
&lt;code&gt;schroot -l&lt;/code&gt;: the former starts a shell in the chroot named
&lt;strong&gt;$name&lt;/strong&gt; (eg: &lt;strong&gt;bullseye&lt;/strong&gt; in the configuration above). The latter
lists all available chroots. That’s it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;ema@pinolo:~$ schroot -l
chroot:bullseye
chroot:fedora-36
ema@pinolo:~$ sudo schroot -c fedora-36
[root@pinolo ema]# cat /etc/redhat-release
Fedora release 36 (Thirty Six)
[root@pinolo ema]#&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There are two main types of chroots: &lt;strong&gt;directory&lt;/strong&gt; or &lt;strong&gt;file&lt;/strong&gt;. A &lt;strong&gt;directory&lt;/strong&gt;
chroot like &lt;strong&gt;bullseye&lt;/strong&gt; in the example above can be modified, meaning that the
results of any command executed within it will persist after leaving the
chroot. Conversely the second example is a &lt;strong&gt;file&lt;/strong&gt; chroot (&lt;strong&gt;fedora-36&lt;/strong&gt;).
&lt;strong&gt;file&lt;/strong&gt; chroots, are ephemeral: you can use them to try whatever disruptive
action you like, and after logging out the chroot will be back to its
original stage.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_creating_pretty_much_any_distro&#34;&gt;Creating pretty much any distro&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;One great thing about Docker is that with dockerhub you can fetch a pre-made
image of whatever distro you care about. If you’re not careful you end up with
a monero miner on your laptop, but I digress.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Luckily for us, Debian has all the tools to bootstrap whatever distro you
fancy in a safe way.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Use &lt;code&gt;debootstrap&lt;/code&gt; to create a Debian distribution (or derivative, including
Ubuntu). For example, to create a &lt;strong&gt;directory&lt;/strong&gt; chroot with Debian Bullseye
under &lt;code&gt;/srv/chroots/bullseye&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo debootstrap bullseye /srv/chroots/bullseye http://deb.debian.org/debian&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Similarly, for a &lt;strong&gt;directory&lt;/strong&gt; chroot with &lt;strong&gt;Ubuntu Kinetic&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo debootstrap kinetic /srv/chroots/kinetic http://archive.ubuntu.com/ubuntu&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;See &lt;code&gt;ls /usr/share/debootstrap/scripts/&lt;/code&gt; for the list of all distros
supported by &lt;strong&gt;debootstrap&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There’s a more modern and under certain aspects better version of debootstrap called &lt;strong&gt;mmdebstrap&lt;/strong&gt;. See the man page for details, but you can create a &lt;strong&gt;file&lt;/strong&gt; chroot with &lt;strong&gt;Debian Sid&lt;/strong&gt; with this simple command:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo mmdebstrap sid /srv/chroots/sid.tar&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;It may be obvious to my astute readers, but let me say it out loud:
you can make a &lt;strong&gt;file&lt;/strong&gt; chroot out of a &lt;strong&gt;directory&lt;/strong&gt; chroot with
&lt;code&gt;tar&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo tar -cvf /srv/chroots/kinetic.tar -C /srv/chroots/kinetic .&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;To create RedHat and derivatives, use &lt;strong&gt;rinse&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo rinse --distribution fedora-36 --arch amd64 --directory /srv/chroots/fedora-36&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;See &lt;code&gt;ls -l /etc/rinse/*.packages&lt;/code&gt; for the list of all distros
supported by &lt;strong&gt;rinse&lt;/strong&gt;. There’s CentOS, OpenSuse, you name it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Alpine Linux can be created with &lt;strong&gt;alpine-chroot-install&lt;/strong&gt; as
follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo alpine-chroot-install -d /srv/chroots/alpine/&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Technically, &lt;strong&gt;pacstrap&lt;/strong&gt; should be able to bootstrap an Arch Linux
installation, but I did not manage to get it to work. If you know how to make
it do the right thing, &lt;a href=&#34;https://www.linux.it/~ema/contacts/&#34;&gt;let me know&lt;/a&gt;! First
I tried:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo pacstrap /srv/chroots/arch/
==&amp;gt; Creating install root at /srv/chroots/arch/
==&amp;gt; Installing packages to /srv/chroots/arch/
error: no usable package repositories configured.
==&amp;gt; ERROR: Failed to install packages to new root&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;To fix that I’ve added the following to &lt;code&gt;pacman.conf&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;[core]
Server = https://mirrors.kernel.org/archlinux/$repo/os/$arch&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Trying the command again however I just got a lot of failed dependencies, and finally:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;:: unable to satisfy dependency &amp;#39;archlinux-keyring&amp;#39; required by base
==&amp;gt; ERROR: Failed to install packages to new root&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;That’s when I gave up and followed
&lt;a href=&#34;https://wiki.archlinux.org/title/Install_Arch_Linux_from_existing_Linux#Method_A:_Using_the_bootstrap_tarball_(recommended)&#34;&gt;the
Arch wiki&lt;/a&gt;, which suggests downloading pre-made tarballs. Hopefully without
monero miners.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Testing Debian Python Packages with Autopkgtest</title>
      <link>https://www.linux.it/~ema/posts/autopkgtest-python-packages/</link>
      <pubDate>Thu, 06 Oct 2022 07:18:40 +0200</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/autopkgtest-python-packages/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;In the past few years
&lt;a href=&#34;https://wiki.debian.org/ContinuousIntegration/autopkgtest&#34;&gt;autopkgtest&lt;/a&gt;
established itself as &lt;strong&gt;the&lt;/strong&gt; system for automated testing of Debian packages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Although there is good documentation available, both in terms of
&lt;a href=&#34;https://manpages.debian.org/testing/autopkgtest/autopkgtest.1.en.html&#34;&gt;the
command itself&lt;/a&gt; and
&lt;a href=&#34;https://salsa.debian.org/ci-team/autopkgtest/raw/master/doc/README.package-tests.rst&#34;&gt;the details about writing tests&lt;/a&gt;,
I often have to look around and copy-paste code to add automated testing to
Python libraries. For this reason, I’m dropping a few notes here. They’re
surely going to be useful for me, and hopefully for others too!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_adding_tests_to_a_packaged_python_library&#34;&gt;Adding tests to a packaged Python library&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If the package you’re working with already has a &lt;strong&gt;debian/tests/&lt;/strong&gt; directory,
then congratulations! It already ships some autopkgtests, so you can just look
around there. Otherwise, go ahead and create the directory. Then, create a file
called &lt;strong&gt;debian/tests/control&lt;/strong&gt; with the following contents:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;Test-Command: for py in $(py3versions -s); do echo &amp;#34;[*] testing on $py:&amp;#34;; $py -c &amp;#39;import module_name&amp;#39; ; done&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Replace &lt;strong&gt;module_name&lt;/strong&gt; with the name of the Python module you want to test,
and you’re done writing some basic automated testing for your Debian Python
package. What the test does is simply trying to import the module, with the
added bonus of doing so for all supported python3 versions on the system.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;You likely want to test something more than just importing the library. Simply
write your test code as a python script (eg: &lt;strong&gt;debian/tests/smoke.py&lt;/strong&gt;) and
change &lt;strong&gt;debian/tests/control&lt;/strong&gt; as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;Test-Command: for py in $(py3versions -s); do echo &amp;#34;[*] testing on $py:&amp;#34;; $py -c &amp;#39;import module_name&amp;#39; ; done

Test-Command: for py in $(py3versions -s); do echo &amp;#34;[*] testing on $py:&amp;#34;; $py debian/tests/smoke.py&amp;#39; ; done&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;By default, autopkgtest installs all the packages generated by the source
package containing the tests. If you want to install only one specific package,
or if the tests to be executed need another set of packages, use the
&lt;strong&gt;Depends:&lt;/strong&gt; field:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;Test-Command: for py in $(py3versions -s); do echo &amp;#34;[*] testing on $py:&amp;#34;; $py -c &amp;#39;import module_name&amp;#39; ; done
Depends: python3-module_name

Test-Command: for py in $(py3versions -s); do echo &amp;#34;[*] testing on $py:&amp;#34;; $py debian/tests/smoke.py&amp;#39; ; done
Depends: python3-module_name, curl&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;A lot of Debian packages are using autopkgtest. Get inspired by taking a look
at some of them with the Debian Code Search query
&lt;a href=&#34;https://codesearch.debian.net/search?q=Depends+path%3Adebian%2Ftests%2Fcontrol&amp;amp;literal=1&#34;&gt;Depends
path:debian/tests/control&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_running_the_tests&#34;&gt;Running the tests&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There are many ways to execute the tests with &lt;strong&gt;autopkgtest&lt;/strong&gt; on your
development machine. The system supports various &lt;strong&gt;virtualization servers&lt;/strong&gt;,
depending on the level of isolation you want. LXC, Docker, and QEMU are some of
the supported virtualization servers. QEMU is the easiest way I found, and the
one providing the best isolation. See &lt;strong&gt;isolation-machine&lt;/strong&gt; in
&lt;a href=&#34;https://salsa.debian.org/ci-team/autopkgtest/raw/master/doc/README.package-tests.rst&#34;&gt;the
specifications&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;An autopkgtest virtual machine image for QEMU can be created as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;sudo autopkgtest-build-qemu unstable /var/tmp/autopkgtest-unstable.img&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Once the image is in place, you can execute your tests from within the package source directory with:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;autopkgtest -- qemu /var/tmp/autopkgtest-unstable.img&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There are multiple knobs to play with, for example in terms of the resources to
assign to the VM. For example, you can specify the number of virtual CPUs and
the amount of memory:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;autopkgtest -- qemu --cpus=8 --ram-size=4096 /var/tmp/autopkgtest-unstable.img&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Additionally, you may want to get dropped into a shell in case of tests failure
to investigate the situation. That can be done with &lt;strong&gt;--shell-fail&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;autopkgtest --shell-fail -- qemu --cpus=8 --ram-size=4096 /var/tmp/autopkgtest-unstable.img&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;See
&lt;a href=&#34;https://manpages.debian.org/testing/autopkgtest/autopkgtest-virt-qemu.1.en.html&#34;&gt;man
autopkgtest-virt-qemu(1)&lt;/a&gt; for the fine details, and happy testing!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Debugging production: the LIAR method</title>
      <link>https://www.linux.it/~ema/posts/production-debugging-liar-method/</link>
      <pubDate>Mon, 22 Mar 2021 09:38:00 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/production-debugging-liar-method/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The release of
&lt;a href=&#34;https://www.usenix.org/legacy/event/usenix04/tech/general/full_papers/cantrill/cantrill_html/&#34;&gt;DTrace&lt;/a&gt;
in 2005 marked a turning point in the world of UNIX systems when it comes to
production analysis, and more in general it greatly helped the process of
understanding what’s going on under the covers by means of dynamic tracing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Various systems inspired by DTrace have been developed throughout the years,
including &lt;a href=&#34;https://sourceware.org/systemtap/wiki&#34;&gt;SystemTap&lt;/a&gt; and
&lt;a href=&#34;https://github.com/iovisor/bpftrace&#34;&gt;bpftrace&lt;/a&gt;. Although these systems differ in
several important aspects, they all allow to ask questions about a running
system by following a similar workflow. The List, Instrument, Aggregate, and
Report (LIAR) acronym can be used to describe such workflow. The rest of this
article will illustrate the methodology using bpftrace, taking as an example
the problem of identifying which programs are sending data over TCP sockets,
and how much data they are sending.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_list&#34;&gt;List&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Without specific knowledge about Linux kernel internals, we can try and &lt;strong&gt;List&lt;/strong&gt;
all available probe points that have &amp;#39;tcp&amp;#39; and &amp;#39;send&amp;#39; in their name:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo bpftrace -l &amp;#39;*tcp*send*&amp;#39;
tracepoint:tcp:tcp_send_reset
kprobe:__traceiter_tcp_send_reset
kprobe:tcp_send_mss
kprobe:do_tcp_sendpages
kprobe:tcp_sendpage_locked
kprobe:tcp_sendpage
kprobe:tcp_sendmsg_locked
kprobe:tcp_sendmsg
[...]&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The function
&lt;a href=&#34;https://elixir.bootlin.com/linux/latest/source/net/ipv4/tcp.c#L1454&#34;&gt;tcp_sendmsg&lt;/a&gt;
seems interesting, and indeed it is the one responsible for gathering up data
to be written to a TCP socket. Its signature is:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The &amp;#39;size&amp;#39; argument is what we are interested in, and we are going to print it
together with the PID next.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_instrument&#34;&gt;Instrument&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;At the &lt;strong&gt;Instrument&lt;/strong&gt; step, we need to write a simple bpftrace program that prints
a line every time the tcp_sendmsg function is called. Given that &amp;#39;size&amp;#39; is the
third argument of tcp_sendmsg, and that bpftrace allows to print function
arguments using the arg0, …​, argN keywords, we are going to access it by
using &amp;#39;arg2&amp;#39;. We are going to print the builtin &amp;#39;pid&amp;#39; variable too.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo bpftrace -e &amp;#39;kprobe:tcp_sendmsg {
    printf(&amp;#34;pid=%d: size=%d\n&amp;#34;, pid, arg2)
}&amp;#39;
Attaching 1 probe...
pid=764374: size=36
pid=764374: size=36
pid=633506: size=43
pid=633506: size=566
pid=633506: size=600
pid=633506: size=58
pid=633506: size=819
^C&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The output looks reasonable, we can now work on aggregating the &amp;#39;size&amp;#39; data to
get further insights on the TCP sending behavior of this system.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_aggregate&#34;&gt;Aggregate&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The
&lt;a href=&#34;https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md#map-functions&#34;&gt;Map
Functions&lt;/a&gt; provided by bpftrace allow to Aggregate data in various useful ways.
For example, the
&lt;a href=&#34;https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md#7-stats-stats&#34;&gt;stats()&lt;/a&gt;:
function returns the count, average, and total for a given value.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Let’s use it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo bpftrace -e &amp;#39;kprobe:tcp_sendmsg {
    @bytes[pid] = stats(arg2);
    print(@bytes);
}&amp;#39;
Attaching 1 probe...
@bytes[770234]: count 1, average 77, total 77

@bytes[770234]: count 1, average 77, total 77
@bytes[770237]: count 1, average 77, total 77&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;We have defined a BPF map called &amp;#39;bytes&amp;#39;, used the PID as the key, and aggregated
the &amp;#39;size&amp;#39; argument using stats(). Every time tcp_sendmsg is called, we print
the values obtained so far.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_report&#34;&gt;Report&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;As the final step, we need to Report our findings. Instead of printing the
values every time tcp_sendmsg is called, it would be nicer to do that only once
at program termination. Just like DTrace, bpftrace defaults to automatically
printing aggregation results when the program exits. This is to say that, in
bpftrace terminology, all populated maps are printed automatically.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The full program is thus simply:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo bpftrace -e &amp;#39;kprobe:tcp_sendmsg {
    @bytes[pid] = stats(arg2);
}&amp;#39;
Attaching 1 probe...
^C

@bytes[769042]: count 1, average 75, total 75
@bytes[769047]: count 1, average 75, total 75
@bytes[769052]: count 1, average 75, total 75
@bytes[769057]: count 1, average 75, total 75
@bytes[633506]: count 13, average 378, total 4915&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;All values of the &amp;#39;bytes&amp;#39; map are printed by default when the user issues a
CTRL-C. If we want to instead make the program exit after 10 seconds, we can
use the &amp;#39;interval&amp;#39; probe as follows:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo bpftrace -e &amp;#39;kprobe:tcp_sendmsg {
    @bytes[pid] = stats(arg2);
}

interval:s:10 {
    exit();
}&amp;#39;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;This article introduced the LIAR method of production debugging, a workflow in
four steps that can be followed using DTrace-like systems to inspect various
aspects of running production systems. See
&lt;a href=&#34;https://www.usenix.org/legacy/event/usenix04/tech/general/full_papers/cantrill/cantrill_html/index.html&#34;&gt;the original DTrace paper&lt;/a&gt;, and
&lt;a href=&#34;https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md&#34;&gt;the
bpftrace reference guide&lt;/a&gt; for more!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>certbot renew: An authentication script must be provided</title>
      <link>https://www.linux.it/~ema/posts/letsencrypt-the-manual-plugin-is-not-working/</link>
      <pubDate>Mon, 01 Mar 2021 06:52:40 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/letsencrypt-the-manual-plugin-is-not-working/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;For a personal project of mine I’ve been using a wildcard TLS certificate
issued by Let’s Encrypt.
&lt;a href=&#34;https://certbot.eff.org/&#34;&gt;certbot&lt;/a&gt; made the process of creating the certificate
extremely easy, I just had to &lt;code&gt;apt install certbot&lt;/code&gt; and then run the following
command, duly copy-pasted from the Internet:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;certbot --manual certonly --agree-tos --email ema@example.org --preferred-challenges=dns -d &amp;#39;*.example.org&amp;#39;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The command gave this output:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;[...]
Please deploy a DNS TXT record under the name
_acme-challenge.example.org with the following value:

05REcrGYWuv_fTBQ3QQYTxmNm3f_LU2cN8JNf_f458z&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Being a happy &lt;a href=&#34;https://www.gandi.net/en&#34;&gt;Gandi&lt;/a&gt; customer and
&lt;a href=&#34;https://www.terraform.io/&#34;&gt;Terraform&lt;/a&gt; user, I deployed the change with this
configuration:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;resource &amp;#34;gandi_livedns_record&amp;#34; &amp;#34;acme&amp;#34; {
    zone = &amp;#34;example.org&amp;#34;
    name = &amp;#34;_acme-challenge&amp;#34;
    type = &amp;#34;TXT&amp;#34;
    ttl = 300
    values = [
        &amp;#34;05REcrGYWuv_fTBQ3QQYTxmNm3f_LU2cN8JNf_f458z&amp;#34;
    ]
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;This was enough to issue the certificate, and I completely forgot about it till
the nice Let’s Encrypt Expiry Bot emailed saying the certificate would expire
in 20 days.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Didn’t I configure auto-renewal of the cert? I thought I did but then again who
knows, weeks have gone by! It turns out I did, with this wonderful
&lt;code&gt;/etc/cron.weekly/certbot-renew&lt;/code&gt; script:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;#!/bin/sh

certbot renew&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Other than not being very advanced, the script was also failing claiming that
&lt;strong&gt;The manual plugin is not working&lt;/strong&gt; and that &lt;strong&gt;An authentication script must be
provided with --manual-auth-hook&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.org.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Non-interactive renewal: random delay of 293 seconds
Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError(&amp;#39;An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.&amp;#39;)
Attempting to renew cert (example.org) from /etc/letsencrypt/renewal/example.org.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration.
The error was: PluginError(&amp;#39;An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.&amp;#39;). Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/example.org/fullchain.pem (failure)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Unfortunately certbot did not guess that — even though the certificate was
created manually — I wanted renewals to happen automatically. Luckily certbot
also didn’t guess my Gandi API key.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;When the certificate was issued, this
&lt;code&gt;/etc/letsencrypt/renewal/example.org.conf&lt;/code&gt; was created for me:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# renew_before_expiry = 30 days
version = 0.31.0
archive_dir = /etc/letsencrypt/archive/example.org
cert = /etc/letsencrypt/live/example.org/cert.pem
privkey = /etc/letsencrypt/live/example.org/privkey.pem
chain = /etc/letsencrypt/live/example.org/chain.pem
fullchain = /etc/letsencrypt/live/example.org/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = redacted
pref_challs = dns-01,
authenticator = manual
manual_public_ip_logging_ok = True
server = https://acme-v02.api.letsencrypt.org/directory&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The important line is &lt;code&gt;authenticator = manual&lt;/code&gt; in the &lt;code&gt;renewalparams&lt;/code&gt; section.
We need to replace that with a plugin for the Gandi DNS service. Thankfully
&lt;a href=&#34;https://github.com/obynio&#34;&gt;Yohann Leon&lt;/a&gt; was nice enough to
&lt;a href=&#34;https://github.com/obynio/certbot-plugin-gandi&#34;&gt;write one&lt;/a&gt;, and
&lt;a href=&#34;https://wiki.ubuntu.com/Unit193&#34;&gt;Unit193&lt;/a&gt; packaged it for Debian.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;What I did to get certbot to automatically renew my wildcard certificate was:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;1) installing the plugin with &lt;code&gt;apt install python3-certbot-dns-gandi&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;2) replacing &lt;code&gt;authenticator = manual&lt;/code&gt; with &lt;code&gt;authenticator = certbot-plugin-gandi:dns&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;3) adding &lt;code&gt;certbot_plugin_gandi:dns_credentials = /etc/letsencrypt/gandi.ini&lt;/code&gt; to tell the plugin where to find my credentials&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;4) creating &lt;code&gt;/etc/letsencrypt/gandi.ini&lt;/code&gt; with &lt;code&gt;dns_gandi_api_key=REDACTED&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Almost. Now &lt;code&gt;certbot renew&lt;/code&gt; failed saying that it cannot find &lt;code&gt;certbot_plugin_gandi:dns_api_key&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;Attempting to renew cert (example.org) from /etc/letsencrypt/renewal/example.org.conf produced an unexpected error: Missing property in credentials configuration file /etc/letsencrypt/gandi.ini:
 * Property &amp;#34;certbot_plugin_gandi:dns_api_key&amp;#34; not found (should be API key for Gandi account).. Skipping.&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;So apparently something was wrong with step (4). Though
&lt;a href=&#34;https://github.com/obynio/certbot-plugin-gandi/blob/master/README.md&#34;&gt;the docs&lt;/a&gt;
use &lt;code&gt;dns_gandi_api_key&lt;/code&gt; as the property name, it seems it should be
&lt;code&gt;certbot_plugin_gandi:dns_api_key&lt;/code&gt; instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;And that’s it, here is the final configuration.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;&lt;code&gt;/etc/letsencrypt/renewal/example.org.conf&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;# renew_before_expiry = 30 days
version = 0.31.0
archive_dir = /etc/letsencrypt/archive/example.org
cert = /etc/letsencrypt/live/example.org/cert.pem
privkey = /etc/letsencrypt/live/example.org/privkey.pem
chain = /etc/letsencrypt/live/example.org/chain.pem
fullchain = /etc/letsencrypt/live/example.org/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = certbot-plugin-gandi:dns
certbot_plugin_gandi:dns_credentials = /etc/letsencrypt/gandi.ini
account = redacted
pref_challs = dns-01,
server = https://acme-v02.api.letsencrypt.org/directory&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;&lt;code&gt;/etc/letsencrypt/gandi.ini&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;certbot_plugin_gandi:dns_api_key=REDACTED&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Lessons learned from a 27 years old UNIX book</title>
      <link>https://www.linux.it/~ema/posts/porsche-book/</link>
      <pubDate>Tue, 16 Feb 2021 22:06:00 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/porsche-book/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;One of the Amazon reviewers of &amp;#34;Sun Performance and Tuning: Java and the
Internet&amp;#34; gave it 3/5 stars. While still a nice introduction, the book by
Adrian Cockcroft has become dated — claimed Roland in 2003, which believe it
or not was 18 years ago. The book Roland reviewed was published in 1998, and it
is a second edition. The first edition (1994) has a significantly different
title: &amp;#34;&lt;a href=&#34;https://archive.org/details/sunperformancetu00cock_0&#34;&gt;Sparc &amp;amp; Solaris&lt;/a&gt;&amp;#34;,
is the focus instead of &amp;#34;Java and the Internet&amp;#34;. Other than reflecting a major
shift in Sun’s focus happened between &amp;#39;94, and &amp;#39;98, the two editions also have
a different price tag. &amp;#34;Java and the Internet&amp;#34; costs 15.97 EUR, while one can
get &amp;#34;Sparc &amp;amp; Solaris&amp;#34; used in allegedly &lt;strong&gt;Very Good&lt;/strong&gt; conditions for 1.94.  If
I’m buying an outdated book I’m gonna get the most outdated version possible, I
figured, plus imagine the embarrassment if someone would find a book about Java
in my bookshelf. Shipping is 3 bucks, for a grand total of 4.94 EUR the book is
in my hands 15 days after placing the order.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;imageblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;img src=&#34;https://images-na.ssl-images-amazon.com/images/I/51PSF9CDRYL.jpg&#34; alt=&#34;51PSF9CDRYL&#34;/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;&amp;#34;The Porsche Book&amp;#34; is quick to explain the analogy between UNIX and the Porsche
911 featured on the cover: both were created in the &amp;#39;60s, in a form similar to
the current one. Both represent the latest and greatest of products still around
in 1994, and indeed 2021, despite their quirks.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;A valid question at this point clearly is: why do you care about a book
published 30 years ago when there’s so much recent and surely more useful
material? One reason is that I find the history of Sun Microsystems
particularly interesting.  I’ve read and very much enjoyed
&lt;a href=&#34;https://archive.org/details/highnoon00kare&#34;&gt;High Noon&lt;/a&gt; as well as
&lt;a href=&#34;https://archive.org/details/sunburstascentof00hall&#34;&gt;Sunburst&lt;/a&gt; — dealing with
recent history there’s the privilege of having plenty of primary sources
readily available, which is great. When it comes to the Porsche book, I find it
fascinating to read about the most common usage scenarios of Sun servers in the
&amp;#39;90s, and I can’t help but feel sorry for the admin who didn’t know that for
SunOS 4, only filenames up to 14 characters long are cached in the Directory
Name Lookup Cache (DNLC). In this article, however, I want to focus on the
information contained in the book which is still valid today.  In a world that
moves as quickly as the world of computing, you could argue that all books are
outdated to begin with. If some of the information in &amp;#34;Sun Performance and
Tuning&amp;#34; was valid in 1994 and is still valid in 2021, there’s a good chance
that it will still be valid 30 years from now.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;It seems to me that we can categorize tech knowledge as follows: theoretical
knowledge, generic practical information, and implementation details. Of the
three, theoretical knowledge is the most likely to stay relevant with time,
followed by generic practical information which might still apply some years
later, and finally implementation details which are very likely to become
irrelevant as time goes by. Those details are far from being useless however:
in fact they provide the distinction between novice and experienced
practitioner. To give an example: the chapter about Networks opens with a
description of the built-in &lt;strong&gt;le&lt;/strong&gt; network interface, pointing out that it shared
its DMA connection with the SCSI interface. Crucially, the network interface had
higher priority: heavy network activity was likely to reduce disk throughput. In
1994 you would have needed to see multiple workstations with bad disk
performance before concluding that network traffic had anything to do with it — or read the book.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;But what is the content that stood the test of time?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_configuration_factors_and_levels&#34;&gt;Configuration Factors and Levels&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;When performing a set of tests, there are multiple settings and knobs one can
work with, each having various options to choose from. Which filesystem are we
using?  What’s the version of the application we’re testing? Kernel buffer
size?&lt;/p&gt;
&lt;/div&gt;
&lt;table border=&#34;1&#34;&gt;
&lt;tbody&gt;&lt;tr&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;&lt;b&gt;Factor&lt;/b&gt;&lt;/td&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;&lt;b&gt;Level&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;Filesystem type&lt;/td&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;ext4, xfs, btrfs,...&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;OS version&lt;/td&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;5.10.16, 5.11, ...&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;vm.dirty_ratio kernel setting&lt;/td&gt;&lt;td style=&#34;padding-left: 5px&#34;&gt;20, 40, 60, ...&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;To measure every combination of 6 different factors with 4 levels each would
take 4^6 = 4096 measurements, which clearly is madness. By reducing the levels
we consider to 2, still evaluating all 6 different factors in all possible
combination, we get down to 2^6 = 64 measurements instead.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_throughput_response_time_utilization&#34;&gt;Throughput, Response Time, Utilization&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;&lt;strong&gt;Throughput&lt;/strong&gt; — the amount of work performed in a given amount of time — was a
thing in the &amp;#39;60s, it’s the same thing today, and it will still be &lt;strong&gt;work/time&lt;/strong&gt;
in 2050. Your web server might have a maximum throughput of 10000 requests per
second (rps), that’s something you can use to compare it with another one.
&lt;strong&gt;Response time&lt;/strong&gt; (latency) is defined as the amount of time the user has to
wait.  For example, how long did a given database transaction take.
&lt;strong&gt;Utilization&lt;/strong&gt; is how much of the computer’s resources were used to do the work.
The values reported by &lt;code&gt;sar&lt;/code&gt; and &lt;code&gt;iostat&lt;/code&gt;, two tools very much still in use
today, are an example of Utilization measures.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The author suggests taking multiple &lt;code&gt;sar&lt;/code&gt; Utilization measurements at various
load levels and combine them with &lt;code&gt;awk&lt;/code&gt; to get an overview of how the system
behaves. We do have &lt;a href=&#34;https://prometheus.io/&#34;&gt;Prometheus&lt;/a&gt;,
&lt;a href=&#34;https://grafana.com/&#34;&gt;Grafana&lt;/a&gt;, and friends nowadays, but the &lt;code&gt;sar | awk&lt;/code&gt; idea
is a useful reminder that quick, simple measurements can go a long way too!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_vmstat_sar_and_iostat_rules&#34;&gt;vmstat, sar and iostat Rules&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;&lt;code&gt;vmstat&lt;/code&gt; and &lt;code&gt;sar&lt;/code&gt; are described in detail, with a focus on runnable queue,
blocked queue, swap usage, and so forth. The Linux versions of &lt;code&gt;vmstat&lt;/code&gt; and
&lt;code&gt;sar&lt;/code&gt; from &lt;a href=&#34;https://gitlab.com/procps-ng/procps&#34;&gt;procps&lt;/a&gt; and
&lt;a href=&#34;http://sebastien.godard.pagesperso-orange.fr/&#34;&gt;sysstat&lt;/a&gt; are a bit different than
the Solaris ones, but the main ideas still apply.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The three commands are also used in the &lt;strong&gt;Rules and Tunables Quick Reference
Tables&lt;/strong&gt; section. For each subsystem (Disk, Network, Memory, CPU), the author
specified a list of Rules involving the commands and the action to take if the
rule applies. Rules consist in the name of the command with any options, then a
&amp;#34;.&amp;#34; followed by the name of the variable to take into account. For example, the
following indicates a disk bottleneck: &lt;code&gt;35%  &amp;lt; iostat-D30.util &amp;lt; 65%&lt;/code&gt;. The
action to take is to try balance the I/O load on other disks too, or get more
disks.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;A contemporary version of those rules for Linux would be great to have.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_interrupt_distribution_tuning&#34;&gt;Interrupt Distribution Tuning&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Interrupts in Solaris 2.2 were load-balanced among all available CPUs. The
drawback was that, in case of heavy interrupt load from a given device, cache
hit rate would suffer: the OS allowed to statically assign IRQs to CPUs as an
improvement instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Nowadays a very similar problem occurs with the &lt;code&gt;irqbalance&lt;/code&gt; daemon on Linux,
which on systems doing lots of network activity should not be used. SMP
affinity should instead be configured to ensure the interrupts of multiqueue
network cards are statically mapped among CPUs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;There’s more information in &amp;#34;Sun Performance and Tuning&amp;#34; that can still provide
valuable lessons today, as well as some true historical gems for those into
such things. Go &lt;a href=&#34;https://archive.org/details/sunperformancetu00cock_0&#34;&gt;check it
out&lt;/a&gt; on the Internet Archive if you’re interested!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>The alternative to wpa_supplicant</title>
      <link>https://www.linux.it/~ema/posts/the-alternative-to-wpa-supplicant/</link>
      <pubDate>Wed, 02 Dec 2020 16:52:40 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/the-alternative-to-wpa-supplicant/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;As of December 2020, there is an alternative to wpa_supplicant. It works. It’s
called &lt;a href=&#34;https://iwd.wiki.kernel.org/&#34;&gt;iwd&lt;/a&gt;, iNet Wireless Daemon, and you can use
it on Debian systems today.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now, if you use Linux and you’ve never heard of wpa_supplicant before, you are
a lucky person. Starting some weeks ago, all my videoconferences got
interrupted after a few minutes, &lt;code&gt;ping example.org&lt;/code&gt; said &amp;#34;not today&amp;#34;, and I was
sad. Looking at the the logs I could always see lines like this, a few seconds
before the connection dropped:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;Nov 30 18:56:36 orion wpa_supplicant[728]: wlan0: CTRL-EVENT-SIGNAL-CHANGE above=1 signal=-50 noise=9999 txrate=115600&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;I am however sitting very close to the access point, and my laptop is the only
device in the house having issues. So I blame wpa_supplicant. Suddenly iwd came
to mind, a project I had heard about at All Systems Go! 2019.
&lt;a href=&#34;https://media.ccc.de/v/ASG2019-147-iwd-state-of-the-union&#34;&gt;Here&lt;/a&gt; is the video of
the talk.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Here’s how it goes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;apt install iwd
systemctl enable iwd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;As you don’t want to see wpa_supplicant ever again, mask its unit:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;systemctl mask wpa_supplicant&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Then you need to tell Network Manager to use iwd as a supplicant, which boils down to adding the following to &lt;code&gt;/etc/NetworkManager/NetworkManager.conf&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;[device]
wifi.backend=iwd&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Reboot. Rejoice! wpa_supplicant is gone and your wifi connection is up
nonetheless. My connection stayed up for the whole duration of a meeting. I am
a happy man.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>A brief introduction to SystemTap</title>
      <link>https://www.linux.it/~ema/posts/systemtap-intro/</link>
      <pubDate>Mon, 14 Oct 2019 17:18:40 +0100</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/posts/systemtap-intro/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;SystemTap allows to instrument Linux systems at runtime. By using it, you can
gather insights about running programs, including the Linux kernel itself,
without invoking them in specific ways, modifying them, or indeed even having
access to their source code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;On Debian systems and derivatives, including Ubuntu, get started with SystemTap
by installing the &lt;strong&gt;systemtap&lt;/strong&gt; package as well as the Linux kernel headers:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;apt install systemtap linux-headers-$(uname -r)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;To verify that SystemTap is working correctly you can try this hello world
one-liner:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo stap -v -e &amp;#39;probe oneshot { println(&amp;#34;hello world&amp;#34;) }&amp;#39;
Pass 1: parsed user script and 476 library scripts using 101404virt/87992res/6960shr/81096data kb, in 150usr/30sys/218real ms.
Pass 2: analyzed script: 1 probe, 1 function, 0 embeds, 0 globals using 102988virt/89752res/7152shr/82680data kb, in 10usr/0sys/7real ms.
Pass 3: using cached /root/.systemtap/cache/28/stap_2871d732a80a0612c98a3e7e9d7dc4a2_973.c
Pass 4: using cached /root/.systemtap/cache/28/stap_2871d732a80a0612c98a3e7e9d7dc4a2_973.ko
Pass 5: starting run.
hello world
Pass 5: run completed in 10usr/20sys/494real ms.&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Give it another go without &lt;strong&gt;-v&lt;/strong&gt; for more terse and less exciting output.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_user_space_instrumentation&#34;&gt;User space instrumentation&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now that SystemTap is installed and working on your machine, let’s use it to
give a peek at what &lt;strong&gt;ls&lt;/strong&gt; is doing under the hood. In order for SystemTap
to inspect the behavior of a given program it needs to have access to its
debugging symbols, which in the case of &lt;strong&gt;ls&lt;/strong&gt; on Debian are provided by the
&lt;strong&gt;coreutils-dbgsym&lt;/strong&gt; package. Once the package is installed, you can ask
SystemTap to list all available &lt;em&gt;probe points&lt;/em&gt;, which to simplify a little
we can say are equivalent to the functions ls can call. Let’s list as an
example all functions that might have something to do with usernames:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo stap -L &amp;#39;process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;*user*&amp;#34;)&amp;#39;
process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;format_user@src/ls.c:3955&amp;#34;) $u:uid_t $width:int $stat_ok:_Bool
process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;format_user_or_group@src/ls.c:3927&amp;#34;) $name:char const* $id:long unsigned int $width:int
process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;format_user_or_group_width@src/ls.c:3973&amp;#34;) $id:long unsigned int
process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;format_user_width@src/ls.c:3991&amp;#34;) $u:uid_t
process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;getuser@lib/idcache.c:69&amp;#34;) $uid:uid_t $match:struct userid*&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The &lt;strong&gt;format_user&lt;/strong&gt; function seems interesting. We can see that it takes
three arguments: &lt;strong&gt;u&lt;/strong&gt;, &lt;strong&gt;width&lt;/strong&gt;, and &lt;strong&gt;stat_ok&lt;/strong&gt;. Let’s print all
invocations of it, as well as the value of &lt;strong&gt;u&lt;/strong&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo stap -e &amp;#39;probe process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;format_user&amp;#34;) { printf(&amp;#34;format_user(uid=%d)\n&amp;#34;, $u) }&amp;#39;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;If SystemTap complains about a &lt;em&gt;Build-id mismatch&lt;/em&gt;, try again passing
&lt;strong&gt;-DSTP_NO_BUILDID_CHECK&lt;/strong&gt; on the command line. In case you’re curious, read
&lt;strong&gt;man error::buildid&lt;/strong&gt; to find out more about this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now try running &lt;strong&gt;ls -l /etc/passwd&lt;/strong&gt;, and you should see the following
output from SystemTap:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;format_user(uid=0)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Try running &lt;strong&gt;ls /etc/passwd&lt;/strong&gt; without &lt;strong&gt;-l&lt;/strong&gt; and notice that SystemTap
produces no output, indicating that &lt;strong&gt;ls&lt;/strong&gt; does not call the
&lt;strong&gt;format_user&lt;/strong&gt; function in that case.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;SystemTap is a fully-fledged programming language with variables, loops,
conditionals and so forth. One-liners on the shell are fine for exploration and
simple examples like the ones above, but for longer scripts you might want to
save your work to a file. Let’s do that by creating &lt;strong&gt;ls_non_root.stp&lt;/strong&gt;, a
file that slightly changes our previous example by only printing
&lt;strong&gt;format_user&lt;/strong&gt; calls for files owned by non-root users:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;// SystemTap example: ls_non_root.stp
probe process(&amp;#34;/bin/ls&amp;#34;).function(&amp;#34;format_user&amp;#34;) {
    if ($u != 0) {
        printf(&amp;#34;format_user(uid=%d)\n&amp;#34;, $u)
    }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Run the script with &lt;strong&gt;stap -v ls_non_root.stp&lt;/strong&gt; and you should now see some
output only when running &lt;strong&gt;ls -l&lt;/strong&gt; on files owned by users other than root.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;sect1&#34;&gt;
&lt;h2 id=&#34;_kernel_instrumentation&#34;&gt;Kernel instrumentation&lt;/h2&gt;
&lt;div class=&#34;sectionbody&#34;&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;How about the Linux kernel? Just as we did before for &lt;strong&gt;coreutils&lt;/strong&gt;, we need
to install the debugging symbols for the kernel currently running. What is
different though, is that the kernel debug symbols are huge. For example, in
the case of the 4.19 kernel the debug symbols are about 5G. Make sure you’ve
got plenty of disk space available and the patience needed while waiting for
&lt;strong&gt;apt install linux-image-$(uname -r)-dbg&lt;/strong&gt; to do its thing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Now let’s look for available Linux kernel probe points matching the
&lt;code&gt;*icmp*reply&lt;/code&gt; pattern:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo stap -L &amp;#39;kernel.function(&amp;#34;*icmp*reply*&amp;#34;)&amp;#39;
kernel.function(&amp;#34;icmp_push_reply@./net/ipv4/icmp.c:367&amp;#34;) $icmp_param:struct icmp_bxm* $fl4:struct flowi4* $ipc:struct ipcm_cookie* $rt:struct rtable**
kernel.function(&amp;#34;icmp_reply@./net/ipv4/icmp.c:402&amp;#34;) $icmp_param:struct icmp_bxm* $skb:struct sk_buff* $ipc:struct ipcm_cookie $fl4:struct flowi4
kernel.function(&amp;#34;icmpv6_echo_reply@./net/ipv6/icmp.c:670&amp;#34;) $skb:struct sk_buff* $tmp_hdr:struct icmp6hdr $fl6:struct flowi6 $msg:struct icmpv6_msg $ipc6:struct ipcm6_cookie&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Interesting! Let’s run &lt;strong&gt;ping localhost&lt;/strong&gt; in one terminal and see if, as
you’d expect, the &lt;strong&gt;icmp_reply&lt;/strong&gt; function gets called:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;stap -ve &amp;#39;probe kernel.function(&amp;#34;icmp_reply&amp;#34;) { println(&amp;#34;reply&amp;#34;) }&amp;#39;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Silence. Ha! localhost resolves to &lt;strong&gt;::1&lt;/strong&gt; here, and &lt;strong&gt;icmp_reply&lt;/strong&gt; deals
with ICMPv4. The function we’re looking for is &lt;strong&gt;icmpv6_echo_reply&lt;/strong&gt;. We can
extend the script as follows, and see when the kernel is sending both v4 and v6
echo replies.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;// v4/v6 echo reply
probe kernel.function(&amp;#34;icmp_reply&amp;#34;) {
    println(&amp;#34;Sending v4 echo reply&amp;#34;)
}

probe kernel.function(&amp;#34;icmpv6_echo_reply&amp;#34;) {
    println(&amp;#34;Sending v6 echo reply&amp;#34;)
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Some of SystemTap requirements such as large debug packages and GCC are
undesirable on production systems. Luckily, SystemTap is designed so that you
can develop and compile your probes on a build host (eg. your laptop, or a
designated build server), and run them on production hosts with minimal
dependencies. For example, to compile the hello world probe on a development
machine:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo stap -e &amp;#39;probe oneshot { println(&amp;#34;hello word&amp;#34;) }&amp;#39; -m hello -p4
hello.ko&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;The command above generates a kernel module named &lt;strong&gt;hello.ko&lt;/strong&gt;, which can be
copied to a production host and run with &lt;strong&gt;staprun hello.ko&lt;/strong&gt;. Only
&lt;strong&gt;systemtap-runtime&lt;/strong&gt; needs to be installed on the target machine. If the
kernels running on the build and target hosts differ, you need to specify the
target Linux kernel version with &lt;strong&gt;-r&lt;/strong&gt;. For example, to target the
4.19.0-3-amd64 kernel:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;listingblock&#34;&gt;
&lt;div class=&#34;content&#34;&gt;
&lt;pre&gt;$ sudo stap -e &amp;#39;probe oneshot { println(&amp;#34;hello word&amp;#34;) }&amp;#39; -m hello -p4 -r 4.19.0-3-amd64&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;In this introduction we have always executed &lt;strong&gt;stap&lt;/strong&gt; as root. On production
systems you might want to add your user to the &lt;strong&gt;staprun&lt;/strong&gt; group instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;We’ve just scratched the surface of what SystemTap can do. Go ahead and
&lt;a href=&#34;https://sourceware.org/systemtap/documentation.html&#34;&gt;read the documentation&lt;/a&gt;,
play with it, and have fun.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://www.linux.it/~ema/contacts/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/contacts/</guid>
      <description>&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Contacts, LOL so 90s.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;E-mail: &lt;a href=&#34;mailto:ema@linux.it&#34;&gt;ema@linux.it&lt;/a&gt;. My PGP key is &lt;a href=&#34;https://keyserver.ubuntu.com/pks/lookup?search=0x50FDB7A3&amp;amp;fingerprint=on&amp;amp;op=index&#34;&gt;0x50FDB7A3&lt;/a&gt;, and this is the full fingerprint if you want to verify it: &lt;strong&gt;9545 9696 1928 1C17 FFAC  5891 D508 5A07 50FD B7A3&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;IRC: &lt;strong&gt;ema&lt;/strong&gt; on &lt;a href=&#34;https://www.oftc.net/&#34;&gt;OFTC&lt;/a&gt; and &lt;a href=&#34;https://libera.chat/&#34;&gt;Libera&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;Mastodon: &lt;a href=&#34;https://fosstodon.org/@ema&#34;&gt;@ema @ fosstodon.org&lt;/a&gt;
Twitter: &lt;a href=&#34;https://twitter.com/realEmaRocca&#34;&gt;@realEmaRocca&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;paragraph&#34;&gt;
&lt;p&gt;GitHub: &lt;a href=&#34;https://github.com/ema/&#34; class=&#34;bare&#34;&gt;https://github.com/ema/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://www.linux.it/~ema/publications/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/publications/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Emanuele Rocca. &lt;a href=&#34;https://hal.science/hal-05334704/&#34;&gt;Packages Not Using The Default Build Flags: A Taxonomy&lt;/a&gt;. DebConf25, IRISA, Jul 2025, Brest, France. pp.4.&lt;/li&gt;
&lt;li&gt;G. Pierre, T. Kielmann, E. Rocca, K. Razavi, B. IJff, H. Fernandez, R. Figueiredo, A. Uta, A. Vintila, A. Oprescu, T. Schuett, M. Berlin, M. Artac, A. Cernivec, &lt;a href=&#34;http://www.cs.vu.nl/~kaveh/pubs/pdf/hpdc13-conpaas-poster.pdf&#34;&gt;ConPaaS: An Integrated Runtime Environment for Elastic Cloud Applications&lt;/a&gt;, in: HPDC (Poster), 2013.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My &lt;a href=&#34;https://en.wikipedia.org/wiki/Erd%C5%91s_number&#34;&gt;Erdős number&lt;/a&gt; is 5 thanks
to the ConPaaS publication: Thilo Kielmann -&amp;gt; Willem Jan Fokkink -&amp;gt; Robbert
J.  Fokkink -&amp;gt; Jeffrey O. Shallit -&amp;gt; Paul Erdős.&lt;/p&gt;
&lt;p&gt;Further, I have performed as an extra in &lt;a href=&#34;https://www.imdb.com/title/tt1754841/&#34;&gt;a movie featuring  Maximilian
Dirr&lt;/a&gt;, meaning that my &lt;a href=&#34;https://en.wikipedia.org/wiki/Six_Degrees_of_Kevin_Bacon#Bacon_numbers&#34;&gt;Bacon
number&lt;/a&gt;
is 3: Maximilian Dirr -&amp;gt; Donald Sutherland -&amp;gt; Kevin Bacon.&lt;/p&gt;
&lt;p&gt;At parties, I can thus impress people by saying that my &lt;a href=&#34;https://en.wikipedia.org/wiki/Erd%C5%91s%E2%80%93Bacon_number&#34;&gt;Erdős–Bacon
number&lt;/a&gt; is 8.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>https://www.linux.it/~ema/talks/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <author>ema@linux.it (Emanuele Rocca)</author>
      <guid>https://www.linux.it/~ema/talks/</guid>
      <description>&lt;div class=&#34;ulist&#34;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Packages not using the default build ﬂags: a taxonomy&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/nocflags_slides.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://peertube.debian.social/w/vRqQD8rWKMZhTmfJQ8dLrH&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2025-07-15, Debconf 25, Brest, France&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Enabling Architectural Features in Debian: PAC and BTI on arm64&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/pacbti.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://fosdem.org/2025/schedule/event/fosdem-2025-5517-enabling-architectural-features-in-debian-pac-and-bti-on-arm64/&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2025-02-02, FOSDEM 25, Brussels, Belgium&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Debian Live&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/debian-live.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://peertube.debian.social/w/aXDhcG5ahPBHe9m47G8d5q&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2024-10-12, Mini-debconf, Cambridge, United Kingdom&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hardware Enablement in Debian: Lenovo Thinkpad X13s&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/debian-x13s.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://peertube.debian.social/w/ikGRH1fPwUiSYZNGx42z9E&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2023-11-25, Mini-debconf, Cambridge, United Kingdom&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Traffic Switchover 2018 vs 2020&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/Traffic-Switchover-2018-2020.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2020-09-21, Wikimedia SRE Session, The Internet&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go and Wikipedia’s CDN&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/Go-Wikipedia-CDN-2019.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2019-11-11, Golang Users Berlin, Zalando Lounge HQ Berlin, Germany&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wikipedia’s CDN, A Day In The Life&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/Traffic-SRE-Session-2019.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2019-10-31, Wikimedia SRE Session, The Internet&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SystemTap markers in ATS&lt;/strong&gt; (&lt;a href=&#34;https://www.youtube.com/watch?v=IB_wnJ2uLyk&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2019-10-10, Apache Traffic Server Summit, Sunnyvale, California, USA&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Serving Wikipedia with ATS&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/WMF_ATS-Summit-2019.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://www.youtube.com/watch?v=X3WfZJhfVSI&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2019-10-08, Apache Traffic Server Summit, Sunnyvale, California, USA&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wikipedia’s CDN&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/WMF_Traffic_DIBRIS.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2018-03-26, DIBRIS, Università degli studi di Genova, Italy&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Running Wikipedia.org&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/WMF_Traffic_Varnishcon_2016.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://peertube.debian.social/w/sXAwgrnH8DXecRnUdgmpjQ&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2016-06-17, VarnishCon 2016, Amsterdam, Netherlands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/terraform.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2015-10-05, ZenMate, Berlin, Germany&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Buildbot&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/buildbot.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2015-06-18, ZenMate, Berlin, Germany&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Varnish Cache&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/varnish.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2015-06-11, ZenMate, Berlin, Germany&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A brief history of Unix&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/unix-history.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://archive.org/details/a-brief-history-of-unix&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2015-03-19, ZenMate, Berlin, Germany&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ConPaaS Architecture&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/conpaas-architecture.pdf&#34;&gt;slides&lt;/a&gt;, &lt;a href=&#34;https://peertube.debian.social/w/hxskMZde2duVA8S7ft8c4A&#34;&gt;video&lt;/a&gt;)&lt;br/&gt;
2013-06-13, ConPaaS Workshop, Vrije Universiteit Amsterdam, Netherlands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer support in a federated PaaS environment&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/developers-and-paas.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2012-06-14, MSc thesis discussion, Vrije Universiteit Amsterdam, Netherlands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cross-site request forgery&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/csrf.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2011-12-13,  Vrije Universiteit Amsterdam, Netherlands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scalable Applications: design, refactor, host&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/scalable-webapp-hosting.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2011-10-14, Vrije Universiteit Amsterdam, Netherlands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bigtable: A Distributed Storage System for Structured Data&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/bigtable.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2011-03-16, Vrije Universiteit Amsterdam, Netherlands&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[Italian] &lt;strong&gt;Notifica e consultazione del dossier clinico&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/notifica-consultazione-referti.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2010-01-20, E.O. Ospedali Galliera, Genova, Italy&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[Italian] &lt;strong&gt;SystemTap: applicazioni alla sicurezza informatica&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/systemtap-ids.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2009-10-17, BSc thesis discussion, DISI, Università degli studi di Genova, Italy&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[Italian] &lt;strong&gt;Debian Security Team&lt;/strong&gt; (&lt;a href=&#34;http://www.linux.it/~ema/slides/debian_security_team.pdf&#34;&gt;slides&lt;/a&gt;)&lt;br/&gt;
2005-12-16, DISI, Università degli studi di Genova, Italy&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
