<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Ponyhof</title>
  <subtitle>Dysfunctional Programming</subtitle>
  <id>https://dvdhrm.github.io/</id>
  <updated>2023-04-11T08:48:19+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator>
  <link href="https://dvdhrm.github.io/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://dvdhrm.github.io/" rel="alternate" type="text/html" />


<entry>
  <title>Towards Stable Rust UEFI Firmware</title>
  <id>https://dvdhrm.github.io/2022/09/07/towards-stable-rust-uefi</id>
  <published>2022-09-07T00:00:00+00:00</published>
  <updated>2022-09-07T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2022/09/07/towards-stable-rust-uefi/" rel="alternate" type="text/html" title="Towards Stable Rust UEFI Firmware" />

  <summary type="html">&lt;p&gt;While &lt;em&gt;Tianocore EDKII&lt;/em&gt; still dominates the UEFI development world, there has
been continuous effort to enable Rust for firmware development. But so far the
tools involved have not been stabilised. We now started an effort to remedy
this and get stable Rust support for UEFI targets.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2022/09/07/towards-stable-rust-uefi/">&lt;p&gt;While &lt;em&gt;Tianocore EDKII&lt;/em&gt; still dominates the UEFI development world, there has
been continuous effort to enable Rust for firmware development. But so far the
tools involved have not been stabilised. We now started an effort to remedy
this and get stable Rust support for UEFI targets.&lt;/p&gt;

&lt;p&gt;The rust compiler has gained support for multiple UEFI targets in the past,
namely:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aarch64-unknown-uefi&lt;/code&gt; &lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html&quot;&gt;@&lt;strong&gt;Tier-3&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i686-unknown-uefi&lt;/code&gt; &lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html&quot;&gt;@&lt;strong&gt;Tier-3&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x86_64-unknown-uefi&lt;/code&gt; &lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html&quot;&gt;@&lt;strong&gt;Tier-3&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows building Rust UEFI Applications with a standard compiler by simply
passing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--target &amp;lt;arch&amp;gt;-unknown-uefi&lt;/code&gt; to &lt;em&gt;cargo&lt;/em&gt; or &lt;em&gt;rustc&lt;/em&gt;. Unfortunately,
&lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/target-tier-policy.html#tier-3-target-policy&quot;&gt;&lt;em&gt;Tier-3&lt;/em&gt;&lt;/a&gt;
support means no compiler builds are distributed via the Rust release
channels, nor does the Rust-CI guarantee the targets build successfully.
Moreover, this implies that a nightly/unstable compiler is required to build
for those targets, even though no nightly Rust Language features are required.&lt;/p&gt;

&lt;p&gt;Raising support of these targets to
&lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/target-tier-policy.html#tier-2-target-policy&quot;&gt;&lt;em&gt;Tier-2&lt;/em&gt;&lt;/a&gt;
will include automatic toolchain builds distributed via Rust release channels.
Hence, no nightly/unstable compiler is required, anymore. Automatic CI builds
will guarantee the targets build successfully and do not randomly break. This
will greatly improve the trust in the platform and significantly enhance the
developer experience.&lt;/p&gt;

&lt;p&gt;Rust support for UEFI has been documented in the &lt;em&gt;rustc-book&lt;/em&gt; section
&lt;a href=&quot;https://doc.rust-lang.org/nightly/rustc/platform-support/unknown-uefi.html&quot;&gt;UEFI Platform Support&lt;/a&gt;.
You can follow and support the &lt;em&gt;Major Change Proposal&lt;/em&gt; (MCP) to raise support
to &lt;em&gt;Tier-2&lt;/em&gt; on the
&lt;a href=&quot;https://github.com/rust-lang/compiler-team/issues/555&quot;&gt;Rust Compiler-Team Tracker&lt;/a&gt;.&lt;/p&gt;</content>
</entry>

<entry>
  <title>Meson with MSVC on GitHub Actions</title>
  <id>https://dvdhrm.github.io/2021/04/21/meson-msvc-github-actions</id>
  <published>2021-04-21T00:00:00+00:00</published>
  <updated>2021-04-21T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2021/04/21/meson-msvc-github-actions/" rel="alternate" type="text/html" title="Meson with MSVC on GitHub Actions" />

  <summary type="html">&lt;p&gt;The Meson Build System provides support for running on Microsoft Windows,
including support for Microsoft Visual Studio C++. GitHub Actions provides
public access to CI machines running Microsoft Windows. But trying to tie both
together is not as straightforward as it sounds.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2021/04/21/meson-msvc-github-actions/">&lt;p&gt;The Meson Build System provides support for running on Microsoft Windows,
including support for Microsoft Visual Studio C++. GitHub Actions provides
public access to CI machines running Microsoft Windows. But trying to tie both
together is not as straightforward as it sounds.&lt;/p&gt;

&lt;p&gt;Sometimes you stumble over a task you never thought you have to deal with. This
story is about one of those times. In particular, I was faced with running CI
tests for a simple C library on
&lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B&quot;&gt;Microsoft Visual Studio C++&lt;/a&gt;
(&lt;em&gt;MSVC&lt;/em&gt;). Gladly, GitHub already provides simple access to machines running
Microsoft Windows Server 2016 and 2019, so this sounded like a straightforward
task. Unfortunately, my infinite ignorance of anything Windows made this harder
than it should have been.&lt;/p&gt;

&lt;p&gt;The root of this problem is that the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Meson_%28software%29&quot;&gt;Meson Build System&lt;/a&gt;
needs to run in the &lt;em&gt;MSVC Developer Shell&lt;/em&gt;. This shell has all the necessary
environment variables prepared for a particular install of &lt;em&gt;MSVC&lt;/em&gt;. Since you
can have multiple versions installed in parallel, &lt;em&gt;Meson&lt;/em&gt; cannot know which
install to use if run outside of such a shell. Unfortunately, &lt;em&gt;GitHub Actions&lt;/em&gt;
has no simple way to enter this shell. Therefore, running &lt;em&gt;Meson&lt;/em&gt; on
&lt;em&gt;GitHub Actions&lt;/em&gt; will end up using &lt;em&gt;GCC&lt;/em&gt; rather than &lt;em&gt;MSVC&lt;/em&gt;, since this is what
it detects by default in the &lt;em&gt;GitHub Actions Environment&lt;/em&gt;. This is not what we
wanted, so adjustments are needed.&lt;/p&gt;

&lt;p&gt;Luckily, Microsoft provides a tool called
&lt;a href=&quot;https://github.com/microsoft/vswhere&quot;&gt;&lt;em&gt;vswhere&lt;/em&gt;&lt;/a&gt;
which finds &lt;em&gt;MSVC&lt;/em&gt; installs on a Windows system. We can use this to find the
required setup scripts and then import the environment variables into our
GitHub Actions setup. This tool is pre-deployed on &lt;em&gt;GitHub Actions&lt;/em&gt;, so we can
simply invoke it to find a suitable &lt;em&gt;MSVC&lt;/em&gt; install. From there on, we look for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DevShell.dll&lt;/code&gt;, which provides the required integration. We load it into
PowerShell and invoke the provided &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter-VsDevShell&lt;/code&gt; function. By comparing
our own environment variables before and after that call, we can extract the
changes and export them into the &lt;em&gt;GitHub Actions&lt;/em&gt; environment. Thus,
the following workflow-steps will have access to those variables as well.&lt;/p&gt;

&lt;p&gt;I plugged this into a re-usable &lt;em&gt;GitHub Action&lt;/em&gt; using the new &lt;em&gt;composite&lt;/em&gt; type.
To use it in a &lt;em&gt;GitHub Actions&lt;/em&gt; workflow, simply use:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Prepare MSVC&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bus1/cabuild/action/msdevshell@v1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;architecture&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;x64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This queries the &lt;em&gt;MSVC&lt;/em&gt; environment and exports it to your &lt;em&gt;GitHub Actions&lt;/em&gt;
job. Following steps will thus run as if in an &lt;em&gt;MSVC Developer Shell&lt;/em&gt;. A full
example is appended at the bottom, which shows how to get &lt;em&gt;Meson&lt;/em&gt; to compile
and test a project on &lt;em&gt;MSVC&lt;/em&gt; for both &lt;em&gt;Windows Server 2016&lt;/em&gt; and &lt;em&gt;2019&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you rather import the code into your own project, you can find it on
&lt;a href=&quot;https://github.com/bus1/cabuild/blob/8c91ebf06b7a5f8405cf93c89a6928e4c76967e0/action/msdevshell/action.yml&quot;&gt;GitHub&lt;/a&gt;.
Note that this uses PowerShell syntax, so it might look alien to linux
developers.&lt;/p&gt;

&lt;p&gt;While this is only roughly 50 lines of PowerShell scripting, it still feels a
bit too hacky. The &lt;em&gt;Meson&lt;/em&gt; developers are aware of this, but so far no patches
have found their way upstream. Lets hope that this workaround will one day be
obsolete and &lt;em&gt;Meson&lt;/em&gt; invokes &lt;em&gt;vswhere&lt;/em&gt; itself.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Following a full example workflow:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yml&quot; data-lang=&quot;yml&quot;&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Continuous Integration&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;ci-msvc&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;CI with MSVC&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${{ matrix.os }}&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;strategy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;matrix&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;windows-2016&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;windows-latest&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Fetch Sources&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Setup Python&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;actions/setup-python@v2&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;python-version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3.x'&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Install Python Dependencies&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;pip install meson ninja&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Prepare MSVC&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bus1/cabuild/action/msdevshell@v1&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;architecture&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;x64&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Prepare Build&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;meson setup build&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Run Build&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;meson compile -v -C build&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Run Test Suite&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;meson test -v -C build&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content>
</entry>

<entry>
  <title>Locating D-Bus Resource Leaks</title>
  <id>https://dvdhrm.github.io/2021/04/14/locating-dbus-resource-leaks</id>
  <published>2021-04-14T00:00:00+00:00</published>
  <updated>2021-04-14T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2021/04/14/locating-dbus-resource-leaks/" rel="alternate" type="text/html" title="Locating D-Bus Resource Leaks" />

  <summary type="html">&lt;p&gt;With &lt;em&gt;dbus-broker&lt;/em&gt; we have introduced the resource-accounting of &lt;em&gt;bus1&lt;/em&gt;
into the D-Bus world. We believe it greatly improves and strengthens
the resource distribution of the D-Bus messages bus, and we have already found
a handful of resource leaks that way. However, it can be a daunting task to
solve resource exhaustion bugs, so I decided to describe the steps we took to
resolve a recent resource-leak in the openQA package.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2021/04/14/locating-dbus-resource-leaks/">&lt;p&gt;With &lt;em&gt;dbus-broker&lt;/em&gt; we have introduced the resource-accounting of &lt;em&gt;bus1&lt;/em&gt;
into the D-Bus world. We believe it greatly improves and strengthens
the resource distribution of the D-Bus messages bus, and we have already found
a handful of resource leaks that way. However, it can be a daunting task to
solve resource exhaustion bugs, so I decided to describe the steps we took to
resolve a recent resource-leak in the openQA package.&lt;/p&gt;

&lt;p&gt;A few days ago, Adam Williamson approached me &lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; with a bug in the openQA
package, where he saw the log stream filled with messages like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dbus-broker[&amp;lt;pid&amp;gt;]: Peer :1.&amp;lt;id&amp;gt; is being disconnected as it does not have the resources to receive a reply or unicast signal it expects.
dbus-broker[&amp;lt;pid&amp;gt;]: UID &amp;lt;uid&amp;gt; exceeded its 'bytes' quota on UID &amp;lt;uid&amp;gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the typical sign of a resource exhaustion in &lt;em&gt;dbus-broker&lt;/em&gt;. When the
message broker generates or forwards messages to an individual client, it will
queue them as outgoing-messages and push them into the unix-socket of the
client. If this client does not dequeue messages, this queue might fill up. If
a limit is reached, something needs to be done. Since D-Bus is not a lossy
protocol, dropping messages is not an option. Instead, the message broker will
either refuse new incoming operations or disconnect a client. All resources are
accounted on UIDs, this means multiple clients of the same user will share the
same resource limits.&lt;/p&gt;

&lt;p&gt;Depending on what message is sent, it is accounted either on the receiver or
sender. Furthermore, some messages can be refused by the broker, others
cannot. The exact rules are described in the wiki &lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;In the case of openQA, the first step was to query the accounting information
of the running message broker:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.Debug.Stats.GetStats
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--system&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--session&lt;/code&gt; to query the session or user bus.)&lt;/p&gt;

&lt;p&gt;While preferably this query is performed when the resource exhaustion happens,
it will often yield useful information under normal operation as well.
Resources are often consumed slowly, so the accumulation will still show up.&lt;/p&gt;

&lt;p&gt;The output &lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; of this query shows a list of all D-Bus clients with their
accounting information. Furthermore, it lists all UIDs that have clients
connected to this message bus, again with all accounting information. The
challenge is to find suspicious entries in this huge data dump. The most
promising solution so far was to search for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;OutgoingBytes&quot;&lt;/code&gt; and check for
big numbers. This shows the number of bytes queued in the message broker for
a particular client. It is usually 0, since the kernel queues are big enough
to hold most normal messages. Even if it is not 0, it is usually just a couple
of KiB.&lt;/p&gt;

&lt;p&gt;In this case, we checked for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;OutgoingBytes&quot;&lt;/code&gt;, and found:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dict entry(
    string &quot;OutgoingBytes&quot;
    uint32 62173024
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;62 MiB of messages are waiting to be delivered to that client. Expanding the
logs to show the surrounding block, we see:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct {
    string &quot;:1.211366&quot;
    array [
        dict entry(
            string &quot;UnixUserID&quot;
            variant                            uint32 991
        )
        dict entry(
            string &quot;ProcessID&quot;
            variant                            uint32 674968
        )
        [...]
    ]

    array [
        [...]
        dict entry(
            string &quot;Matches&quot;
            uint32 1
        )
        [...]
        dict entry(
            string &quot;OutgoingBytes&quot;
            uint32 62173024
        )
        [...]
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This tells us the PID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;674968&lt;/code&gt; of user &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;991&lt;/code&gt; has roughly 62 MiB of data queued,
and it is likely not dequeuing the data. Furthermore, we see it has 1 message
filter (D-Bus match rule) installed. D-Bus message filters will cause matching
D-Bus signals to be delivered to a client. So a likely problem is that this
client keeps receiving signals, but does not dispatch its client socket.&lt;/p&gt;

&lt;p&gt;We digged further, and the data dump includes more such clients. Matching back
the PIDs to processes via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps auxf&lt;/code&gt;, we found that each and every of those
suspicious entries was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/bin/isotovideo: backend&lt;/code&gt;. The code of this process
is part of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;os-autoinst&lt;/code&gt; repository, in this case &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu.pm&lt;/code&gt;. A quick look
showed only a single use of D-Bus &lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. At a first glance, this looks alright.
It creates a system-bus connection via the &lt;em&gt;Net::DBus&lt;/em&gt; perl module, dispatches
a method-call, and returns the result. However, we know this process has a
match-rule installed (assuming the dbus-broker logs are correct), so we checked
further and found that the &lt;em&gt;Net::DBus&lt;/em&gt; module always installs a match-rule on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NameOwnerChanged&lt;/code&gt;. Furthermore, it caches the system-bus connection in a
global variable, sharing it across users in the same code-base.&lt;/p&gt;

&lt;p&gt;Long story short, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;os-autoinst&lt;/code&gt; qemu module created a D-Bus connection
which was idle in the background and never dispatched by any code. However, the
connection has a match-rule installed, and the message broker kept sending
matching signals to that connection. This data accumulated and eventually
exceeded the resource quota of that client. A workaround was quickly provided,
and it will hopefully resolve this problem &lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Hopefully, this short recap will be helpful to debug other similar situations.
You are always welcome to message us on &lt;em&gt;bus1-devel@googlegroups&lt;/em&gt; or on the
dbus-broker GitHub issue tracker if you need help.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://progress.opensuse.org/issues/90872&quot;&gt;OpenSUSE Bug #90872&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/bus1/dbus-broker/wiki/Accounting&quot;&gt;D-Bus Broker Accounting&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://progress.opensuse.org/attachments/11201/dbusdebug.txt&quot;&gt;OpenSUSE Bug Attachment&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/os-autoinst/os-autoinst/blob/965960f534c93ef12f0978014d589b8b2be6e6d2/backend/qemu.pm#L138&quot;&gt;os-autoinst qemu.pm&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/os-autoinst/os-autoinst/pull/1641&quot;&gt;os-autoinst PR #1641&lt;/a&gt; &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content>
</entry>

<entry>
  <title>Inside Specs: ELF Segments and Sections</title>
  <id>https://dvdhrm.github.io/2020/04/26/inside-specs-elf-segments-and-sections</id>
  <published>2020-04-26T00:00:00+00:00</published>
  <updated>2020-04-26T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2020/04/26/inside-specs-elf-segments-and-sections/" rel="alternate" type="text/html" title="Inside Specs: ELF Segments and Sections" />

  <summary type="html">&lt;p&gt;The &lt;em&gt;ELF data format&lt;/em&gt; divides object files into &lt;strong&gt;segments&lt;/strong&gt; and &lt;strong&gt;sections&lt;/strong&gt;,
which has for long caused confusion. Both terms &lt;strong&gt;segment&lt;/strong&gt; and &lt;strong&gt;section&lt;/strong&gt; can
be used interchangeably in almost all cases in the English language
(&lt;a href=&quot;https://www.lexico.com/en/definition/section&quot;&gt;[1]&lt;/a&gt;,
&lt;a href=&quot;https://www.lexico.com/en/definition/segment&quot;&gt;[2]&lt;/a&gt;). What is often overlooked is
that the ELF specification explicitely meant both to mean almost the same. They
merely provide two views of the same data, but use different terms to allow
referring to them more easily.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2020/04/26/inside-specs-elf-segments-and-sections/">&lt;p&gt;The &lt;em&gt;ELF data format&lt;/em&gt; divides object files into &lt;strong&gt;segments&lt;/strong&gt; and &lt;strong&gt;sections&lt;/strong&gt;,
which has for long caused confusion. Both terms &lt;strong&gt;segment&lt;/strong&gt; and &lt;strong&gt;section&lt;/strong&gt; can
be used interchangeably in almost all cases in the English language
(&lt;a href=&quot;https://www.lexico.com/en/definition/section&quot;&gt;[1]&lt;/a&gt;,
&lt;a href=&quot;https://www.lexico.com/en/definition/segment&quot;&gt;[2]&lt;/a&gt;). What is often overlooked is
that the ELF specification explicitely meant both to mean almost the same. They
merely provide two views of the same data, but use different terms to allow
referring to them more easily.&lt;/p&gt;

&lt;p&gt;When we look at the defining specification
(&lt;a href=&quot;https://refspecs.linuxfoundation.org/elf/gabi4+/contents.html&quot;&gt;&lt;strong&gt;gABI&lt;/strong&gt;&lt;/a&gt;:
&lt;em&gt;System V Application Binary Interface&lt;/em&gt;) we find this quote in the introduction:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Object files participate in program linking (building a program) and program
execution (running a program). For convenience and efficiency, the object file
format provides parallel views of a file’s contents, reflecting the differing
needs of those activities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is, in my opinion, a crucial detail often overlooked. The ELF data format
explicitly provides two views of the &lt;em&gt;same data&lt;/em&gt;. The difference between
segments and sections is thus not what data they contain, but how they index
the &lt;em&gt;same data&lt;/em&gt;. The specification goes a step further:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A program header table tells the system how to create a process image. Files
used to build a process image (execute a program) must have a program header
table; relocatable files do not need one.&lt;/p&gt;

  &lt;p&gt;A section header table contains information describing the file’s sections.
Every section has an entry in the table; each entry gives information such as
the section name, the section size, and so on. Files used during linking must
have a section header table; other object files may or may not have one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Keep in mind that the &lt;em&gt;program header table&lt;/em&gt; is effectively a &lt;em&gt;segment header
table&lt;/em&gt;. Therefore, the specification explicitly says that these two data views
do not have to be present in a specific file. Depending on the use case, the
format allows for &lt;em&gt;only segments&lt;/em&gt; or &lt;em&gt;only sections&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To summarize, an ELF object file contains data and machine code of a program,
which itself is divided into many parts. The ELF format then provides two
different views of this same content: &lt;em&gt;segments&lt;/em&gt; and &lt;em&gt;sections&lt;/em&gt;. However, these
are views of the data present in the file, they do not define the content, but
merely index it.&lt;/p&gt;

&lt;p&gt;As a closing note, we must acknowledge how all this evolved over time, though.
While the ELF specification provides this neat dual-view, a lot of this freedom
is not actually used in most ELF files. Instead, most files are effectively
split into many small sections, and the segments merely provide a grouping of
sequential sections in the file. Sections have become the tool that drives the
data in ELF files, and segments have become a view of that data. But this was
a purely artifical interpretation and is not rooted in the ELF data format.&lt;/p&gt;</content>
</entry>

<entry>
  <title>Fair Resource Distribution Algorithm v1</title>
  <id>https://dvdhrm.github.io/fairdist-v1</id>
  <published>2019-03-13T00:00:00+00:00</published>
  <updated>2019-03-13T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/fairdist-v1/" rel="alternate" type="text/html" title="Fair Resource Distribution Algorithm v1" />

  <summary type="html">&lt;p&gt;Imagine a finite resource that you want to distribute amongst peers in a fair
manner. If you know the number of peers to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, the problem becomes
trivial and you can assign every peer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1/n&lt;/code&gt;-th of the total. This way
every peer gets the same amount, while no part of the resource stays unused.
But what if the number of peers is only known retrospectively? That is, how
many resources do you grant a peer if you do not know whether there are more
peers or not? How do you define “fairness”? And how do you make sure as little
of the resource as possible stays unused?&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/fairdist-v1/">&lt;p&gt;Imagine a finite resource that you want to distribute amongst peers in a fair
manner. If you know the number of peers to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;, the problem becomes
trivial and you can assign every peer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1/n&lt;/code&gt;-th of the total. This way
every peer gets the same amount, while no part of the resource stays unused.
But what if the number of peers is only known retrospectively? That is, how
many resources do you grant a peer if you do not know whether there are more
peers or not? How do you define “fairness”? And how do you make sure as little
of the resource as possible stays unused?&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fairdist&lt;/code&gt; algorithm provides one possible solution to this problem. It
defines how many resources a new peer is assigned, considering the following
propertis:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The total amount of resources already distributed to other peers. This is
also referred to by the term &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consumption&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The number of peers that already got resources assigned.&lt;/li&gt;
  &lt;li&gt;The amount of resources remaining. That is, the resources that are
remaining to be distributed. This is also referred to by the term
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reserve&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following is a mathematical proof of the properties of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fairdist&lt;/code&gt;
algorithm. For the reference implementation of the algorithm and information on
the different applications of it, see the
&lt;a href=&quot;https://crates.io/crates/r-fairdist&quot;&gt;r-fairdist&lt;/a&gt; project.&lt;/p&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;We define a set of symbols up front, to keep the proofs shorter. Whenever these
symbols are mentioned, the following definition applies:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Let \(c \in \mathbb{R}_{\geq 0}\) be a total amount of consumed resources.&lt;/li&gt;
  &lt;li&gt;Let \(r \in \mathbb{R}_{\geq 0}\) be a total amount of reserved resources.&lt;/li&gt;
  &lt;li&gt;Let \(n \in \mathbb{N}_0\) be a number of peers that consumed resources.&lt;/li&gt;
  &lt;li&gt;Let \(A: \mathbb{N}_0 \to \mathbb{R}_{&amp;gt;0}\) be a function that computes
the proportion of \(r\) a peer can consume, based on the number of peers
\(n\) that currently have resources consumed.&lt;/li&gt;
  &lt;li&gt;Let \(G: \mathbb{N}_0 \to \mathbb{R}_{&amp;gt;0}\) be a function that computes
the proportion of \(c + r\) a peer is guaranteed, based on the number of
peers \(n\) that currently have resources consumed.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;

  &lt;p&gt;The algorithm considers a total amount of resources, but splits it into two
separate parts, the remaining reserve \(r\) and the consumed part \(c\).
Their sum represents the total amount that was initially available. It then
declares a function \(A\), which is the resource allocator. It will later on
be used to calculate how many resources of the reserve a peer can allocate:
\(\frac{r}{A(n)}\). That is, \(A\) defines the proportion of the reserve a
new peer gets access to. The smaller it is, the more a peer gets.&lt;/p&gt;

  &lt;p&gt;Similarly,
the guarantee \(G\) is used to declare a lower bound of the total resources
the allocator \(A\) grants a new peer. That is, while \(A\) is a function
applied to allocations, \(G\) is a property the allocator will guarantee you.
Unlike an allocation, \(G\) will later on be calculated based on the total
amount of resources: \(\frac{c + r}{G(n)}\). Again, the function defines the
proportion that is guaranteed. So the smaller \(G\) is, the stronger the
guarantee becomes.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2 id=&quot;definition&quot;&gt;Definition&lt;/h2&gt;

&lt;p&gt;The allocator \(A\) is said to guarantee the limit \(G\), if there exists a
function \(R: \mathbb{N}_+ \to \mathbb{R}_{&amp;gt;0}\) so that for all \(c\),
\(r\), and \(n\):&lt;/p&gt;

\[r \geq \frac{c}{R(n)}\]

&lt;p&gt;&lt;em&gt;implies both:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
\[\frac{r}{A(n)} \geq \frac{c+r}{G(n)}\]
  &lt;/li&gt;
  &lt;li&gt;
\[r - \frac{r}{A(n)} \geq \frac{c + \frac{r}{A(n)}}{R(n+1)}\]
  &lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;

  &lt;p&gt;The idea here is to define a function \(A\) which calculates how many
resources a new peer can allocate. That is, considering a new peer requests
resources, it will get \(\frac{1}{A(n)}\) of the reserve. The first property
of this implication guarantees that this allocation is bigger than, or equal
to, the guaranteed total for each peer. The guaranteed total is calculated
through \(G\) based on the total amount of resources (which is the
consumption plus the reserve).&lt;/p&gt;

  &lt;p&gt;If you now pick an allocator \(A\) and a guarantee \(G\) that fulfil this
definition, the idea is that this ensures you that the allocator \(A\) can be
used to serve resource requests from new peers, and it ensures that
regardless of how many peers will request resources, each one will be
guaranteed an amount equal to, or bigger than, the guarantee \(G\).&lt;/p&gt;

  &lt;p&gt;This definition requires the existance of a reserve watermark \(R\). It uses
this watermark as a selector for an inductive step. That is, if the
requirements of this reserve selector are true, the second implication
guarantees that they are true for an infinite number of following
allocations. That is, the right hand side of the second implication matches
exactly the requirement of the implication, once a single allocation was
performed (i.e., a resource chunk was subtracted from the reserve and added
to the total consumption, while the number of peers increased by one).&lt;/p&gt;

  &lt;p&gt;Note that if \(c\) is \(0\), then the requirement of the implication is true
for all \(r\) and \(R\). This guarantees that there is always a situation
where allocator \(A\) can actually be applied.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2 id=&quot;lemma-1&quot;&gt;Lemma 1&lt;/h2&gt;

&lt;p&gt;To prove an allocator \(A\) guarantees \(G\), it is sufficient to show that
\(R\) fulfils:&lt;/p&gt;

\[R(n) \leq \frac{G(n)}{A(n)} - 1\]

&lt;p&gt;and&lt;/p&gt;

\[A(n) \geq \frac{1+R(n+1)}{R(n+1)-R(n)}\]

&lt;blockquote&gt;

  &lt;p&gt;This lemma is used to make it easier to prove a specific allocator guarantees
a specific limit. Without it, each proof of the different allocators would
have to replicate it.&lt;/p&gt;

  &lt;p&gt;However, this lemma also gives a better feeling of what the different
functions actually mean. For instance, it clearly shows \(A\) must always be
smaller than \(G\), and that by a considerable amount. If \(A = G\), then no
\(R\) would ever fulfil this requirement (remember: \(R(n) &amp;gt; 0\)). At the
same time, you can see the closer \(A\) and \(G\) are together, the smaller
\(R\) gets, and as such the requirements on the reserve get harder to fulfil.&lt;/p&gt;

  &lt;p&gt;The second requirement gives you a recursive equation to find an \(R\) for
any allocator you pick. Hence, in combination both these requirements show
you an iterative process to find \(A\) and \(R\), for any guarantee \(G\) you
pick. However, the closer \(A\) and \(G\) get, the harder it becomes to solve
the recursive equation.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h3 id=&quot;proof&quot;&gt;Proof&lt;/h3&gt;

&lt;p&gt;To show this lemma is true, we must show both implications of the definition
are true. As first step, we show the first implication is true, which is:&lt;/p&gt;

\[r \geq \frac{c}{R(n)} \implies \frac{r}{A(n)} \geq \frac{c+r}{G(n)}\]

&lt;p&gt;We show this b starting with the left-hand side and showing it implies the
right hand side, using the requisite of this lemma.&lt;/p&gt;

\[\begin{align}
r &amp;amp;\geq_{req} \frac{c}{R(n)}\\[8pt]
R(n) &amp;amp;\geq \frac{c}{r}\\[8pt]
\frac{G(n)}{A(n)} - 1 \geq_{req} R(n) &amp;amp;\geq \frac{c}{r}\\[8pt]
\frac{G(n)}{A(n)} - 1 &amp;amp;\geq \frac{c}{r}\\[8pt]
\frac{r G(n)}{A(n)} - r &amp;amp;\geq c\\[8pt]
\frac{r G(n)}{A(n)} &amp;amp;\geq c+r\\[8pt]
\frac{r}{A(n)} &amp;amp;\geq \frac{c+r}{G(n)}\\[8pt]
\end{align}\]

&lt;p&gt;As second step, we need to show the second implication of the definition is
true, which is:&lt;/p&gt;

\[r \geq \frac{c}{R(n)} \implies r - \frac{r}{A(n)} \geq \frac{c + \frac{r}{A(n)}}{R(n+1)}\]

&lt;p&gt;To prove this, we start with the second requisite of this lemma and then show
it implies the right-hand side of the implication, using the requisite of the
implication.&lt;/p&gt;

\[\begin{align}
A(n) &amp;amp;\geq_{req} \frac{1+R(n+1)}{R(n+1)-R(n)}\\[16pt]
A(n)R(n+1) - A(n)R(n) &amp;amp;\geq 1+R(n+1)\\[16pt]
-A(n)R(n) &amp;amp;\geq 1+R(n+1) - A(n)R(n+1)\\[16pt]
A(n)R(n) &amp;amp;\leq A(n)R(n+1)-R(n+1)-1\\[16pt]
R(n) &amp;amp;\leq R(n+1) - \frac{R(n+1)}{A(n)} - \frac{1}{A(n)}\\[16pt]
\end{align}\]

&lt;blockquote&gt;
  &lt;p&gt;Hint: The following introduction of \(c\) is correct, since \(R(n)\) is per
definition greater than \(0\), so neither side can be 0.&lt;/p&gt;
&lt;/blockquote&gt;

\[\begin{align}
\frac{c}{R(n)} &amp;amp;\geq \frac{c}{R(n+1) - \frac{R(n+1)}{A(n)} - \frac{1}{A(n)}}\\[16pt]
r \geq_{req} \frac{c}{R(n)} &amp;amp;\geq \frac{c}{R(n+1) - \frac{R(n+1)}{A(n)} - \frac{1}{A(n)}}\\[16pt]
r &amp;amp;\geq \frac{c}{R(n+1) - \frac{R(n+1)}{A(n)} - \frac{1}{A(n)}}\\[16pt]
rR(n+1) - \frac{rR(n+1)}{A(n)} - \frac{r}{A(n)} &amp;amp;\geq c\\[16pt]
rR(n+1) - \frac{rR(n+1)}{A(n)} &amp;amp;\geq c + \frac{r}{A(n)}\\[16pt]
r - \frac{r}{A(n)} &amp;amp;\geq \frac{c + \frac{r}{A(n)}}{R(n+1)}\\[16pt]
\end{align}\]

&lt;h2 id=&quot;theorem&quot;&gt;Theorem&lt;/h2&gt;

&lt;p&gt;The following allocators each guarantee the specified limit:&lt;/p&gt;

\[\begin{align}
A_1(n) &amp;amp;:= 2\\
G_1(n) &amp;amp;:= 2^{n+1} = \mathcal{O}(2^n)\\
\\
A_2(n) &amp;amp;:= n+2\\
G_2(n) &amp;amp;:= n^2+3n+2 = \mathcal{O}(n^2)\\
\\
A_3(n) &amp;amp;:= (n+2) \log_2(n+2) + (n+2)\\
G_3(n) &amp;amp;:= \mathcal{O}(n \log_2(n)^2)\\
\end{align}\]

&lt;blockquote&gt;

  &lt;p&gt;This theorem defines three different allocators for different guarantees. The
last one provides the strongest guarantee. Both the allocation and the
guarantee are quasilinear. It is thus a good fit for fair allocation schemes,
while still being reasonably fast to compute.&lt;/p&gt;

  &lt;p&gt;The other two provide quadratic and exponential guarantees and are mostly
listed for documentational purposes. With the quasilinear guarantees at hand,
there is little reason to use the other two.&lt;/p&gt;

  &lt;p&gt;As you might notice, this theorem does not provide a solution where \(A\) and
\(G\) become infinitesimally close. It remains open whether what this
solution would look like. However, the listed quasilinear solution is good
enough, that it is unlikely that better options exist, which can still be
calculated in reasonable amounts of time.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h3 id=&quot;proof-1&quot;&gt;Proof&lt;/h3&gt;

&lt;p&gt;We provide a function \(R\) for each pair. We then substitute them in &lt;em&gt;Lemma 1&lt;/em&gt;
and show through equivalence transformations that the assertions are true.&lt;/p&gt;

&lt;h4 id=&quot;proof-1-exponential-guarantee&quot;&gt;Proof 1: Exponential Guarantee&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Allocator:&lt;/em&gt; \(A(n) := 2\)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Guarantee:&lt;/em&gt; \(G(n) := 2^{n+1}\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let \(R(n) := 2^n - 1\).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Part 1:&lt;/em&gt;&lt;/p&gt;

\[\begin{align}
R(n) &amp;amp;\leq_{lemma} \frac{G(n)}{A(n)} - 1\\[8pt]
2^n - 1 &amp;amp;\leq \frac{2^{n+1}}{2} - 1\\[8pt]
2^n &amp;amp;= \frac{2^{n+1}}{2}\\[8pt]
2^n &amp;amp;= 2^n\\[8pt]
\end{align}\]

&lt;p&gt;&lt;em&gt;Part 2:&lt;/em&gt;&lt;/p&gt;

\[\begin{align}
A(n) &amp;amp;\geq \frac{1+R(n+1)}{R(n+1)-R(n)}\\[8pt]
2 &amp;amp;\geq \frac{1+(2^{n+1} - 1)}{(2^{n+1} - 1)-(2^n - 1)}\\[8pt]
2 &amp;amp;\geq \frac{2^{n+1}}{2^{n+1} - 2^n}\\[8pt]
2 &amp;amp;\geq \frac{2^{n+1}}{2^{n+1}(1 - \frac{1}{2})}\\[8pt]
2 &amp;amp;\geq \frac{1}{1 - \frac{1}{2}}\\[8pt]
2 &amp;amp;\geq 2\\[8pt]
\end{align}\]

&lt;h4 id=&quot;proof-2-polynomial-guarantee&quot;&gt;Proof 2: Polynomial Guarantee&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Allocator:&lt;/em&gt; \(A(n) := n+2\)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Guarantee:&lt;/em&gt; \(G(n) := n^2 + 3n + 2\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let \(R(n) := n\).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Part 1:&lt;/em&gt;&lt;/p&gt;

\[\begin{align}
R(n) &amp;amp;\leq_{lemma} \frac{G(n)}{A(n)} - 1\\[8pt]
n &amp;amp;\leq \frac{n^2 + 3n + 2}{n+2} - 1\\[8pt]
n+1 &amp;amp;\leq \frac{n^2 + 3n + 2}{n+2}\\[8pt]
(n+1)(n+2) &amp;amp;\leq n^2 + 3n + 2\\[8pt]
n^2 + 3n + 2 &amp;amp;\leq n^2 + 3n + 2\\[8pt]
\end{align}\]

&lt;p&gt;&lt;em&gt;Part 2:&lt;/em&gt;&lt;/p&gt;

\[\begin{align}
A(n) &amp;amp;\geq \frac{1+R(n+1)}{R(n+1)-R(n)}\\[8pt]
n+2 &amp;amp;\geq \frac{1+(n+1)}{(n+1)-(n)}\\[8pt]
n+2 &amp;amp;\geq \frac{n+2}{n-n+1}\\[8pt]
n+2 &amp;amp;\geq n+2\\[8pt]
\end{align}\]

&lt;h4 id=&quot;proof-3-quasilinear-guarantee&quot;&gt;Proof 3: Quasilinear Guarantee&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Allocator:&lt;/em&gt; \(A(n) := (n+2) \log_2(n+2) + (n+2)\)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Guarantee:&lt;/em&gt; \(G(n) := \mathcal{O}(n \log_2(n)^2)\)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let \(R(n) := \log_2(n+1)\).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Part 1:&lt;/em&gt;&lt;/p&gt;

\[\begin{align}
R(n) &amp;amp;\leq_{lemma} \frac{G(n)}{A(n)} - 1\\[8pt]
\log_2(n+1) &amp;amp;\leq \frac{\mathcal{O}(n \log_2 (n)^2)}{(n+2) \log_2(n+2) + (n+2)} - 1\\[8pt]
\log_2(n+1) + 1 &amp;amp;\leq \frac{\mathcal{O}(n \log_2 (n)^2)}{(n+2) \log_2(n+2) + (n+2)}\\[8pt]
\log_2(n+1) + 1 &amp;amp;\leq \frac{\mathcal{O}(n \log_2 (n)^2)}{(n+2) (\log_2(n+2) + 1)}\\[8pt]
\log_2(n+1) + 1 \leq \log_2(n+2) + 1 &amp;amp;\leq \frac{\mathcal{O}(n \log_2 (n)^2)}{(n+2) (\log_2(n+2) + 1)}\\[8pt]
(\log_2(n+1) + 1)^2 &amp;amp;\leq \frac{\mathcal{O}(n \log_2 (n)^2)}{(n+2)}\\[8pt]
(n+2) \cdot (\log_2(n+1) + 1)^2 &amp;amp;\leq \mathcal{O}(n \cdot \log_2 (n)^2)\\[8pt]
\end{align}\]

&lt;p&gt;&lt;em&gt;Part 2:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For this part, we rely on the following property:&lt;/p&gt;

\[\frac{1}{n+1} \leq \log(n+1) - \log(n) \leq \frac{1}{n}\]

&lt;p&gt;This is true for all logarithms for all \(n \in \mathbb{N}_+\).&lt;/p&gt;

&lt;p&gt;We now show the second requirement of the Lemma is true. However, we cannot use
equivalence transformations as in the other proofs. Hence, we show it by
implication.&lt;/p&gt;

\[\begin{align}
n+2 &amp;amp;= n+2\\[8pt]
(n+2) (1+\log_2(n+2)) &amp;amp;= (n+2) (1+\log_2(n+2))\\[8pt]
(n+2) (1+\log_2(n+2)) &amp;amp;= \frac{1+\log_2(n+2)}{\frac{1}{n+2}}\\[8pt]
(n+2) \log_2(n+2) + (n+2) &amp;amp;= \frac{1+\log_2(n+2)}{\frac{1}{n+2}}\\[8pt]
(n+2) \log_2(n+2) + (n+2) &amp;amp;\geq \frac{1+\log_2(n+2)}{\log_2(n+2) - \log_2(n+1)}\\[8pt]
(n+2) \log_2(n+2) + (n+2) &amp;amp;\geq \frac{1+\log_2((n+1)+1)}{\log_2((n+1)+1) - \log_2(n+1)}\\[8pt]
A(n) &amp;amp;\geq \frac{1+R(n+1)}{R(n+1)-R(n)}\\[8pt]
\end{align}\]</content>
</entry>

<entry>
  <title>Goodbye Gnu-EFI!</title>
  <id>https://dvdhrm.github.io/2019/01/31/goodbye-gnuefi</id>
  <published>2019-01-31T00:00:00+00:00</published>
  <updated>2019-01-31T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2019/01/31/goodbye-gnuefi/" rel="alternate" type="text/html" title="Goodbye Gnu-EFI!" />

  <summary type="html">&lt;p&gt;The recommended way to link &lt;a href=&quot;https://www.uefi.org/&quot;&gt;UEFI&lt;/a&gt; applications on linux
was until now through
&lt;em&gt;GNU-EFI&lt;/em&gt;, a toolchain provided by the &lt;em&gt;GNU Project&lt;/em&gt; that bridges from the
&lt;em&gt;ELF&lt;/em&gt; world into &lt;em&gt;COFF/PE32+&lt;/em&gt;. But why don’t we compile directly to native
UEFI? A short dive into the past of &lt;em&gt;GNU Toolchains&lt;/em&gt;, its remnants, and a
surprisingly simple way out.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2019/01/31/goodbye-gnuefi/">&lt;p&gt;The recommended way to link &lt;a href=&quot;https://www.uefi.org/&quot;&gt;UEFI&lt;/a&gt; applications on linux
was until now through
&lt;em&gt;GNU-EFI&lt;/em&gt;, a toolchain provided by the &lt;em&gt;GNU Project&lt;/em&gt; that bridges from the
&lt;em&gt;ELF&lt;/em&gt; world into &lt;em&gt;COFF/PE32+&lt;/em&gt;. But why don’t we compile directly to native
UEFI? A short dive into the past of &lt;em&gt;GNU Toolchains&lt;/em&gt;, its remnants, and a
surprisingly simple way out.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Linux World&lt;/em&gt; (and many &lt;em&gt;UNIX Derivatives&lt;/em&gt; for that matter) is modeled
around
&lt;a href=&quot;https://en.wikipedia.org/wiki/Executable_and_Linkable_Format&quot;&gt;ELF&lt;/a&gt;. With
statically linked languages becoming more prevalent, the impact of the ABI
diminishes, but it still defines properties far beyond just how to call
functions. The ABI your system uses also effects how compiler and linker
interact, how binaries export information (especially symbols), and what
features application developers can make use of. We have become used to ELF,
and require its properties in places we didn’t expect.&lt;/p&gt;

&lt;p&gt;UEFI does not use ELF. For all that matters,
&lt;a href=&quot;https://www.uefi.org/uefi&quot;&gt;UEFI follows Microsoft Windows&lt;/a&gt;. This means, UEFI
uses
&lt;a href=&quot;https://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx&quot;&gt;&lt;em&gt;COFF/PE32+&lt;/em&gt;&lt;/a&gt;
(or short &lt;em&gt;PE+&lt;/em&gt;). If we compile binaries for UEFI, they must target &lt;em&gt;PE+&lt;/em&gt;. And
the &lt;em&gt;GNU Compiler Collection&lt;/em&gt; can do this… somewhat.&lt;/p&gt;

&lt;p&gt;Conceptually, &lt;em&gt;GCC&lt;/em&gt; supports many languages, ABIs, targets, and architectures
in a single code-base. Technically, though, every compiled instance of &lt;em&gt;GCC&lt;/em&gt;
compiles from one language to one target. Your compiler that takes &lt;em&gt;C&lt;/em&gt; and
produces &lt;em&gt;x86-64&lt;/em&gt; is actually specific to &lt;em&gt;x86_64-pc-linux-gnu&lt;/em&gt;. You cannot
tweak it to compile UEFI binaries. Instead, you need another instance of &lt;em&gt;GCC&lt;/em&gt;,
one that takes &lt;em&gt;C&lt;/em&gt; and produces &lt;em&gt;x86_64-windows-msvc&lt;/em&gt;. You probably know this
combination under the name &lt;em&gt;MinGW&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But this is not what &lt;em&gt;GNU&lt;/em&gt; went for. Instead, to what still puzzles me to this
day, the &lt;em&gt;GNU&lt;/em&gt; project decided against using its own software and instead
produced something named
&lt;a href=&quot;https://sourceforge.net/projects/gnu-efi/&quot;&gt;&lt;em&gt;GNU-EFI&lt;/em&gt;&lt;/a&gt;. The goal of &lt;em&gt;GNU-EFI&lt;/em&gt;
is to allow writing UEFI applications using the common &lt;em&gt;GNU Toolchain&lt;/em&gt; (meaning
you compile &lt;em&gt;ELF&lt;/em&gt; binaries for &lt;em&gt;Linux&lt;/em&gt;). They achieve this by linking a
&lt;em&gt;PE+ Stub&lt;/em&gt;, which at runtime performs required relocations, parameter
translations, and jumps into the &lt;em&gt;ELF&lt;/em&gt; application. You effectively write a
free-standing &lt;em&gt;Linux Application&lt;/em&gt;, add a wrapping layer and then execute it on
&lt;em&gt;UEFI&lt;/em&gt;. It works, but is needlessly complex.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Is this really the best way to compile for UEFI?&lt;/em&gt; &lt;strong&gt;Not anymore!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;LLVM&lt;/em&gt; toolchain (&lt;em&gt;clang&lt;/em&gt; compiler plus &lt;em&gt;lld&lt;/em&gt; linker) combines all
supported targets in a single toolchain, offering a target selector &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--target&lt;/code&gt;
to let &lt;em&gt;LLVM&lt;/em&gt; know what to compile for. So as long as you have &lt;em&gt;clang&lt;/em&gt; and
&lt;em&gt;lld&lt;/em&gt; installed, you can compile native UEFI binaries just like normal local
compilation:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Normal local compile+link&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;clang &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$CFLAGS&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; OBJECT &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;SOURCES…]
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;clang &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$LDFLAGS&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; BINARY &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;OBJECTS…]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To make this compile for UEFI targets, you simply set:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CFLAGS+&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt; x86_64-unknown-windows &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-ffreestanding&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-fshort-wchar&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-mno-red-zone&lt;/span&gt;

LDFLAGS+&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt; x86_64-unknown-windows &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-nostdlib&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-Wl&lt;/span&gt;,-entry:efi_main &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-Wl&lt;/span&gt;,-subsystem:efi_application &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-fuse-ld&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;lld-link
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The two things special are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--target &amp;lt;TRIPLE&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--fuse-ld=&amp;lt;LINKER&amp;gt;&lt;/code&gt;. The
former instructs both compiler and linker to produce &lt;em&gt;COFF/PE32+&lt;/em&gt; objects
compatible to the &lt;em&gt;Microsoft Windows Platform&lt;/em&gt; (which matches the UEFI
platform). The latter selects the linker to use. Mind you, using the default
linker will very likely fail (default being &lt;em&gt;ld&lt;/em&gt; or &lt;em&gt;ld-gold&lt;/em&gt;). Currently, you
either have to use &lt;em&gt;lld-link&lt;/em&gt; (&lt;em&gt;PE+&lt;/em&gt; backend of the &lt;em&gt;LLVM&lt;/em&gt; linker), or you need
a version of &lt;em&gt;GNU-ld&lt;/em&gt; compiled for a &lt;em&gt;PE+&lt;/em&gt; toolchain. I recommend &lt;em&gt;LLVM lld&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Voilà! No need for &lt;em&gt;GNU-EFI&lt;/em&gt;, no need to mess with separated toolchains. With
&lt;em&gt;LLVM&lt;/em&gt; you get all this through your local toolchain.&lt;/p&gt;

&lt;p&gt;If you use &lt;em&gt;Meson Build&lt;/em&gt;, the
&lt;a href=&quot;https://github.com/c-util/c-efi&quot;&gt;&lt;strong&gt;c-efi&lt;/strong&gt;&lt;/a&gt; project even provides you an
example &lt;em&gt;cross-file&lt;/em&gt;. A native meson C project can then be compiled for UEFI by
nothing more than passing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cross-file x86_64-unknown-uefi&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meson&lt;/code&gt;. See
its
&lt;a href=&quot;https://github.com/c-util/c-efi/blob/master/src/x86_64-unknown-uefi.mesoncross.ini&quot;&gt;sources&lt;/a&gt;
for details.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/c-util/c-efi&quot;&gt;&lt;strong&gt;c-efi&lt;/strong&gt;&lt;/a&gt; project also provides the
protocol contants and definitions from the UEFI specification, so you don’t
have to extract them yourself.&lt;/p&gt;</content>
</entry>

<entry>
  <title>Exec in VM</title>
  <id>https://dvdhrm.github.io/2018/01/10/exec-in-vm</id>
  <published>2018-01-10T00:00:00+00:00</published>
  <updated>2018-01-10T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2018/01/10/exec-in-vm/" rel="alternate" type="text/html" title="Exec in VM" />

  <summary type="html">&lt;p&gt;Almost everyone these days relies on continuous integration. And it seems, once
you got accustomed to it, you never want to work without it again.
Unfortunately, most CI systems lack cross-architecture capabilities. As a
systems engineer with lots of C projects, I was desperately looking for a
solution to run my tests on little-endian, big-endian, 32bit, and 64bit
machines. So far, without any luck. Hence, I patched together qemu, docker,
fedora, and some bash scripts to get a tool that allows me to execute scripts
from the command-line in a VM ad-hoc.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2018/01/10/exec-in-vm/">&lt;p&gt;Almost everyone these days relies on continuous integration. And it seems, once
you got accustomed to it, you never want to work without it again.
Unfortunately, most CI systems lack cross-architecture capabilities. As a
systems engineer with lots of C projects, I was desperately looking for a
solution to run my tests on little-endian, big-endian, 32bit, and 64bit
machines. So far, without any luck. Hence, I patched together qemu, docker,
fedora, and some bash scripts to get a tool that allows me to execute scripts
from the command-line in a VM ad-hoc.&lt;/p&gt;

&lt;p&gt;My ultimate goal is to type &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmrun make&lt;/code&gt;&lt;/strong&gt; as replacement for &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;&lt;/strong&gt;,
and it spawns a virtual machine, mounts the current directory into the machine,
executes &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;&lt;/strong&gt; inside of it, returning the exit-code to my shell. Of
course, it could be extended to support selecting the target architecture
and/or OS image to us. So eventually, it might look something like:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vmrun &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--image&lt;/span&gt; fedora-ci &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--architecture&lt;/span&gt; armv7hl &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            meson setup build &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ninja &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a developer, I would love having this at hand. I can easily compile &lt;strong&gt;and
run&lt;/strong&gt; projects in foreign architectures, without the requirement of setting up
non-volatile VMs, moving data in and out of the machine, and also getting
automation and scripting support.&lt;/p&gt;

&lt;p&gt;Containers already allow this kind of setup. Using &lt;em&gt;docker&lt;/em&gt; or &lt;em&gt;systemd-nspawn&lt;/em&gt;
you can get something similar already:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--interactive&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--tty&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--volume&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;:/mnt/cwd &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--workdir&lt;/span&gt; /mnt/cwd &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    fedora-ci &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            meson setup build &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ninja &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; build

systemd-nspawn &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--bind&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;:/mnt/cwd &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--chdir&lt;/span&gt; /mnt/cwd &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--ephemeral&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--image&lt;/span&gt; fedora-ci &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            meson setup build &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ninja &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This, however, has one major drawback: This can only run native binaries. If
you want to run code in a foreign architecture, you need a kernel for that
architecture as well. There are options like &lt;strong&gt;qemu-user&lt;/strong&gt;, though they cannot
provide perfect compatibility. They only get you so far.&lt;/p&gt;

&lt;p&gt;Hence, you need some machine emulator. So how about we execute the image inside
of qemu, rather than in a container? Sounds easier than it is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Needs to Boot&lt;/strong&gt;: Unlike in a container, the virtual machine needs to boot a
kernel, user-space, and prepare the execution environment. This means, we
cannot simply specify a script or binary to execute by qemu. We must actually
boot the image and instruct the image to execute a given binary.&lt;/p&gt;

    &lt;p&gt;One way to get this to work on Fedora is to craft a special &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.service&lt;/code&gt; file
and pull it in after boot is done. Make the service file execute your binary
and then poweroff the machine when done, or on failure.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Exit-Code Propagation&lt;/strong&gt;: The qemu emulator does not propagate the
exit-code of the code executed in the virtual machine. Hence, we need a
side-channel to detect whether the script executed successfully. This is
easily done by hooking up a separate serial-line and making your OS write
&lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;success&lt;/code&gt;&lt;/em&gt; into it, once everything succeeded.&lt;/p&gt;

    &lt;p&gt;Maybe someone wants to hook up a qemu extension to propagate Exit-Codes?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Bind Mounts&lt;/strong&gt;: The biggest issue is, we cannot simply bind-mount the
directory of the caller into the virtual machine. This is particularly bad,
because there is no simple alternative solution. The closest possible
solution I am aware of is to share the directory via &lt;strong&gt;NFS&lt;/strong&gt; or &lt;strong&gt;9pfs&lt;/strong&gt;.&lt;/p&gt;

    &lt;p&gt;Maybe someone can figure out a way to do this. All my attempts failed. While
I successfully shared the directory, either performance suffered, or random
features failed, which were expected by some development tools (e.g.,
file-locks or mmap failed). I am not saying the tools are broken, but just
that I couldn’t make it work. Help welcome!&lt;/p&gt;

    &lt;p&gt;(Also be aware that you suddenly run into UID and permission issues. The
 entire qemu machine runs as an unprivileged user, so it will only be able to
 access/write files as that user. But inside of the VM, you are free to use
 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; and friends. There is no way to propagate this to the outside. This
 might be fine, but it is a source of confusion.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Image Hubs&lt;/strong&gt;: While docker gave us image stores for free (e.g.,
Docker Hub, Quay.io, etc.), there is nothing like it for virtual machine
images. Companies seem unwilling to provide the world with free terrabytes of
storage.&lt;/p&gt;

    &lt;p&gt;Solution: Use docker.&lt;/p&gt;

    &lt;p&gt;While docker stores images in a format unsuitable to qemu, we can still use
its storage. I simply took my XFS-qcow2 image-file and threw it into a docker
container. While at it, I threw in a qemu binary with all its dependencies as
well. This combined image can now be pushed to docker repositories and be
hosted on Docker Hub and friends. As a consumer, you simply fetch the docker
image and execute the qemu-binary inside of it, including its embedded OS
image.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I went forth and threw together all the bits and pieces. But, sadly, I cannot
provide you the &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmrun&lt;/code&gt;&lt;/strong&gt; tool as I described it above. I simply ran into too
many issues around sharing a directory. However, I did end up with something
close:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;/myscript.sh:/mnt/cherryimages/input/main:ro &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        cherrypick/cherryimages-fedora-vmrun:ci-x86_64-to-armv7hl-20180110-1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command executes &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PWD/myscript.sh&lt;/code&gt;&lt;/em&gt; inside of a fedora armv7hl image,
hosted by an &lt;em&gt;x86_64&lt;/em&gt; qemu. For reproducability, I tagged the image at the time
of this blog-post as
&lt;em&gt;cherrypick/cherryimages-fedora-vmrun:ci-x86_64-to-armv7hl-20180110-1&lt;/em&gt;. If you
want the latest image, use
&lt;em&gt;cherrypick/cherryimages-fedora-vmrun:ci-x86_64-to-armv7hl-latest&lt;/em&gt;. Other tags
exist as well. Just check out the repository, if interested. The Dockerfile
sources as of the time of this post can be found on
&lt;a href=&quot;https://github.com/cherry-pick/cherry-images/tree/a176d7feb95bc3cf89dd8071e304f30f763820cb&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unlike the &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmrun&lt;/code&gt;&lt;/strong&gt; tool I described above, this shares the input script
read-only. Furthermore, it shares the input as FAT16 volume (qemu can create
this on-the-fly via the vvfat driver), so its size is quite limited, and
filesystem attributes are mostly discarded. In the end, its only use is to push
a script into the machine to execute (alternatively, you can push an entire
directory into the machine, but the entrypoint must be named &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;For my personal use, I now added a script that fetches a git-repository, runs
the embedded tests, and returns.
In combination with this docker-qemu-image, I can easily run my CI on
foreign architectures. Maybe some day I will pick this up again and get a
proper &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmrun&lt;/code&gt;&lt;/strong&gt; tool (or maybe someone else does?). Until then, I will stick
to the reduced version, as it serves my needs. Sadly, there are still too many
variables that cannot be auto-detected (How many memory to give to the VM?
Which devices to forward? Which CPU features to enable?), and too many hacks
required (String-conversions required between different command-lines… Getting
a distribution to boot fast in these containers… Sharing data correctly into
and out of the VM…).&lt;/p&gt;

&lt;p&gt;In the end, I think it is just too much a hassle to turn into a project I can
maintain and support. The tools I needed do not provide proper APIs, but
require me to lump together command-lines, PID-files, and magic configurations.
Maybe some day we will get there? Until then, lets make use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu-user&lt;/code&gt; and
avoid system integration tests…&lt;/p&gt;</content>
</entry>

<entry>
  <title>Cross-Bootstrap Fedora</title>
  <id>https://dvdhrm.github.io/2018/01/09/cross-bootstrap-fedora</id>
  <published>2018-01-09T00:00:00+00:00</published>
  <updated>2018-01-09T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2018/01/09/cross-bootstrap-fedora/" rel="alternate" type="text/html" title="Cross-Bootstrap Fedora" />

  <summary type="html">&lt;p&gt;I recently had to assemble linux distribution images to be run in containers and
virtual machines. While most package managers provide tools to bootstrap an
entire distribution into a target directory (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debootstrap&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf
--installroot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zypper&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pacstrap&lt;/code&gt;, …), I needed to do that for foreign
architectures. Fortunately, Fedora got me covered!&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2018/01/09/cross-bootstrap-fedora/">&lt;p&gt;I recently had to assemble linux distribution images to be run in containers and
virtual machines. While most package managers provide tools to bootstrap an
entire distribution into a target directory (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debootstrap&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf
--installroot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zypper&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pacstrap&lt;/code&gt;, …), I needed to do that for foreign
architectures. Fortunately, Fedora got me covered!&lt;/p&gt;

&lt;p&gt;If you use &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf --installroot=/path&lt;/code&gt;&lt;/em&gt;, dnf will perform the given operations in
a separate directory tree, rather than your file-system root. It is easy to use
this with &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf install&lt;/code&gt;&lt;/em&gt; to install an entire Fedora distribution into some
custom directory. Unfortunately, RPM allows scripts to be run as part of the
installation process of packages. Those scripts might invoke binaries of the
target architecture as part of the installation. Hence, before we can cross
bootstrap Fedora, we need one more tool: qemu-user-static&lt;/p&gt;

&lt;p&gt;The qemu project provides two kinds of emulators:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;System Emulators&lt;/strong&gt;: These are the commonly known emulators used to emulate
an entire machine of a given architecture. They can be used to run virtual
machines of any kind. The binaries are usually called
&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu-system-&amp;lt;arch&amp;gt;&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;User Emulators&lt;/strong&gt;: These emulators are much less known. They emulate the
linux user-space of your target architecture of choice. That is, they
execute binaries of foreign architectures on your machine, translating on
the syscall boundary. Hence, you can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MIPS&lt;/code&gt; binaries on your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x86_64&lt;/code&gt;
machine running a normal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x86_64&lt;/code&gt; kernel, as long as you use the
qemu-user-mips emulator. The binaries are usually called
&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu-&amp;lt;arch&amp;gt;&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fedora provides a package called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu-user-static&lt;/code&gt;, which provides statically
linked qemu user-space emulators and hooks them up with the kernel-binfmt
configuration. Hence, with the package installed, you can directly execute
binaries of foreign architectures, and the kernel will use the qemu emulators
to run the binaries. Since the qemu emulators are statically linked, they will
work just fine in chroots as well.&lt;/p&gt;

&lt;p&gt;With this in mind, you can simply add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--forcearch=&amp;lt;arch&amp;gt;&lt;/code&gt; to dnf to bootstrap
Fedora in a foreign architecture. For instance, this bootstraps just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt; and
all its dependencies as 32bit ARM targets:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dnf \
        -y \
        --repo=fedora \
        --repo=updates \
        --releasever=27 \
        --forcearch=armv7hl \
        --installroot=/some/path \
        install \
                bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For more information, have a look at Nathaniel McCallum’s
&lt;a href=&quot;https://npmccallum.gitlab.io/post/cross-architecture-roots-with-dnf/&quot;&gt;introduction&lt;/a&gt;
of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--forcearch&lt;/code&gt; argument to dnf.&lt;/p&gt;</content>
</entry>

<entry>
  <title>Rethinking the D-Bus Message Bus</title>
  <id>https://dvdhrm.github.io/rethinking-the-dbus-message-bus</id>
  <published>2017-08-23T00:00:00+00:00</published>
  <updated>2017-08-23T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/rethinking-the-dbus-message-bus/" rel="alternate" type="text/html" title="Rethinking the D-Bus Message Bus" />

  <summary type="html">&lt;p&gt;Later this year, on November 21, 2017, D-Bus will see its
&lt;a href=&quot;https://cgit.freedesktop.org/dbus/dbus/commit/?id=93cff3d69fb705806d2af4fd6f29c497ea3192e0&quot;&gt;15th birthday&lt;/a&gt;.
An impressive age, only shy of the KDE and GNOME projects, whose collaboration
inspired the creation of this independent IPC system. While still relied upon
by the most recent KDE and GNOME releases, D-Bus is not free of criticism.
Despite its age and mighty advocates, it never gained traction outside of its
origins. On the contrary, it has long been criticized as bloated,
over-engineered, and orphaned. Though, when looking into those claims, you’re
often left with unsubstantiated ranting about the environment D-Bus is used in.
If you rather want a glimpse into the deeper issues, the best place to look is
the
&lt;a href=&quot;https://bugs.freedesktop.org/buglist.cgi?bug_status=__open__&amp;amp;product=dbus&quot;&gt;D-Bus bug-tracker&lt;/a&gt;,
including the assessments of the D-Bus developers
themselves. The bugs range from uncontrolled memory usage, over silent dropping
of messages, to dead-locks by design, unsolved for up to 7 years. Looking
closer, most of them simply cannot be solved without breaking guarantees long
given by &lt;em&gt;dbus-daemon(1)&lt;/em&gt;, the reference implementation. Hence, workarounds
have been put in place to keep them under control.&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/rethinking-the-dbus-message-bus/">&lt;p&gt;Later this year, on November 21, 2017, D-Bus will see its
&lt;a href=&quot;https://cgit.freedesktop.org/dbus/dbus/commit/?id=93cff3d69fb705806d2af4fd6f29c497ea3192e0&quot;&gt;15th birthday&lt;/a&gt;.
An impressive age, only shy of the KDE and GNOME projects, whose collaboration
inspired the creation of this independent IPC system. While still relied upon
by the most recent KDE and GNOME releases, D-Bus is not free of criticism.
Despite its age and mighty advocates, it never gained traction outside of its
origins. On the contrary, it has long been criticized as bloated,
over-engineered, and orphaned. Though, when looking into those claims, you’re
often left with unsubstantiated ranting about the environment D-Bus is used in.
If you rather want a glimpse into the deeper issues, the best place to look is
the
&lt;a href=&quot;https://bugs.freedesktop.org/buglist.cgi?bug_status=__open__&amp;amp;product=dbus&quot;&gt;D-Bus bug-tracker&lt;/a&gt;,
including the assessments of the D-Bus developers
themselves. The bugs range from uncontrolled memory usage, over silent dropping
of messages, to dead-locks by design, unsolved for up to 7 years. Looking
closer, most of them simply cannot be solved without breaking guarantees long
given by &lt;em&gt;dbus-daemon(1)&lt;/em&gt;, the reference implementation. Hence, workarounds
have been put in place to keep them under control.&lt;/p&gt;

&lt;p&gt;Nevertheless, these issues still bugged us!
Which is, why we rethought some of the fundamental concepts behind the shared
Message Buses defined by the D-Bus Specification. We developed a new
architecture that is designed particularly for the use-cases of modern D-Bus,
and it allows us to solve several long standing issues with &lt;em&gt;dbus-daemon(1)&lt;/em&gt;.
With this in mind, we set out to implement an alternative D-Bus Message Bus.
Half a year later, we hereby announce the
&lt;a href=&quot;https://www.github.com/bus1/dbus-broker/wiki&quot;&gt;&lt;strong&gt;dbus-broker project&lt;/strong&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;But before we dive into the project, lets first have a look at some of the long
standing open bug reports on D-Bus. A selection:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://bugs.freedesktop.org/show_bug.cgi?id=33606#c11&quot;&gt;Bug #33606&lt;/a&gt;:
&lt;em&gt;“stop dbus-daemon memory usage ballooning if a client is slow to read”&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;The bug-report describes a situation where the memory-usage of
&lt;em&gt;dbus-daemon(1)&lt;/em&gt; grows in an uncontrolled manner, if inflight messages keep
piling up in the incoming and outgoing queues of the daemon. Despite
being reported more than 6 years ago, there is no satisfying solution
to the issue.&lt;/p&gt;

    &lt;p&gt;What it boils down to is the fact that &lt;em&gt;dbus-daemon(1)&lt;/em&gt; does not
judge messages based on their message type. Hence, whether a message
was triggered by a peer itself (e.g., a method call), or triggered by
another peer (e.g., a method reply), the message is always accounted on
the sender of the message. Hence, if those messages are piled up in
outgoing queues in &lt;em&gt;dbus-daemon(1)&lt;/em&gt;, the sender of those messages is
accounted and punished for them.
This can be misused by malicious applications that simply trigger a
target peer to send messages (like method replies and signals), but
they never read those messages but leave them queued. As a result,
there is still no agreed upon way to decide who to punish for excessive
buffering.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://bugs.freedesktop.org/show_bug.cgi?id=80817&quot;&gt;Bug #80817&lt;/a&gt;:
&lt;em&gt;“messages with abusive recursion are silently dropped”&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Depending on the linux kernel you use, consecutively queued
unix-domain-sockets may be rejected by &lt;strong&gt;sendmsg(2)&lt;/strong&gt;. This can have the
effect of &lt;em&gt;dbus-daemon(1)&lt;/em&gt; being unable to forward a message. The message
will be silently dropped, without notifying anyone.&lt;/p&gt;

    &lt;p&gt;There is no known workaround for this issue, since the time of
&lt;strong&gt;sendmsg(2)&lt;/strong&gt; might be too late for proper error-handling, due to output
buffering or short writes.&lt;/p&gt;

    &lt;p&gt;Similarly,
&lt;a href=&quot;https://bugs.freedesktop.org/show_bug.cgi?id=52372&quot;&gt;Bug #52372&lt;/a&gt;
describes another situation where messages are
silently dropped, if they are queued on an activatable name but their
sender disconnects before the destination is activated.&lt;/p&gt;

    &lt;p&gt;Lastly, &lt;em&gt;dbus-daemon(1)&lt;/em&gt; might fail any message and reply with an error
message. That is, method-calls but also method-replies, signals, and
error-messages can all be rejected for arbitrary reason by
&lt;em&gt;dbus-daemon(1)&lt;/em&gt; and trigger an error-reply. Nearly no application is
ready to expect asynchronous error-replies to their attempt to send a
method reply or signal.
Again, this stems from &lt;em&gt;dbus-daemon(1)&lt;/em&gt; never judging messages by their
type. Despite method-transactions being stateful, there is no reliable
way for a peer to cancel a message transaction. Any attempt to do so
might fail. Same is true for a signal-subscription.&lt;/p&gt;

    &lt;p&gt;There are some more similar scenarios where &lt;em&gt;dbus-daemon(1)&lt;/em&gt; has to
silently drop messages, or unexpectedly rejects messages, thus breaking
the rule of reliability. This is not about catching errors in client
libraries, but this is about either messages being silently discarded
or asynchronously rejected.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://bugs.freedesktop.org/show_bug.cgi?id=28355&quot;&gt;Bug #28355&lt;/a&gt;:
&lt;em&gt;“dbus-daemon hangs while starting if users are in LDAP/NIS/etc.”&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Additionally to client-side policies, &lt;em&gt;dbus-daemon(1)&lt;/em&gt; implements a
mandatory access control mechanism, based on uids, gids, and message
content. This, however, required D-Bus to resolve user-names and
group-names to IDs, which will involve NSS, and as such LDAP/NIS/etc.
This has long been a source of deadlocks, when using D-Bus to implement
those NSS modules themselves. Workarounds are available, but the
problem itself is not solved.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://bugs.freedesktop.org/show_bug.cgi?id=83938&quot;&gt;Bug #83938&lt;/a&gt;:
&lt;em&gt;“improve data structures for pending replies”&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;This bug-report concerns the method-call tracking in &lt;em&gt;dbus-daemon(1)&lt;/em&gt;,
which is used to allow exactly one reply per method-call, but not more.
A list of &lt;em&gt;open reply windows&lt;/em&gt; is kept to track pending method-calls.
In &lt;em&gt;dbus-daemon(1)&lt;/em&gt;, this is a global, linked list, searched whenever a
reply is sent. By queuing up too many replies on too many connections,
lookups on this list will consume a considerable amount of time,
slowing down the entire bus.&lt;/p&gt;

    &lt;p&gt;While the issue at hand can be solved, and has been solved, there
remain many similar global data-structures in &lt;em&gt;dbus-daemon(1)&lt;/em&gt;, that are
shared across all users. Some of them can be fixed, some cannot, since
D-Bus defines some global behavior (like broadcast matching and
name-ownership/handover). This prevents D-Bus from scaling nicely with
more processors being added to a system.&lt;/p&gt;

    &lt;p&gt;In fact, the name-registry of D-Bus, and the atomic hand-over of queued
name owners, requires huge global state-tracking without any known
efficient, parallel solution.&lt;/p&gt;

    &lt;p&gt;Furthermore, many of the employed workarounds simply introduce per-peer
limits for those global resources. By setting them low enough, their
scope has been kept under control. However, history shows that those
limits have had violated application expectations
&lt;a href=&quot;https://bugs.freedesktop.org/show_bug.cgi?id=50264&quot;&gt;several&lt;/a&gt;
&lt;a href=&quot;https://github.com/NetworkManager/NetworkManager/commit/2c299ba65c51e9c407090dc83929d692c74ee3f2&quot;&gt;times&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of the issues mentioned here is critical enough for D-Bus to become
unbearable. On the contrary, D-Bus is still popular and no serious replacement
is even close to be considered a contender. Furthermore, suitable workarounds
have often been put in place to control those issues.&lt;/p&gt;

&lt;p&gt;But we kept being annoyed by these fundamental problems, so we set forth to
solve them in &lt;em&gt;dbus-broker(1)&lt;/em&gt;. What we came up with is a set of theoretical
rules and concepts for a different message bus:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Shared Medium&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;This is a rather theoretical change. Previously, the D-Bus Message Bus
followed the model of actual physically wired buses, where peers place
messages on a shared medium for others to fetch. The problem here is to
guarantee fairness, and to make peers accountable for excessive use.
In D-Bus the problem can be reduced to outgoing queues in the message
broker. Whenever many peers send messages to the same destination, they
fill the same message queue. If that queue runs full, someone needs to
be held accountable. Was the destination too slow reading messages and
should be disconnected? Did a sender flood the destination with an
unreasonable amount of messages? Or did an innocent 3rd party just send
a single message, but happened to be the final straw?&lt;/p&gt;

    &lt;p&gt;We decided to overcome this by throwing the model of a shared medium
overboard. We no longer consider a D-Bus Message Bus a global medium
that all peers
are connected to and submit messages to. We rather consider a bus a set
of distinct peers with no global state. Whenever a peer sends a message,
we consider this a transaction between the sender and the destination
(or multiple destinations in case of multicasts). We try to avoid any
global state or context. We want every action taken by a peer to only
affect the source and target of the action, but nothing else.&lt;/p&gt;

    &lt;p&gt;While nice in theory, D-Bus does not allow this. There is global state,
and it is hard-coded in the D-Bus specification with many existing
applications relying on it. However, we still tried to stick to this as
close as possible. In particular, this means:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Whenever a peer creates an object in the bus manager, it must be
linked and indexed on a specific peer. There must not be any
global lists or maps. Whenever the bus manager performs a
transaction, it must be able to collect all objects that affect
it by just looking at the involved peers.&lt;/p&gt;

        &lt;p&gt;This rule is, in some corner-cases, violated to keep compatibility
to the specification. That is, if applications rely on global
behavior, it will still work. However, anything that can be
indexed, is indexed, and as long as applications don’t rely on
obscure D-Bus features, they will never end up in those global
data-structures.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;We now judge messages by their message types. We implement proper
message transactions and always know who to account for for
inflight
messages. Moreover, every peer now has a limited incoming queue,
which every other peer gets a fair share of. Whenever a peer
exceeds their share on another peer’s queue, one of both exceeded
their configured limits and the message must be rejected.
Details on how we dynamically adjust those shares can be found in
the online
&lt;a href=&quot;https://github.com/bus1/dbus-broker/wiki/Accounting&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;

        &lt;p&gt;We still need to decide who is at fault. Is the sender to blame
or the receiver? Our solution is to base this on the question
whether a message is unsolicited. That is, for unsolicited
messages, the sender is to blame. For solicited messages, the
receiver is to blame. Effectively, this means whenever you send a
method call, you are to blame if you did not account for the
reply. In case of signals, we simply treat a subscription as the
intention of the subscriber to receive an unlimited stream of
signals, thus making subscribed signals solicited.&lt;/p&gt;

        &lt;p&gt;Lastly, in case of unsolicited messages, we reply with an error,
and expect every peer to be able to deal with asynchronous errors
to unsolicited messages. By contrast, solicited messages
never yield an error. Instead, we always consider the receiver of
solicited messages to be at fault, thus throw them off the bus.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No IPC to implement IPC&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;D-Bus is an IPC mechanism to allow other processes to communicate. We
strictly believe that the implementation of an IPC mechanism should not
use IPC itself. Otherwise, deadlocks are a steady threat.&lt;/p&gt;

    &lt;p&gt;This means, the transaction of a message (whatever kind) should not
depend on any other means but local data. We do not read files, we do
not invoke NSS, we do not call into D-Bus. Instead, the operation of the
bus manager regarding message transactions is a self-contained process
without any external hooks or callbacks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;User-based Accounting&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Any resource and any object allocated in the bus must be accounted on a
user. We do not account based on peers, but always account based on
users.&lt;/p&gt;

    &lt;p&gt;In particular, this means we never have stacked accounting. We have
limits for specific resources, but all those limits only ever affect the
user accounting. That is, you can no longer exceed limits by simply
connecting multiple times to the bus, or by creating objects that have
separate accounting. Instead, whenever an action is accounted, it will
be accounted on the calling user, regardless through which peer or object
the action is performed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Never ever shall a message be silently dropped! Any error condition must
be caught and handled, and must never put peers into unexpected
situations.&lt;/p&gt;

    &lt;p&gt;If a situation arises where we cannot gracefully handle an error
condition, we exit. We never put the burden on the peers, nor do we
silently ignore it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these in mind, we implemented an independent D-Bus Message Bus and named
it &lt;strong&gt;dbus-broker&lt;/strong&gt;. It is available on
&lt;a href=&quot;https://www.github.com/bus1/dbus-broker&quot;&gt;GitHub&lt;/a&gt; and already capable of
booting a full Fedora Desktop System. Some of its properties are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Pure Bus Implementation&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;One of our aims was to make the bus manager a pure implementation with as
little policy as possible. Furthermore, following our rule of &lt;em&gt;“No IPC to
implement IPC”&lt;/em&gt;, we stripped all external communication from it. The
result is a standalone program we call &lt;em&gt;dbus-broker&lt;/em&gt;, which implements a
Message Bus as defined by the D-Bus specification. The only external
control channel is a private socketpair that must be passed down by the
parent process that spawns &lt;em&gt;dbus-broker(1)&lt;/em&gt;. This channel is used to control
the broker at runtime, as well as get notified about specific events like
name activation.&lt;/p&gt;

    &lt;p&gt;On top of this, we implemented a launcher compatible to &lt;em&gt;dbus-daemon(1)&lt;/em&gt;,
employing &lt;em&gt;dbus-broker(1)&lt;/em&gt;. This &lt;em&gt;dbus-broker-launch(1)&lt;/em&gt; program implements
the &lt;em&gt;dbus-daemon(1)&lt;/em&gt; semantics of a system and session/user message bus.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Local Only&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;We only implement local IPC. No remote transports are supported. We
believe that this is beyond the realm of D-Bus. You can always employ ssh
tunneling to get remote D-Bus working, just like most projects do
already.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Legacy&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;We do not implement legacy D-Bus features. Anything that is marked as
deprecated was dropped, as long as it is not relied upon by crucial
infrastructure. We are compatible to &lt;em&gt;dbus-daemon(1)&lt;/em&gt;, so use it if your
system still requires those legacy features.&lt;/p&gt;

    &lt;p&gt;All those deviations are documented in our online
&lt;a href=&quot;https://github.com/bus1/dbus-broker/wiki/Deviations&quot;&gt;wiki&lt;/a&gt;. Each case comes
with a rationale why we decided to drop support for it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Linux Only&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;A lot of functionality we rely on is simply not available on other
operating systems. &lt;em&gt;dbus-daemon(1)&lt;/em&gt; is still around (and will stay around),
so there will always be a working D-Bus Message Bus for other operating
systems.&lt;/p&gt;

    &lt;p&gt;Note that we rely on several peculiar features of the linux kernel to
implement a secure message broker (including its accounting for inflight
FDs, its output queueing on &lt;em&gt;AF_UNIX&lt;/em&gt; including the &lt;em&gt;IOCOUTQ&lt;/em&gt; ioctl,
edge-triggered event notification, &lt;em&gt;SO_PEERGROUPS&lt;/em&gt; ioctl, and more). We
fixed
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/net/core/sock.c?id=28b5ba2aa0f55d80adb2624564ed2b170c19519e&quot;&gt;several&lt;/a&gt;
&lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/commit/net/unix/af_unix.c?id=27eac47b00789522ba00501b0838026e1ecb6f05&quot;&gt;bugs&lt;/a&gt;
upstream just few weeks ago, and we will continue to
do so. But we are not in a position to review other kernels for the same
guarantees.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Pipelining&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;We support SASL pipelining for fast connection attempts. This means, all
SASL D-Bus authentication requests can be queued up without waiting for
their replies, including any following &lt;em&gt;Hello()&lt;/em&gt; call or other D-Bus
Message.&lt;/p&gt;

    &lt;p&gt;This allows connecting to the message broker without waiting for a single
roundtrip.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;No Spec-Deviation&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;We do not intend to add features not standardized in the D-Bus
Specification, nor do we intend to deviate. However, we do sometimes
deviate from the behavior of the reference implementation. All those
deviations are carefully considered and
&lt;a href=&quot;https://github.com/bus1/dbus-broker/wiki/Deviations&quot;&gt;documented&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Our intention is to base this
implementation on the ideas described above, and thus fix some of the
fundamental issues we see in D-Bus. We report all our findings back and
recommend solutions to upstream &lt;em&gt;dbus-daemon(1)&lt;/em&gt;. Discussion and development
of the D-Bus specification still happens upstream. We are not the persons
to contact for extensions of the specification, but we will happily
collaborate on the upstream mailing-list and bug-tracker with whoever
wants to discuss D-Bus.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Runtime Broker Control&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;The message broker process provides a control API to its parent process
via a private connection. It allows to feed initial
state, but also control the broker at runtime.&lt;/p&gt;

    &lt;p&gt;While it can and is used to implement compatibility to the dbus-daemon
configuration files, it is also possible to modify the broker at runtime,
if necessary. This includes adding and removing listener sockets and
activatable names at runtime. Thus, appearance of activatable names can
now be scheduled arbitrarily.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please be aware that the &lt;em&gt;dbus-broker&lt;/em&gt; project is still experimental. While we
successfully use it on our machines to run the system and session/user bus, we
do not recommend deploying it on production machines at this time. We are
not aware of any critical bugs, but we do want more testing before recommending
its deployment.&lt;/p&gt;

&lt;p&gt;If you are curious and want to try it out, there are packages available for
Fedora and Arch Linux. Other distributions will follow. The online
documentation also contains information on how to compile and deploy it
manually.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/bus1/dbus-broker/wiki&quot;&gt;Project Wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/bus1/dbus-broker/issues&quot;&gt;Issue Tracker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Last Release: &lt;a href=&quot;https://github.com/bus1/dbus-broker/archive/v3/dbus-broker-v3.tar.gz&quot;&gt;v3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Fedora Packages in &lt;a href=&quot;https://copr.fedorainfracloud.org/coprs/g/bus1/dbus/package/dbus-broker/&quot;&gt;Copr&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Arch Linux Packages in &lt;a href=&quot;https://aur.archlinux.org/packages/dbus-broker&quot;&gt;AUR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
</entry>

<entry>
  <title>Moved Blog!</title>
  <id>https://dvdhrm.github.io/2017/07/17/welcome</id>
  <published>2017-07-17T00:00:00+00:00</published>
  <updated>2017-07-17T00:00:00+00:00</updated>
  <author><name>David Rheinsberg</name></author>
  <link href="https://dvdhrm.github.io/2017/07/17/welcome/" rel="alternate" type="text/html" title="Moved Blog!" />

  <summary type="html">&lt;p&gt;The Ponyhof blog was moved over from wordpress to here. Lets see how this will
work out!&lt;/p&gt;</summary>
  <content type="html" xml:base="https://dvdhrm.github.io/2017/07/17/welcome/">&lt;p&gt;The Ponyhof blog was moved over from wordpress to here. Lets see how this will
work out!&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/barryclark&quot;&gt;Barry Clark&lt;/a&gt; for the nice jekyll
guides and examples.&lt;/p&gt;</content>
</entry>


</feed>
