<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Home on ./concord.sh</title><link>https://concord.sh/</link><description>Recent content in Home on ./concord.sh</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 30 Jun 2021 23:10:52 -0400</lastBuildDate><atom:link href="https://concord.sh/index.xml" rel="self" type="application/rss+xml"/><item><title>Blog</title><link>https://concord.sh/blog/</link><pubDate>Sun, 17 Nov 2019 14:42:54 -0500</pubDate><guid>https://concord.sh/blog/</guid><description>&lt;p>My personal blog.&lt;/p></description><content>&lt;p>My personal blog.&lt;/p></content></item><item><title>Links</title><link>https://concord.sh/links/</link><pubDate>Wed, 30 Jun 2021 21:52:25 -0400</pubDate><guid>https://concord.sh/links/</guid><description>&lt;hr>
&lt;h2 id="madaidans-insecurities">madaidan&amp;rsquo;s Insecurities&lt;/h2>
&lt;p>&lt;a href="https://madaidans-insecurities.github.io/">https://madaidans-insecurities.github.io/&lt;/a>&lt;/p>
&lt;p>madaidan is a security researcher most known for his contributions to the
&lt;a href="https://www.whonix.org/">Whonix&lt;/a> project. He is a knowledgeable individual who
maintains an accurate and detailed collection of guides and bulletins on various
privacy and security topics on his site.&lt;/p>
&lt;h2 id="grapheneos">GrapheneOS&lt;/h2>
&lt;p>&lt;a href="https://grapheneos.org/">https://grapheneos.org/&lt;/a>&lt;/p>
&lt;p>GrapheneOS is a third-party Android operating system with a focus on privacy and
security. It employs a variety of different technologies and techniques to
strengthen defenses against exploitation, and has contributed much of this work
back upstream to the Android Open Source Project.&lt;/p></description><content>&lt;hr>
&lt;h2 id="madaidans-insecurities">madaidan&amp;rsquo;s Insecurities&lt;/h2>
&lt;p>&lt;a href="https://madaidans-insecurities.github.io/">https://madaidans-insecurities.github.io/&lt;/a>&lt;/p>
&lt;p>madaidan is a security researcher most known for his contributions to the
&lt;a href="https://www.whonix.org/">Whonix&lt;/a> project. He is a knowledgeable individual who
maintains an accurate and detailed collection of guides and bulletins on various
privacy and security topics on his site.&lt;/p>
&lt;h2 id="grapheneos">GrapheneOS&lt;/h2>
&lt;p>&lt;a href="https://grapheneos.org/">https://grapheneos.org/&lt;/a>&lt;/p>
&lt;p>GrapheneOS is a third-party Android operating system with a focus on privacy and
security. It employs a variety of different technologies and techniques to
strengthen defenses against exploitation, and has contributed much of this work
back upstream to the Android Open Source Project.&lt;/p></content></item><item><title>About</title><link>https://concord.sh/about/</link><pubDate>Sun, 17 Nov 2019 12:16:26 -0500</pubDate><guid>https://concord.sh/about/</guid><description>&lt;p>I&amp;rsquo;m 0xC0ncord, or just &amp;ldquo;Concord,&amp;rdquo; and this site is a place where I talk to
myself. I write about various information security topics. I contribute to open
source projects such as the &lt;a href="https://github.com/SELinuxProject/refpolicy">SELinux reference policy&lt;/a>
and work in systems administration professionally. This site is the work of a
personal motivation effort to share as much useful information I gather
publicly, in the hopes that it will be useful. Most of my work is generally
geared towards security research on the personal Linux desktop.&lt;/p></description><content>&lt;p>I&amp;rsquo;m 0xC0ncord, or just &amp;ldquo;Concord,&amp;rdquo; and this site is a place where I talk to
myself. I write about various information security topics. I contribute to open
source projects such as the &lt;a href="https://github.com/SELinuxProject/refpolicy">SELinux reference policy&lt;/a>
and work in systems administration professionally. This site is the work of a
personal motivation effort to share as much useful information I gather
publicly, in the hopes that it will be useful. Most of my work is generally
geared towards security research on the personal Linux desktop.&lt;/p>
&lt;p>I can be contacted on a few various platforms, namely Matrix. I am one of the
operators of a well-known &lt;a href="https://matrix.to/#/%23general:spitetech.com">Matrix room&lt;/a>,
but can also be reached &lt;a href="https://matrix.to/#/@concord:fuwafuwatime.moe">directly&lt;/a>.&lt;/p>
&lt;hr>
&lt;p>This &lt;a href="https://github.com/0xC0ncord/concord-site">site&lt;/a> and its
&lt;a href="https://github.com/0xC0ncord/concord-theme">theme&lt;/a> are open source!&lt;/p>
&lt;p>You are viewing this site at commit
&lt;a href="https://github.com/0xC0ncord/concord-site/commit/3b256f16103f61ebbd9184ff65d6c81ea48b9494">3b256f1&lt;/a>
and the theme at commit &lt;a href="https://github.com/0xC0ncord/concord-theme/commit/3eedb910bc34fd5a1eaa226fd2e820c2b89567c5">3eedb91&lt;/a>.&lt;/p></content></item><item><title>Writing a Kubernetes Operator to Fix IPv6</title><link>https://concord.sh/posts/2025/04/writing-a-kubernetes-operator-to-fix-ipv6/</link><pubDate>Sun, 27 Apr 2025 11:37:09 -0400</pubDate><guid>https://concord.sh/posts/2025/04/writing-a-kubernetes-operator-to-fix-ipv6/</guid><description>&lt;p>I have an abusive relationship with IPv6.&lt;/p>
&lt;p>Admittedly, I&amp;rsquo;m a bit of a stickler for &amp;ldquo;doing things the right way,&amp;rdquo; and part
of that includes making sure my self-hosted apps are accessible over an
IPv6-only network. In today&amp;rsquo;s age that means using dual-stack networking.&lt;/p>
&lt;p>Unfortunately, it seems most residential ISPs are not doing IPv6 &amp;ldquo;the right
way.&amp;rdquo; Or, the designers of IPv6 were a bit more&amp;hellip; &lt;del>delusional&lt;/del> hopeful let&amp;rsquo;s
say that perfect end-to-end connectivity could be a reality.&lt;/p></description><content>&lt;p>I have an abusive relationship with IPv6.&lt;/p>
&lt;p>Admittedly, I&amp;rsquo;m a bit of a stickler for &amp;ldquo;doing things the right way,&amp;rdquo; and part
of that includes making sure my self-hosted apps are accessible over an
IPv6-only network. In today&amp;rsquo;s age that means using dual-stack networking.&lt;/p>
&lt;p>Unfortunately, it seems most residential ISPs are not doing IPv6 &amp;ldquo;the right
way.&amp;rdquo; Or, the designers of IPv6 were a bit more&amp;hellip; &lt;del>delusional&lt;/del> hopeful let&amp;rsquo;s
say that perfect end-to-end connectivity could be a reality.&lt;/p>
&lt;p>What they didn&amp;rsquo;t account for was that if there was any way ISPs could screw up
that dream, then they damn well would do it. And they did.&lt;/p>
&lt;p>One of the shortcomings of IPv6 in this scenario is you would normally get a
&lt;a href="https://www.rfc-editor.org/rfc/rfc3633">delegated&lt;/a>
&lt;a href="https://www.rfc-editor.org/rfc/rfc8415%5D">prefix&lt;/a> for your internet connection,
which you would then divide into other &lt;code>/64&lt;/code> prefixes for your own use, e.g. for
VLANs. However, if your ISP changes your prefix (which, at least here in the
U.S., is pretty common for residential connections) then it could take some
fiddling to get your client machines to notice and then request a new IPv6
address, because the one they were just using is no longer in the network you&amp;rsquo;ve
been assigned. Normally this is transparent when you&amp;rsquo;re using
&lt;a href="https://www.rfc-editor.org/rfc/rfc4862">SLAAC&lt;/a>, but if your devices need to do
other special things (like have a host firewall) then your firewall rules &lt;a href="https://docs.opnsense.org/manual/aliases.html#dynamic-ipv6-host">need
to be changed&lt;/a>
as well. Additionally, using only SLAAC forfeits some of the benefits of using a
DHCPv6 server such as being able to control static addressing.&lt;/p>
&lt;p>All of this seems to point to the feeling that IPv6 was never designed to handle
the bullshittery that ISPs dish out on a regular basis (is a static IPv6 prefix
so hard? We only have like&amp;hellip; &lt;em>[checks notes]&lt;/em> 18,446,744,073,709,551,616 of
them).&lt;/p>
&lt;p>For me, this manifests as several known problems that I&amp;rsquo;m too lazy to fix, but
recently I finally had enough of one and decided to do something about it.&lt;/p>
&lt;p>On my home network, I have (among others) two separate VLANs for my &amp;ldquo;services&amp;rdquo;
network and my &amp;ldquo;users&amp;rdquo; network. The former is for my home lab and other servers
which I may or may not expose to the internet via port forwarding, and the
latter is where my desktop, laptop, and Android phone reside. Both of these
networks are using dual-stack networking.&lt;/p>
&lt;p>I&amp;rsquo;m making great use of
&lt;a href="https://kubernetes.io/docs/concepts/services-networking/network-policies/">NetworkPolicy&lt;/a>
objects in my Kubernetes cluster for security reasons, but unfortunately I would
need to manually change them to accomodate source traffic from the user network
in order for it to be allowed.&lt;/p>
&lt;p>To fix this, I wrote a Kubernetes operator of sorts that runs as a DaemonSet on
each of the nodes. It checks and monitors a config object that looks like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">apiVersion&lt;/span>: &lt;span style="color:#ae81ff">apps.fuwafuwatime.moe/v1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">kind&lt;/span>: &lt;span style="color:#ae81ff">IP6UpdateConfig&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">ip6-update-config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">delegatedPrefixLength&lt;/span>: &lt;span style="color:#ae81ff">60&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ciliumCIDRGroups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">ciliumCIDRGroupName&lt;/span>: &lt;span style="color:#ae81ff">ip6-local-lan&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">prefixIds&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, it determines what node it is running on and checks the corresponding
config for that node:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">apiVersion&lt;/span>: &lt;span style="color:#ae81ff">apps.fuwafuwatime.moe/v1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">kind&lt;/span>: &lt;span style="color:#ae81ff">IP6UpdateNodeConfig&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">ip6-update-ram&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">nodeSelector&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">kubernetes.io/hostname&lt;/span>: &lt;span style="color:#ae81ff">ram.fuwafuwatime.moe&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">interface&lt;/span>: &lt;span style="color:#ae81ff">br0&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, it checks the IPv6 address on the interface specified in that configs&amp;rsquo;s
&lt;code>spec.interface&lt;/code> and performs the bitmasking to calculate the prefixes that
would be created from that prefix according to the main config&amp;rsquo;s
&lt;code>spec.delegatedPrefixLength&lt;/code> and the listed &lt;code>spec.ciliumCIDRGroups[].prefixIds&lt;/code>.
Finally, if they differ from what is listed in the named CiliumCIDRGroup, it
will update it accordingly with the new CIDRs and post a status to the config
object:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-plain" data-lang="plain">&lt;span style="display:flex;">&lt;span>Status:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Conditions:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Last Transition Time: 2025-04-25T22:18:06Z
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Message: Updated IPv6 address in ip6-local-lan from {} to {&amp;#34;2345:0425:2ca1:1::/64&amp;#34;, &amp;#34;2345:0425:2ca1:2::/64&amp;#34;, &amp;#34;2345:0425:2ca1:0::/64&amp;#34;}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Reason: UpdateSucceeded
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Status: True
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Type: Ready
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note that the above example uses fictitious IPv6 addresses for
demonstration.&lt;/p>
&lt;p>Then, when the
&lt;a href="https://docs.cilium.io/en/latest/network/kubernetes/ciliumcidrgroup/">CiliumCIDRGroup&lt;/a>
is patched, I can just write a corresponding
&lt;a href="https://docs.cilium.io/en/latest/network/kubernetes/policy/#ciliumnetworkpolicy">CiliumNetworkPolicy&lt;/a>
referencing it. Then, whenever my prefix changes, the firewall rules update
automatically.&lt;/p>
&lt;p>The operator is written in Rust and the full source code can be found here:
&lt;a href="https://github.com/0xC0ncord/k6u">https://github.com/0xC0ncord/k6u&lt;/a>. Please
feel free to criticize my Rust skills (but be nice!) &amp;mdash; I&amp;rsquo;m still learning
after all.&lt;/p>
&lt;p>I have some other ideas for a few features I&amp;rsquo;d like to add such as only adding
CIDRs for specific &lt;a href="https://wiki.gentoo.org/wiki/IPv6_Static_Addresses_using_Tokens">IPv6 tokens&lt;/a>
rather than an entire &lt;code>/64&lt;/code>, but what I have so far is working well enough for
me for the moment. It at least allows me to not have to resort to IPv4-only or
using static addressing for accessing my self-hosted email when I&amp;rsquo;m at home
anymore.&lt;/p>
&lt;p>&amp;rsquo;til next time. See ya!&lt;/p></content></item><item><title>A Small Follow-up to UEFI Secure Boot</title><link>https://concord.sh/posts/2022/08/a-small-follow-up-to-uefi-secure-boot/</link><pubDate>Mon, 08 Aug 2022 20:11:51 -0400</pubDate><guid>https://concord.sh/posts/2022/08/a-small-follow-up-to-uefi-secure-boot/</guid><description>&lt;p>This is a follow-up post to
&lt;a href="https://concord.sh/posts/2022/08/uefi-secure-boot-the-right-way/">UEFI Secure Boot the Right Way&lt;/a>
in which I answer some questions I have received and to address some confusion
and clarify some erroneous information. Not only that, but I will share some
additional information that I found out about after publication of that post! 😃&lt;/p>
&lt;h2 id="pcr-7-and-microsofts-third-partyvendor-ca-certificate">PCR 7 and Microsoft&amp;rsquo;s Third-Party/Vendor CA Certificate&lt;/h2>
&lt;p>In my original post I expressed concern that including Microsoft&amp;rsquo;s third-party
CA could potentially downgrade security of the boot process. It turns out that
this is partially due to a misunderstanding on how PCR 7 is populated and what
actually happens when you bind some value to PCRs in the TPM.&lt;/p></description><content>&lt;p>This is a follow-up post to
&lt;a href="https://concord.sh/posts/2022/08/uefi-secure-boot-the-right-way/">UEFI Secure Boot the Right Way&lt;/a>
in which I answer some questions I have received and to address some confusion
and clarify some erroneous information. Not only that, but I will share some
additional information that I found out about after publication of that post! 😃&lt;/p>
&lt;h2 id="pcr-7-and-microsofts-third-partyvendor-ca-certificate">PCR 7 and Microsoft&amp;rsquo;s Third-Party/Vendor CA Certificate&lt;/h2>
&lt;p>In my original post I expressed concern that including Microsoft&amp;rsquo;s third-party
CA could potentially downgrade security of the boot process. It turns out that
this is partially due to a misunderstanding on how PCR 7 is populated and what
actually happens when you bind some value to PCRs in the TPM.&lt;/p>
&lt;p>As the system boots, the hashes of all executed code is measured into PCR 7.
That is, hashes of each payload are subsequently &amp;ldquo;appended&amp;rdquo; to it. The result is
that if at any point one of these payloads differs from a previous boot, (as a
result of a bootloader update, for example), then PCR 7 will differ between
those boots. When you bind a LUKS key to PCR 7, it is guaranteed that the TPM
will only reveal the key if the boot process is the same as it was when it was
sealed in the first place.&lt;/p>
&lt;p>So even if you leave Microsoft&amp;rsquo;s third-party CA certificate in the trusted
store, changing what gets executed during boot will change the value of PCR 7
and the TPM will refuse to reveal the key that was sealed. In short, my
original concerns about this are more or less moot.&lt;/p>
&lt;h2 id="microsofts-third-partyvendor-ca-certificate-may-be-required-on-some-hardware">Microsoft&amp;rsquo;s Third-Party/Vendor CA Certificate May Be Required on Some Hardware&lt;/h2>
&lt;p>This is an important piece of information I inadvertently left out. During the
hardware initialization process of booting, some devices will have option ROMs
with their own code that may need to be executed in order to initialize those
devices. The best example I can think of is NVIDIA graphics cards. More often
than not, if you install an NVIDIA GPU into your system and enable secure boot,
but neglect to install the Microsoft third-party/vendor CA certificate into the
trusted store, then the system will halt when booting because the option ROM is
not trusted by the firmware.&lt;/p>
&lt;p>I actually ran into this exact problem a few years ago with exactly the same
setup. I ended up needing to remove the GPU, disabling secure boot, then
reinstalling it and ensuring to install Microsoft&amp;rsquo;s third-party CA certificate
before enabling it again.&lt;/p>
&lt;p>&amp;hellip; Okay, I lied. I ended up RMAing the motherboard thinking I bricked it
somehow, and the vendor sent it back, unable to reproduce the problem. Only
after did I receive it did I follow the above procedure to fix the issue&amp;hellip;&lt;/p>
&lt;h2 id="can-malware-touch-secure-boot-properties-while-the-os-is-running">Can malware touch secure boot properties while the OS is running?&lt;/h2>
&lt;p>Sort of. When UEFI passes execution to the running OS, it does so by calling
the &lt;code>ExitBootServices()&lt;/code>&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> function. Part of this process involves making
most EFI variables and functions read-only or inaccessible, including protected
properties governing the operation of secure boot.&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup> Additionally, a
UEFI-compliant system&amp;rsquo;s PK (platform key) variable is made read-only as soon as
one is set. There are some other caveats around this which are far too technical
to describe here (and frankly, it&amp;rsquo;s a little too much reading even for me), but
the gist is that as long as the system firmware has implemented this process
correctly, there isn&amp;rsquo;t a concern. The secure boot variables that remain writable
within the running OS have to be authenticated, meaning that the values you put
in have to also be signed and trusted by the platform key. The only secure boot
variables with this property are the authorized device signature databases. This
is what allows things like Windows updates to add or remove trusted signatures
from the device as needed.&lt;/p>
&lt;p>So basically, as long as you trust (and/or verify!) that your motherboard is
properly UEFI-compliant, then you&amp;rsquo;re fine.&lt;/p>
&lt;h2 id="sbctl-the-secure-boot-key-manager">&lt;code>sbctl&lt;/code>, the Secure Boot Key Manager&lt;/h2>
&lt;p>Not long after the original post, I was informed about
&lt;a href="https://github.com/Foxboron/sbctl">&lt;code>sbctl&lt;/code>&lt;/a> which does most of the legwork of
the script that I had written previously. I highly recommend using it, as it
more or less completely automates the process of generating secure boot keys,
enrolling keys, and signing arbitrary EFI executables with them. It will also
take care of installing the Microsoft third-party CA certificate if needed!&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html">https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://uefi.org/specs/UEFI/2.10/32_Secure_Boot_and_Driver_Signing.html">https://uefi.org/specs/UEFI/2.10/32_Secure_Boot_and_Driver_Signing.html&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></content></item><item><title>UEFI Secure Boot the Right Way</title><link>https://concord.sh/posts/2022/08/uefi-secure-boot-the-right-way/</link><pubDate>Mon, 01 Aug 2022 17:18:34 -0400</pubDate><guid>https://concord.sh/posts/2022/08/uefi-secure-boot-the-right-way/</guid><description>&lt;p>Security around the Linux boot process is a bit of a touchy subject. In fact,
if you dig deep enough you&amp;rsquo;ll find that there are many ways to boot a Linux
system in general. There&amp;rsquo;s many different bootloaders, for example, each with
their own strengths and weaknesses. In addition, depending on the system&amp;rsquo;s or
the user&amp;rsquo;s requirements, the system may also require booting with an initramfs
or initrd. You can even boot a Linux kernel directly by taking advantage of
its &lt;code>CONFIG_EFI_STUB&lt;/code> option. While looking into the basics of securing booting
on my own machines I found that the documentation for it can sometimes be a bit
all over the place, and even then there are many guides out there that were
sometimes confusing or didn&amp;rsquo;t give the exact answers to the questions I still
had. All in all, I spent about 2 or 3 weeks really digging into it and only
afterwards did I finally come up with a solution that works well enough for me
and makes booting my various Linux machines reasonably secure.&lt;/p></description><content>&lt;p>Security around the Linux boot process is a bit of a touchy subject. In fact,
if you dig deep enough you&amp;rsquo;ll find that there are many ways to boot a Linux
system in general. There&amp;rsquo;s many different bootloaders, for example, each with
their own strengths and weaknesses. In addition, depending on the system&amp;rsquo;s or
the user&amp;rsquo;s requirements, the system may also require booting with an initramfs
or initrd. You can even boot a Linux kernel directly by taking advantage of
its &lt;code>CONFIG_EFI_STUB&lt;/code> option. While looking into the basics of securing booting
on my own machines I found that the documentation for it can sometimes be a bit
all over the place, and even then there are many guides out there that were
sometimes confusing or didn&amp;rsquo;t give the exact answers to the questions I still
had. All in all, I spent about 2 or 3 weeks really digging into it and only
afterwards did I finally come up with a solution that works well enough for me
and makes booting my various Linux machines reasonably secure.&lt;/p>
&lt;p>This post is a long-awaited one. I originally wanted to publish this a few
months ago, but systemd 251 was released which added a new feature that I
wanted to cover in addition to everything else I had compiled in. For those who
have been patiently waiting for me to finally publish this (you know who you
are), thank you.&lt;/p>
&lt;p>For the sake of brevity (even though I&amp;rsquo;ve already well-exceeded it), I will
avoid going too much into the technical details for some of the aspects and
components of the following material. I will also be skipping over some of the
alternatives and different methods of setup. The depth that I will be going into
is what I feel is relevant to gain a basic understanding of the things that you,
as a user, are setting up if you decide to do it. This is in no way intended to
be a &amp;ldquo;quick guide&amp;rdquo; or &amp;ldquo;setup for the lazy&amp;rdquo;, but that may soon follow if the
demand is high enough.&lt;/p>
&lt;h1 id="the-current-situation">The Current Situation&lt;/h1>
&lt;p>The first problem with securing the Linux boot process is that the diversity
of the many Linux distributions and how they configure the base system also
brings fragmentation around booting. This could make setting it up for yourself
difficult. Worse, most Linux distributions that do not already have UEFI secure
boot just don&amp;rsquo;t support it, and trying to set it up for yourself may result in
system instability after system upgrades. Someone who wants to proceed on such a
distribution anyway will need to ensure that they perform some extra steps after
system updates or else they may be locked out of their system on next boot or
not have a bootable system at all.&lt;/p>
&lt;p>Most Linux distributions with existing UEFI secure boot support do so by using
the GNU GRUB bootloader with a UEFI shim loader. What happens during boot is
that the system EFI firmware will execute the shim loader, which then executes
GRUB, which in turn executes the Linux kernel. The shim, when executed, will
register itself with the system EFI firmware in such a way that when the system
firmware wants to verify a signature for a to be executed EFI executable, it can
ask the shim to do so in addition to the firmware&amp;rsquo;s verification. The result is
a sort of parallel signature verification process that allows EFI executables to
have their signatures verified by both the system EFI firmware and the shim. The
primary advantage of this is that the distribution can sign their own kernels
using keys included in the shim and those signatures will be verified without
the system owner needing to load those keys into the system firmware.&lt;/p>
&lt;p>There are two problems that I (personally) have with this implementation. First,
the shim itself is signed by the Microsoft third-party key&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. The
corresponding public key is included by default in almost all system EFI
firmwares with secure boot support, and Microsoft uses this key pair to sign
other objects. What this means is that if an attacker had another object signed
with the same key pair, they could boot it on a machine with the key loaded in
the system firmware&amp;rsquo;s trusted keys database. My understanding is that this
process is supposed to be restricted to trusted hardware vendors, but it doesn&amp;rsquo;t
seem difficult to maneuver Microsoft into signing something that could
potentially have bugs, vulnerabilities, or even backdoors of its own to
compromise other machines.&lt;/p>
&lt;p>The second problem is that a vulnerability in the GRUB bootloader could
potentially allow an attacker to bypass secure boot verification and boot a
malicious Linux kernel anyway. GRUB is no stranger to major security bugs that
could compromise secure booting, but this is unfair as a simple count of bugs
isn&amp;rsquo;t the best indicator of a project&amp;rsquo;s security track record. What is
noteworthy though, is that vulnerabilities found in GRUB are generally fixed in
bulk. This is because every time a massively critical vulnerability is found,
the Linux distributions need to get their bootloaders signed by Microsoft again
which isn&amp;rsquo;t a very timely process. Because of this, many small GRUB
vulnerabilities will go unfixed for &lt;em>months&lt;/em> until GRUB does its yearly major
release. Just this past June, a major release of GRUB was announced which fixed
multiple known security issues that have been festering for over a year&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>!&lt;/p>
&lt;p>GRUB aside, another major hurdle of Linux boot security is the initrd or
initramfs if one is in use. At boot, the kernel will also unpack an initrd
into memory which contains tools and kernel modules needed to finish booting the
system. For instance, if the root filesystem resides on a filesystem like ZFS
which is not available as a built in filesystem driver, the kernel needs to load
this kernel module from the initrd at boot in order to mount it. Another case
where this is needed is if the machine is (and it should be!) using disk
encryption. The kernel alone does not know how to decrypt the disk, let alone
ask the user for a passphrase. The initrd will contain the scripts and tools
needed to get this going. The initrd is undoubtedly a security-sensitive
object. A compromised initrd can potentially contain malicious code that can
then infect the rest of the system once it is booted. Unfortunately, current
boot security mechanisms like the aforementioned EFI shim loader in combination
with GRUB do not in any way protect the initrd from being tampered with
because there is no signature verification done against the initrd.&lt;/p>
&lt;p>At this point I think it goes without saying that for proper boot security you
really really need to have an encrypted disk. An unencrypted and unverified root
filesystem really just means that an attacker with physical access can just
modify system files in order to cause the system to load malicious code. I
didn&amp;rsquo;t feel it necessary to mention it until now because I figured having an
encrypted disk is basically standard security practice by this point and it&amp;rsquo;s
not really related specifically to UEFI secure boot. But anyway, back to secure
boot&amp;hellip;&lt;/p>
&lt;h1 id="the-solution">The Solution&lt;/h1>
&lt;p>Ultimately what needs to be done is to somehow protect every sensitive component
needed during boot from tampering. The way forward to solve all of these
problems is to take advantage of systemd&amp;rsquo;s boot stub. No, not &lt;code>systemd-boot&lt;/code>.
The boot stub.&lt;/p>
&lt;p>The systemd boot stub is a small EFI executable that does nothing by itself.
But, if you use &lt;code>objcopy&lt;/code> to build a concatenated blob containing the boot stub,
a Linux kernel which has &lt;code>CONFIG_EFI_STUB&lt;/code> enabled, the initrd, the kernel&amp;rsquo;s
commandline, and a splash image, you get a single file containing all these
components that can be signed for UEFI secure boot and executed. This resulting
file is called a unified kernel image. It&amp;rsquo;s important to note that the systemd
boot stub does not actually require systemd on the system to be used. One can
easily compile the boot stub separately from the rest of systemd and copy it
over to various systems to be used. It is not even necessary to use
&lt;code>systemd-boot&lt;/code> as the bootloader, as the resulting file with all the bits
embedded inside can be used as a standalone EFI payload that can be booted
directly from the system EFI firmware.&lt;/p>
&lt;p>What we can do is generate our own signing keys for UEFI secure boot and load
them into the system firmware&amp;rsquo;s trusted signature database. Then, we can use the
systemd boot stub to create our own unified kernel image and sign them using our
generated keys. Finally, we install our unified kernel image to the &lt;code>/boot&lt;/code>
partition and either add it as an EFI payload in the system firmware or install
&lt;code>systemd-boot&lt;/code> boot it.&lt;/p>
&lt;p>Let&amp;rsquo;s take it one step at a time, starting with&amp;hellip;&lt;/p>
&lt;h2 id="generating-secure-boot-signing-keys">Generating Secure Boot Signing Keys&lt;/h2>
&lt;p>Ideally you&amp;rsquo;d do this on a separate system that is disconnected from the network
and do all of the signing on the same machine as well. That way an attacker who
gains code or command execution on the main machine cannot simply copy the UEFI
secure boot signing keys because they would not exist on the machine. However,
if you are someone like me who tends to update their kernel or initrd fairly
frequently this can be impractical. This would mean needing to update the kernel
and initrd, then copying them to the machine for signing, sign them, then
copying them back. There is definitely some security gains here to do it this
way, but I couldn&amp;rsquo;t be bothered personally. From here on I will assume you are
working on the same machine to do the key generation and signing, but if you
would like to go the extra mile, simply do these steps on your airgapped machine
and follow the procedure I described above every time you need to re-sign your
kernel and things.&lt;/p>
&lt;p>First, there&amp;rsquo;s a few packages we will need to install. These packages contain
the tools needed to later sign our kernel images. On Gentoo, we can install
these by running:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># emerge -av efitools sbsigntools
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let&amp;rsquo;s create a directory on our system where we will store our keys.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># mkdir /etc/secureboot
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># chmod &lt;span style="color:#ae81ff">0700&lt;/span> /etc/secureboot
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also set the directory&amp;rsquo;s permissions to &lt;code>0700&lt;/code> so that only the &lt;code>root&lt;/code> user
can view its contents.&lt;/p>
&lt;p>Next, let&amp;rsquo;s create the keys. There are several key pairs that need to be created
and loaded into the EFI firmware and they are all related.&lt;/p>
&lt;p>First, we will enter the directory where we will store the keys and generate a
globally unique identifier (GUID) for the machine:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># cd /etc/secureboot
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># uuidgen --random &amp;gt;guid.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we will create the platform key:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days &lt;span style="color:#ae81ff">3650&lt;/span> -subj &lt;span style="color:#e6db74">&amp;#34;/CN=Platform Key/&amp;#34;&lt;/span> -out PK.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># openssl x509 -outform DER -in PK.crt -out PK.cer
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># cert-to-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> PK.crt PK.esl
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># sign-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> -k PK.key -c PK.crt PK PK.esl PK.auth
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># sign-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> -c PK.crt -k PK.key PK /dev/null rm_PK.auth
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The argument given to the &lt;code>/CN=&lt;/code> field denotes the canonical name that will be
filled into the generated certificate. You can put pretty much whatever you want
in this field like the hostname of the machine you are generating keys for, but
I like to keep things simple.&lt;/p>
&lt;p>The platform key is stored in the UEFI &lt;code>PK&lt;/code> variable and it controls access to
that variable as well as the &lt;code>KEK&lt;/code> variable, which is where the key exchange key
will be stored.&lt;/p>
&lt;p>The above commands will have also created a file named &lt;code>rm_PK.auth&lt;/code>. This file
can be installed to the &lt;code>PK&lt;/code> variable in order to remove the platform key in the
event that it is needed.&lt;/p>
&lt;p>Next, we need to create the key exchange key.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days &lt;span style="color:#ae81ff">3650&lt;/span> -subj &lt;span style="color:#e6db74">&amp;#34;/CN=Key Exchange Key/&amp;#34;&lt;/span> -out KEK.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># openssl x509 -outform DER -in KEK.crt -out KEK.cer
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># cert-to-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> KEK.crt KEK.esl
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># sign-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> -k PK.key -c PK.crt KEK KEK.esl KEK.auth
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The key exchange key is used to update the signature database or to sign
binaries that will be trusted by the system firmware for execution.&lt;/p>
&lt;p>Finally, we will create the signature database.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days &lt;span style="color:#ae81ff">3650&lt;/span> -subj &lt;span style="color:#e6db74">&amp;#34;/CN=Signature Database Key/&amp;#34;&lt;/span> -out db.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># openssl x509 -outform DER -in db.crt -out db.cer
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># cert-to-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> db.crt db.esl
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># sign-efi-sig-list -g &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;guid.txt&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> -k KEK.key -c KEK.crt db db.esl db.auth
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The signature database is stored in the system&amp;rsquo;s &lt;code>db&lt;/code> variable and is what is
used to validate signed EFI binaries and other payloads when secure boot is
enabled.&lt;/p>
&lt;h2 id="installing-keys-and-signing-things">Installing Keys and Signing Things&lt;/h2>
&lt;p>Now that our keys are created, we can start signing objects with them. The way
to do this is via the &lt;code>sbsign&lt;/code> utility:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># sbsign &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --key /etc/secureboot/db.key \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --cert /etc/secureboot/db.crt \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --output /boot/EFI/systemd/systemd-bootx64.efi \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /boot/EFI/systemd/systemd-bootx64.efi
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above command will sign the systemd-boot bootloader and overwrite the
original file. If you wish to preserve the original, unsigned file, simply point
the &lt;code>--output&lt;/code> argument to a different location.&lt;/p>
&lt;p>In order to actually take advantage of signature verification, though, we need
to install our keys into the EFI firmware. We can do this from the running
operating system using the &lt;code>efi-updatevar&lt;/code> utility:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># efi-updatevar -f /etc/secureboot/PK.auth PK
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># efi-updatevar -f /etc/secureboot/KEK.auth KEK
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span># efi-updatevar -f /etc/secureboot/db.auth db
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If this is not an option, or you&amp;rsquo;d like to do this manually, you can instead
copy the &lt;code>*.auth&lt;/code> files to the &lt;code>/boot&lt;/code> directory or some other device that we
can read from the system firmware (usually an external FAT partition). Then,
from within the EFI firmware settings we can manually load the keys. Finally, we
can enable secure boot from within the firmware.&lt;/p>
&lt;style type="text/css">.notice{--root-color:#444;--root-background:#eff;--title-color:#fff;--title-background:#7bd;--warning-title:#c33;--warning-content:#fee;--info-title:#fb7;--info-content:#fec;--note-title:#6be;--note-content:#e7f2fa;--tip-title:#5a5;--tip-content:#efe}@media (prefers-color-scheme:dark){.notice{--root-color:#ddd;--root-background:#eff;--title-color:#fff;--title-background:#7bd;--warning-title:#800;--warning-content:#400;--info-title:#a50;--info-content:#420;--note-title:#069;--note-content:#023;--tip-title:#363;--tip-content:#121}}body.dark .notice{--root-color:#ddd;--root-background:#eff;--title-color:#fff;--title-background:#7bd;--warning-title:#800;--warning-content:#400;--info-title:#a50;--info-content:#420;--note-title:#069;--note-content:#023;--tip-title:#363;--tip-content:#121}.notice{padding:18px;line-height:24px;margin-bottom:24px;border-radius:4px;color:var(--root-color);background:var(--root-background)}.notice p:last-child{margin-bottom:0}.notice-title{margin:-18px -18px 12px;padding:4px 18px;border-radius:4px 4px 0 0;font-weight:700;color:var(--title-color);background:var(--title-background)}.notice.warning .notice-title{background:var(--warning-title)}.notice.warning{background:var(--warning-content)}.notice.info .notice-title{background:var(--info-title)}.notice.info{background:var(--info-content)}.notice.note .notice-title{background:var(--note-title)}.notice.note{background:var(--note-content)}.notice.tip .notice-title{background:var(--tip-title)}.notice.tip{background:var(--tip-content)}.icon-notice{display:inline-flex;align-self:center;margin-right:8px}.icon-notice img,.icon-notice svg{height:1em;width:1em;fill:currentColor}.icon-notice img,.icon-notice.baseline svg{top:.125em;position:relative}&lt;/style>
&lt;div>&lt;svg width="0" height="0" display="none" xmlns="http://www.w3.org/2000/svg">&lt;symbol id="tip-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"/>&lt;/symbol>&lt;symbol id="note-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>&lt;/symbol>&lt;symbol id="warning-notice" viewBox="0 0 576 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>&lt;/symbol>&lt;symbol id="info-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"/>&lt;/symbol>&lt;/svg>&lt;/div>&lt;div class="notice warning" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#warning-notice">&lt;/use>&lt;/svg>&lt;/span>Warning&lt;/p>&lt;p>If you are using a bootloader such as &lt;code>systemd-boot&lt;/code>, you will need to ensure to
sign the bootloader itself or your system won&amp;rsquo;t boot!&lt;/p>&lt;/div>
&lt;p>Either way you do this, you should ensure that you protect the firmware
settings from modification. On most motherboards this is generally just an
administrator password and admittedly could be better, but unfortunately this is
what we are stuck with. The reason you should do this is that an attacker with
physical access could simply wipe the secure boot keys or simply turn secure
boot off in order to trick the system into booting into an insecure state.&lt;/p>
&lt;h2 id="putting-it-all-together">Putting It All Together&lt;/h2>
&lt;p>Before any of what we are about to do can work, your kernel must have
&lt;code>CONFIG_EFI_STUB&lt;/code> enabled. This is needed to allow the system firmware (or
systemd&amp;rsquo;s boot stub) to pass execution directly to the kernel.&lt;/p>
&lt;p>To ensure that the initrd is protected from tampering as well as the kernel
image, we&amp;rsquo;ll need to combine the initrd and kernel into a single object for
signing. As mentioned earlier, the systemd boot stub is a small EFI executable
that can be combined with a Linux kernel, an initrd, the kernel commandline, and
a splash image in order to generate a single file that can be signed for secure
boot. For this we use &lt;code>objcopy&lt;/code> to combine the required components:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># objcopy --add-section .osrel&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/etc/os-release&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --change-section-vma .osrel=0x20000 \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .cmdline=&amp;#34;/etc/kernel/cmdline&amp;#34; \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .cmdline=0x30000 \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .splash=&amp;#34;/etc/kernel/splash.bmp&amp;#34; \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .splash=0x40000 \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .linux=&amp;#34;/boot/vmlinuz-5.15.58-gentoo&amp;#34; \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .linux=0x2000000 \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .initrd=&amp;#34;/boot/initramfs-5.15.58-gentoo&amp;#34; \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .initrd=0x4000000 \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;#34;/usr/lib/systemd/boot/efi/linuxx64.efi.stub&amp;#34; \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;#34;/boot/EFI/Linux/linux-5.15.58-gentoo.efi&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There&amp;rsquo;s a lot to unpack here in this command, but let&amp;rsquo;s go through it piece by
piece:&lt;/p>
&lt;p>We embed various components into the resulting file. These are:&lt;/p>
&lt;ul>
&lt;li>&lt;code>/etc/os-release&lt;/code> - the OS release information file&lt;/li>
&lt;li>&lt;code>/etc/kernel/cmdline&lt;/code> - a plain text file containing the kernel commandline&lt;/li>
&lt;li>&lt;code>/etc/kernel/splash.bmp&lt;/code> - a splash image in BMP format&lt;/li>
&lt;li>&lt;code>/boot/vmlinuz-5.15.58-gentoo&lt;/code> - the kernel image&lt;/li>
&lt;li>&lt;code>/boot/initramfs-5.5.15-gentoo&lt;/code> - the initrd&lt;/li>
&lt;/ul>
&lt;p>It should be noted that on Gentoo, the &lt;code>VERSION_ID&lt;/code> field in &lt;code>/etc/os-release&lt;/code>
may not exist. This field is read by &lt;code>systemd-boot&lt;/code> when populating the list of
valid bootable entries. This is not needed if you intend to boot the image
directly from firmware, but if you are using &lt;code>systemd-boot&lt;/code> you will need this
field. I have mine set to &lt;code>&amp;quot;2.8&amp;quot;&lt;/code>.&lt;/p>
&lt;p>Each argument which adds a file is separated by an argument which sets the
offset for the file to be inserted. I suggest not to change these as I&amp;rsquo;m pretty
sure they may be hard-coded but don&amp;rsquo;t quote me on that.&lt;/p>
&lt;p>Finally, near the end of the command we see the path to the systemd boot stub
and the output path to the resulting file.&lt;/p>
&lt;p>For convenience, what I have done on my systems is install the &lt;code>systemd-boot&lt;/code>
&lt;code>installkernel&lt;/code> script (&lt;code>installkernel-systemd-boot&lt;/code> on Gentoo) along with a
kernel install script hook I wrote that automates this process whenever I
rebuild the kernel:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -Eeuo pipefail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>COMMAND&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>1&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>KERNEL_VERSION&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>2&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BOOT_DIR_ABS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>3&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>KERNEL_IMAGE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>4-&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># If KERNEL_INSTALL_MACHINE_ID is defined but empty, BOOT_DIR_ABS is a fake directory.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># So, let&amp;#39;s skip creating a unified kernel image.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> ! &lt;span style="color:#f92672">[[&lt;/span> &lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_MACHINE_ID-x&lt;span style="color:#e6db74">}&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> -d &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> INITRD&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;initrd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> TARGET&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;../../EFI/Linux/linux-&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_VERSION&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">.efi&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> BOOT_DIR_ABS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/boot&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> INITRD&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;initramfs-&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_VERSION&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">.img&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> TARGET&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;linux-&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_VERSION&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">.efi&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>die&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>1&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>COMMAND&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> add&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[[&lt;/span> -f &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/../etc/secureboot/db.key &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> -f &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/../etc/secureboot/db.cer &lt;span style="color:#f92672">]]&lt;/span> &lt;span style="color:#f92672">||&lt;/span> die &lt;span style="color:#e6db74">&amp;#34;No valid keys found in /etc/secureboot!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[[&lt;/span> -f &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/../etc/kernel/cmdline &lt;span style="color:#f92672">]]&lt;/span> &lt;span style="color:#f92672">||&lt;/span> die &lt;span style="color:#e6db74">&amp;#34;Cannot proceed: No such file &amp;#39;/etc/kernel/cmdline&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[[&lt;/span> -f &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/../etc/os-release &lt;span style="color:#f92672">]]&lt;/span> &lt;span style="color:#f92672">||&lt;/span> die &lt;span style="color:#e6db74">&amp;#34;Cannot proceed: No such file &amp;#39;/etc/kernel/splash.bmp&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> args&lt;span style="color:#f92672">=(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .osrel&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/../etc/os-release&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .osrel&lt;span style="color:#f92672">=&lt;/span>0x20000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .cmdline&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/../etc/kernel/cmdline&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .cmdline&lt;span style="color:#f92672">=&lt;/span>0x30000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .splash&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/../etc/kernel/splash.bmp&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .splash&lt;span style="color:#f92672">=&lt;/span>0x40000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .linux&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/linux&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .linux&lt;span style="color:#f92672">=&lt;/span>0x2000000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> -f &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>INITRD&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Using initrd &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>INITRD&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> args&lt;span style="color:#f92672">+=(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --add-section .initrd&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>INITRD&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --change-section-vma .initrd&lt;span style="color:#f92672">=&lt;/span>0x4000000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> args&lt;span style="color:#f92672">+=(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/../usr/lib/systemd/boot/efi/linuxx64.efi.stub&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>TARGET&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Creating unified kernel image...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> objcopy &lt;span style="color:#e6db74">${&lt;/span>args[@]&lt;span style="color:#e6db74">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Signing the unified kernel image...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sbsign &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --key &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/../etc/secureboot/db.key &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --cert &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_BOOT_ROOT&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>/../etc/secureboot/db.crt &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --output &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>TARGET&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>TARGET&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Removing old loader entry...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rm -vf &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/../../loader/entries/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_INSTALL_MACHINE_ID&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>KERNEL_VERSION&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">.conf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> remove&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rm -f -- &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BOOT_DIR_ABS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>TARGET&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above script, when installed with executable permissions to
&lt;code>/etc/kernel/install.d/99-secureboot.install&lt;/code>, take care of combining all these
files together and installing them to the proper location.&lt;/p>
&lt;h2 id="going-a-step-further">Going a Step Further&lt;/h2>
&lt;p>&lt;code>systemd-cryptenroll&lt;/code> is a utility that enrolls new key slots into an existing
LUKS device. These new key slots can be handled by the &lt;code>systemd-cryptsetup&lt;/code>
tool such that the user can be prompted to decrypt the device. The advantage
of these two tools in tandem is that we can enroll key slots that require the
user to do more than just enter a passphrase to unlock the device.
&lt;code>systemd-cryptenroll&lt;/code> has support for PKCS#11-compliant security tokens, FIDO2
tokens, and TPM2 devices. The latter is what we will be focusing on here.&lt;/p>
&lt;p>At a high level we can take advantage of a TPM2 device on the system to seal the
key to decrypt the root filesystem at boot, then have &lt;code>systemd-cryptsetup&lt;/code> ask
us for a passphrase in order to ask the TPM to unseal the key. Why ask the TPM
to unseal the key? Well, this is because when we seal a key or some other secret
data in the TPM, the TPM will only unseal it if the platform configuration
registers (PCRs) match. What happens during boot is the TPM will have stored
hashes of each of the different components that were used during bootup, and if
we seal a secret in the TPM against these hashes, the TPM will only unseal the
secret if they match. What this means for us is that we can seal the disk
decryption key in the TPM against one or more TPM2 PCRs, and the system has to
be in a trusted state during boot in order for the disk to be decrypted. For me
this means that the TPM will only hand over the disk decryption key if secure
boot is enabled and all the signatures of the different payloads during boot
were successfully verified.&lt;/p>
&lt;p>&lt;code>systemd-cryptenroll&lt;/code> allows us to either add a key slot that requires a
passphrase or add a key slot that does not. The latter will allow the system to
boot without a passphrase so long the PCRs match. This is convenient in that we
can be sure that the system is in a secure state when it boots, but the risk is
that if the machine does something after booting is finished that could
potentially be compromised or used to leverage access, an attacker can do so.
A prime example of this is this lovely penetration test conducted by Dolos
Group&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>. What they found was that even though the machine they were trying to
use for attack was properly configured for secure boot, the machine would
automatically connect to the company&amp;rsquo;s internal network via an automatic VPN
connection that was established after boot. They were able to leverage this in
order to gain a foothold in the internal network even though the machine itself
was sufficiently secured. The solution? Require a PIN or passphrase to continue
booting even though the device was booted in a secure state. The takeaway is
that any potential attack surface that exists on the machine after boot cannot
be used if the attacker does not know the PIN or passphrase to complete the boot
process.&lt;/p>
&lt;p>To ensure that &lt;code>systemd-cryptenroll&lt;/code> can detect the TPM2 device, we can use:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll --tpm2-device&lt;span style="color:#f92672">=&lt;/span>list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PATH DEVICE DRIVER
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/dev/tpmrm0 IFX0785:00 tpm_tis
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will print the path to the TPM device in &lt;code>/dev&lt;/code> as well as information
about it if it is found. If you do not see a device here, make sure you actually
have a TPM2 device installed and that the kernel can load the appropriate driver
for it.&lt;/p>
&lt;p>Since we have only one TPM2 device on this system, it is safe to use
&lt;code>--tpm2-device=auto&lt;/code> when issuing commands that will work on the TPM. Otherwise,
we would need to specify the path to the TPM2 device in this argument. To enroll
a new key slot using TPM2 PCR 7, which is the PCR that stores the secure boot
state, we can use:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll --tpm2-device&lt;span style="color:#f92672">=&lt;/span>auto --tpm2-pcrs&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">7&lt;/span> /dev/nvme0n1p2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This command will ask for the current passphrase to unlock the &lt;code>/dev/nvme0n1p2&lt;/code>
LUKS partition and then enroll a new key slot against PCR 7 into it. At boot,
this partition will automatically be decrypted at boot as long as PCR 7 matches.
If, instead, we want to also enter a PIN or passphrase to unlock it in addition
to being in a secure boot state, we can use:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll --tpm2-device&lt;span style="color:#f92672">=&lt;/span>auto --tpm2-pcrs&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">7&lt;/span> --tpm2-with-pin&lt;span style="color:#f92672">=&lt;/span>true /dev/nvme0n1p2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This command is the same as the above except we add &lt;code>--tpm2-with-pin=true&lt;/code> which
tells &lt;code>systemd-cryptenroll&lt;/code> to enroll a key slot that requires both PCR 7 hashes
to match as well as for the user to enter a PIN or passphrase. When we enter
this command, it will again ask us to enter the current passphrase to unlock
&lt;code>/dev/nvme0n1p2&lt;/code> and then ask for a PIN to use for unlocking via the TPM.
Although it says PIN for this prompt (and even when unlocking), non-numeric
characters are allowed.&lt;/p>
&lt;p>We can also use other PCRs available in the TPM other than just PCR 7. The
&lt;code>systemd-cryptenroll&lt;/code> man page&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup> has a table of well-known PCRs and their
contents. For example, PCR 0 will contain a measurement of the core system
firmware executable code. So, if you wanted to ensure that the system firmware
itself was not updated or modified since enrolling, you can include it:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll --tpm2-device&lt;span style="color:#f92672">=&lt;/span>auto --tpm2-pcrs&lt;span style="color:#f92672">=&lt;/span>0,7 --tpm2-with-pin&lt;span style="color:#f92672">=&lt;/span>true /dev/nvme0n1p2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This gives an extra layer of defense in verifying that not only secure boot is
in a known good state, but also checking other components. Keep in mind that by
enabling the use of other PCRs, updating any of these components (even
legitimately) will stop the TPM from unsealing secrets sealed against these
PCRs. Windows&amp;rsquo;s BitLocker for example only uses PCR 7&lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup>, specifically to avoid
boot issues when the system owner updates the system firmware.&lt;/p>
&lt;p>At this point the next best thing to do would be to enroll a recovery key to the
partition using the &lt;code>--recovery-key&lt;/code> argument to &lt;code>systemd-cryptenroll&lt;/code> and then
securely storing it somewhere and wiping the original passphrase slot. This
would ensure that the LUKS partition can only be unlocked by using a
PIN/passphrase in conjunction with being in a secure boot state. The downside of
this is that if something were to ever go wrong with the boot process, you would
likely be locked out of the system until you have access to the recovery key.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://techcommunity.microsoft.com/t5/hardware-dev-center/updated-uefi-signing-requirements/ba-p/1062916">https://techcommunity.microsoft.com/t5/hardware-dev-center/updated-uefi-signing-requirements/ba-p/1062916&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://www.openwall.com/lists/oss-security/2022/06/07/5">https://www.openwall.com/lists/oss-security/2022/06/07/5&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>&lt;a href="https://dolosgroup.io/blog/2021/7/9/from-stolen-laptop-to-inside-the-company-network">https://dolosgroup.io/blog/2021/7/9/from-stolen-laptop-to-inside-the-company-network&lt;/a>&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>&lt;a href="https://www.freedesktop.org/software/systemd/man/systemd-cryptenroll.html#--tpm2-pcrs=PCR">https://www.freedesktop.org/software/systemd/man/systemd-cryptenroll.html#--tpm2-pcrs=PCR&lt;/a>&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>&lt;a href="https://docs.microsoft.com/en-us/windows/security/information-protection/bitlocker/bitlocker-group-policy-settings#about-the-platform-configuration-register-pcr">https://docs.microsoft.com/en-us/windows/security/information-protection/bitlocker/bitlocker-group-policy-settings#about-the-platform-configuration-register-pcr&lt;/a>&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></content></item><item><title>"Jammy Jellyfish" jammed my girlfriend's laptop</title><link>https://concord.sh/posts/2022/04/jammy-jellyfish-jammed-my-girlfriends-laptop/</link><pubDate>Thu, 28 Apr 2022 10:20:40 -0400</pubDate><guid>https://concord.sh/posts/2022/04/jammy-jellyfish-jammed-my-girlfriends-laptop/</guid><description>&lt;p>My girlfriend has been using Kubuntu 20.04 on her laptop almost since it was
released. Her intent was to become more familiar with Linux and computing in
general, which I am more than happy to help with. She was very enthusiastic from
the beginning about delving into the innards of a Linux desktop, but I didn&amp;rsquo;t
want to overwhelm her with something as technical as Gentoo just yet. So,
because of some friendly recommendations and from my own personal experience I
settled on helping her get set up with Kubuntu 20.04 Focal Fossa.&lt;/p></description><content>&lt;p>My girlfriend has been using Kubuntu 20.04 on her laptop almost since it was
released. Her intent was to become more familiar with Linux and computing in
general, which I am more than happy to help with. She was very enthusiastic from
the beginning about delving into the innards of a Linux desktop, but I didn&amp;rsquo;t
want to overwhelm her with something as technical as Gentoo just yet. So,
because of some friendly recommendations and from my own personal experience I
settled on helping her get set up with Kubuntu 20.04 Focal Fossa.&lt;/p>
&lt;p>It has been almost two years since we initially got her going. She spent a lot
of time customizing her KDE desktop just the way she liked, with a set of gaudy
icons, wallpapers, and animations that honestly were a bit out of my style. But,
nonetheless, she was happy with it and so was I. For the purposes of this post I
will forego mentioning how often I needed to remind her to update her system and
get to the point.&lt;/p>
&lt;p>About a week ago I reminded her to run the regular update mechanism via &lt;code>apt&lt;/code> on
her machine, only this time I suggested we upgrade the machine to Kubuntu 22.04
which was just freshly released. I had only heard of some minor complaints
regarding the release, mostly around the &amp;ldquo;forced&amp;rdquo; packaging of Firefox as a
snap and so I decided it was a good idea for her to do the upgrade, especially
since I was physically present. After running the appropriate &lt;code>apt&lt;/code> commands to
update the local repo metadata and upgrade the installed packages, we performed
the &lt;code>dist-upgrade&lt;/code> command and let it run. After about 20 minutes of churning
and answering some questions during the upgrade, the machine was ready to
reboot. And reboot it did.&lt;/p>
&lt;p>Immediately we were presented with a problem: her laptop was hanging at the boot
process. Not long after exiting the initramfs, several &lt;code>systemd&lt;/code> services would
fail to start including some critical ones like &lt;code>systemd-logind&lt;/code>. To cut a long
story short I spent the next hour or so troubleshooting the machine with a
LiveUSB I was carrying around but without success. It was getting late at this
point and so I went to bed with the intent of continuing in the morning.&lt;/p>
&lt;p>When I woke up, I got right to work with seeing if I could recover the machine.
I tried to see what (if any) problematic service was hanging boot, disabling
potentially unneeded services, and rebuilding the initramfs and Grub config, all
without success. I wasn&amp;rsquo;t able to spend more than maybe an hour in the morning
before leaving for work unfortunately. When I got home I went right back to
trying to fix the machine before we decided it was best to just do a clean
reinstall. For some reason, however, the installer in Kubuntu would hang too! I
was able to navigate through some of the menus up until I was supposed to select
the disk partitioning scheme, but the menu would never finish loading. I tried
this several times before just giving up.&lt;/p>
&lt;p>In the end I decided to just install Gentoo on the laptop. Unfortunately for my
girlfriend, she will need to deal with potentially long compile times and a much
steeper learning curve than we were hoping. Lucky for me though, installing
Gentoo on the machine makes me feel much more comfortable helping her with
technical issues and generally just feeling at home on her machine as if it were
my own. Plus, this alleviates the need to install it later if she ever decides
to take the next step in learning what I feel is a true Linux system.&lt;/p>
&lt;p>I don&amp;rsquo;t have any hard feelings towards Kubuntu or Ubuntu at this point, but I
have to admit that this whole ordeal did leave me and my girlfriend quite a bit
frustrated. I do get the feeling that we did something wrong during the upgrade,
but unfortunately we are beyond the point of finding out what really happened
that led to her laptop being in a broken state. Besides, in the long run I think
that shooting for the moon and installing Gentoo on the machine means my
girlfriend will be able to get a lot closer to the machine and learn the innards
a lot sooner than anticipated. Perhaps I&amp;rsquo;m getting ahead of myself though, since
she will need to get in the habit of doing routine updates first. 😜&lt;/p>
&lt;p>&amp;rsquo;til next time. See ya!&lt;/p></content></item><item><title>How not carefully reading the docs cost me a heart attack and a change of pants</title><link>https://concord.sh/posts/2022/04/how-not-carefully-reading-the-docs-cost-me-a-heart-attack-and-a-change-of-pants/</link><pubDate>Tue, 26 Apr 2022 13:29:52 -0400</pubDate><guid>https://concord.sh/posts/2022/04/how-not-carefully-reading-the-docs-cost-me-a-heart-attack-and-a-change-of-pants/</guid><description>&lt;p>A couple weeks ago I was coming into work and wanted to quickly finish up some
experimentation I was doing with regards to setting up automatic disk decryption
at boot using TPM 2.0 and LUKS. I have been using full disk encryption (FDE) for
a while now but I wanted to try out the different ways that &lt;code>systemd-cryptsetup&lt;/code>
supports unlocking the disk. Of the various methods, it seems that using a TPM
2.0 device to unlock the disk, given the validity of the system firmware and
secure boot state, was most interesting. The most desireable approach is
actually to use TPM 2.0 along with a passphrase or PIN, but &lt;a href="https://github.com/systemd/systemd/pull/22563">this
functionality&lt;/a> is not yet
available as it will be released in systemd v251.&lt;/p></description><content>&lt;p>A couple weeks ago I was coming into work and wanted to quickly finish up some
experimentation I was doing with regards to setting up automatic disk decryption
at boot using TPM 2.0 and LUKS. I have been using full disk encryption (FDE) for
a while now but I wanted to try out the different ways that &lt;code>systemd-cryptsetup&lt;/code>
supports unlocking the disk. Of the various methods, it seems that using a TPM
2.0 device to unlock the disk, given the validity of the system firmware and
secure boot state, was most interesting. The most desireable approach is
actually to use TPM 2.0 along with a passphrase or PIN, but &lt;a href="https://github.com/systemd/systemd/pull/22563">this
functionality&lt;/a> is not yet
available as it will be released in systemd v251.&lt;/p>
&lt;p>Anyways, I had previously added a slot to the TPM consisting of PCRs 0,2,4,7 and
found that the disk was not automatically unlocking. I could verify that I had
the slot added with:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll /dev/nvme0n1p2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I wanted to remove the old slot and try again, so I issued this command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll /dev/nvme0n1p2 --wipe-slot&lt;span style="color:#f92672">=&lt;/span>0,2,4,7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, I went to add a new slot but with different PCRs, so I did:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll /dev/nvme0n1p2 --tpm2-device&lt;span style="color:#f92672">=&lt;/span>auto --tpm2-pcrs&lt;span style="color:#f92672">=&lt;/span>0,7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This command prompted me for a passphrase like usual, but for some reason it
wouldn&amp;rsquo;t accept my passphrase. When I reissued a command to view the slots,
this is what I saw:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-console" data-lang="console">&lt;span style="display:flex;">&lt;span># systemd-cryptenroll /dev/nvme0n1p2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SLOT TYPE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1 tpm2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>My passphrase was gone! 😱&lt;/p>
&lt;p>At this point I was in a bit of a panic. I tried a few more times out of
insanity to try and add in the passphrase again so that I could work on my
encrypted disk, but to no avail. I started to collect myself and had a couple
realizations. First, I couldn&amp;rsquo;t think of any way to restore the passphrase into
the LUKS header of the disk without just reformatting it, and second, my disk
&lt;em>was&lt;/em> still decrypted at this point in time.&lt;/p>
&lt;p>So, while continuously being paranoid of a kernel panic or largely improbable
cosmic event knocking out my laptop and costing all my data, I continued to work
until lunch came around, at which point I went back to the house and grabbed my
SATA to USB hard drive adapter and a spare 8TB hard disk drive I had laying
around. (Okay, the drive was meant to go into my desktop as a replacement but I
have been too lazy to do it as of late.)&lt;/p>
&lt;p>I brought the two devices back to the office and continued to work until the
closing of the day. I immediately hooked up the drive to my laptop and began
copying over all my data with an &lt;code>rsync&lt;/code> command. I left my laptop at the office
that day (locked to the desk, mind you) while the backup operation ran
overnight.&lt;/p>
&lt;p>The next morning I came in to see that it had thankfully finished. With my
fingers crossed, I rebooted the laptop back into a Gentoo LiveDVD environment
and reformatted the LUKS partition with my old passphrase. Then, I began
recreating my LVM volumes on top of it and adjusting my &lt;code>/etc/fstab&lt;/code>
accordingly. After the volumes were all mounted, I ran another &lt;code>rsync&lt;/code> to begin
the restoration process and found something else to do at work while this was
running. Needless to say this also took basically the entire day, and I left my
laptop at the office for a second night while this completed.&lt;/p>
&lt;p>At the dawn of the final day, I returned to my laptop to see it had finished.
After verifying that my &lt;code>/etc/fstab&lt;/code> was correct and making the same adjustments
to the kernel commandline, I rebooted the machine and was greeted with a
pleasant TTY asking for my credentials. 👏&lt;/p>
&lt;p>The last thing I needed to do after rebooting was fix the SELinux contexts on
the machine with a simple &lt;code>rlpkg -ar&lt;/code> and manually fix the contexts on the
various mountpoints for the root inode of the volumes (sit tight for a minor
writeup on this as well).&lt;/p>
&lt;p>After all was done it was like I had never screwed up in the first place. What I
didn&amp;rsquo;t mention was that I was also researching on the side what exactly I did
wrong while the recovery was taking place. You may have already guessed it, but
my error was in thinking that the &lt;code>--wipe-slot&lt;/code> argument took PCRs to wipe and
not the slot itself. Normally when you encrypt a disk with LUKS and a
passphrase, the passphrase goes into slot 0. When issuing the above wipe
command, I ended up removing the passphrase slot entirely. If the TPM unlocking
had worked, I could in theory have not worried so much about it, however I would
not be able to update the kernel or initramfs without breaking the disk
decryption process. Additionally, I never got it to work in the first place with
those PCRs.&lt;/p>
&lt;p>I am writing this from the same laptop a couple weeks since this happened with a
fully working disk decryption with TPM 2.0 setup. It turns out that in addition
to the errors I made above, dracut currently has &lt;a href="https://github.com/dracutdevs/dracut/pull/1677">a
bug&lt;/a> that omits some of the
required libraries for systemd-cryptsetup to do its job. I had to manually
include these in my dracut config for the time being until a new version with
the fix is released. Lastly, I opted to stick with PCRs 0,7 for the time being
as this allows me to update my kernel and initramfs together without needing to
add a new slot for them every time.&lt;/p>
&lt;p>Going forward, I intend to add a recovery key to the disk in the event that
something like this happens again. That way, I should still be able to
manipulate the LUKS header in case I do something similarly silly in my
experimentation.&lt;/p>
&lt;p>Hopefully this was an interesting read and a lesson to carefully read the
corresponding documentation when working on particularly sensitive projects.&lt;/p>
&lt;p>&amp;rsquo;til next time, see ya! 👋&lt;/p></content></item><item><title>License and Copyright</title><link>https://concord.sh/license/</link><pubDate>Mon, 04 Oct 2021 13:57:30 -0400</pubDate><guid>https://concord.sh/license/</guid><description>&lt;p>Some icons are provided by &lt;a href="https://fontawesome.com">Font Awesome&lt;/a> under a
&lt;a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0 License&lt;/a>.&lt;/p>
&lt;p>The &lt;a href="https://sourceforge.net/projects/terminus-font/">Terminus&lt;/a> font is licensed
under the &lt;a href="https://spdx.org/licenses/GPL-2.0.html">GPL-2&lt;/a> and the
&lt;a href="https://spdx.org/licenses/OFL-1.1.html">OFL-1.1&lt;/a>.&lt;/p>
&lt;p>The &lt;a href="https://www.opensans.com/">OpenSans&lt;/a> font is licensed under the
&lt;a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache-2.0&lt;/a> license.&lt;/p>
&lt;p>The &lt;a href="https://github.com/martignoni/hugo-notice">hugo-notice&lt;/a> component is
licensed under the &lt;a href="https://spdx.org/licenses/GPL-3.0-or-later.html">GPL-3.0 or later&lt;/a>.&lt;/p>
&lt;p>All other content is licensed under a &lt;a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0 License&lt;/a>,
unless otherwise explicitly noted.&lt;/p></description><content>&lt;p>Some icons are provided by &lt;a href="https://fontawesome.com">Font Awesome&lt;/a> under a
&lt;a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0 License&lt;/a>.&lt;/p>
&lt;p>The &lt;a href="https://sourceforge.net/projects/terminus-font/">Terminus&lt;/a> font is licensed
under the &lt;a href="https://spdx.org/licenses/GPL-2.0.html">GPL-2&lt;/a> and the
&lt;a href="https://spdx.org/licenses/OFL-1.1.html">OFL-1.1&lt;/a>.&lt;/p>
&lt;p>The &lt;a href="https://www.opensans.com/">OpenSans&lt;/a> font is licensed under the
&lt;a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache-2.0&lt;/a> license.&lt;/p>
&lt;p>The &lt;a href="https://github.com/martignoni/hugo-notice">hugo-notice&lt;/a> component is
licensed under the &lt;a href="https://spdx.org/licenses/GPL-3.0-or-later.html">GPL-3.0 or later&lt;/a>.&lt;/p>
&lt;p>All other content is licensed under a &lt;a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0 License&lt;/a>,
unless otherwise explicitly noted.&lt;/p></content></item><item><title>Gentoo Clang Toolchain Initial Setup</title><link>https://concord.sh/posts/2021/10/gentoo-clang-toolchain-initial-setup/</link><pubDate>Sun, 03 Oct 2021 14:31:34 -0400</pubDate><guid>https://concord.sh/posts/2021/10/gentoo-clang-toolchain-initial-setup/</guid><description>&lt;p>Clang is pivoted to become the next-generation C/C++ compiler for modern systems.
It aims to provide better diagnostics, be easier to integrate with IDEs, and have a license that is more compatible with commercial products.&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
On Gentoo, Clang is already available as a compiler that can be used system-wide instead of GCC.
The primary motivation for this is to take better advantage of link-time-optimization (LTO)&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup> features.
While GCC does support LTO, it only supports &amp;ldquo;full&amp;rdquo; LTO, which may not be feasible on lower-end systems.
This is because full LTO requires merging all of the program&amp;rsquo;s input into a single module at once, which can be very demanding on systems with low memory or compute power.
Clang, on the other hand, supports &amp;ldquo;ThinLTO,&amp;rdquo;&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup> which aims to be a viable alternative to full LTO by only merging summaries of LTO bitcode at link time.
This allows for fast and efficient optimizations to be made to the program without requiring the amount of resources that full LTO otherwise would.&lt;/p></description><content>&lt;p>Clang is pivoted to become the next-generation C/C++ compiler for modern systems.
It aims to provide better diagnostics, be easier to integrate with IDEs, and have a license that is more compatible with commercial products.&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
On Gentoo, Clang is already available as a compiler that can be used system-wide instead of GCC.
The primary motivation for this is to take better advantage of link-time-optimization (LTO)&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup> features.
While GCC does support LTO, it only supports &amp;ldquo;full&amp;rdquo; LTO, which may not be feasible on lower-end systems.
This is because full LTO requires merging all of the program&amp;rsquo;s input into a single module at once, which can be very demanding on systems with low memory or compute power.
Clang, on the other hand, supports &amp;ldquo;ThinLTO,&amp;rdquo;&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup> which aims to be a viable alternative to full LTO by only merging summaries of LTO bitcode at link time.
This allows for fast and efficient optimizations to be made to the program without requiring the amount of resources that full LTO otherwise would.&lt;/p>
&lt;p>The other primary motivation for implementing this on Gentoo is to build programs with Control Flow Integrity (CFI)&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup> enabled.
CFI is a series of compile-time hardening features that can be utilized to mitigate or eliminate various code-reuse attacks, among other things.
Clang employs a variety of different CFI schemes, none of which are currently (nor are there any plans to be) supported by GCC.
We can take advantage of Clang&amp;rsquo;s CFI to further harden the system by building our programs with it, and therefore reduce attack surface and prevent potentially malicious behavior as a result of a compromise.
Lastly, CFI is available&lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup> as part of the mainline Linux kernel, although at the time of writing, it is only currently supported on ARM64 platforms.
Support for x86_64 is in the works&lt;sup id="fnref:6">&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref">6&lt;/a>&lt;/sup>, and will likely land in upstream Linux in 5.16.&lt;/p>
&lt;p>Getting started with using Clang as a system-wide compiler isn&amp;rsquo;t too difficult - it&amp;rsquo;s &lt;em>mostly&lt;/em> supported in Gentoo&lt;sup id="fnref:7">&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref">7&lt;/a>&lt;/sup>, with only a few various edge cases floating around in my personal experience.&lt;/p>
&lt;style type="text/css">.notice{--root-color:#444;--root-background:#eff;--title-color:#fff;--title-background:#7bd;--warning-title:#c33;--warning-content:#fee;--info-title:#fb7;--info-content:#fec;--note-title:#6be;--note-content:#e7f2fa;--tip-title:#5a5;--tip-content:#efe}@media (prefers-color-scheme:dark){.notice{--root-color:#ddd;--root-background:#eff;--title-color:#fff;--title-background:#7bd;--warning-title:#800;--warning-content:#400;--info-title:#a50;--info-content:#420;--note-title:#069;--note-content:#023;--tip-title:#363;--tip-content:#121}}body.dark .notice{--root-color:#ddd;--root-background:#eff;--title-color:#fff;--title-background:#7bd;--warning-title:#800;--warning-content:#400;--info-title:#a50;--info-content:#420;--note-title:#069;--note-content:#023;--tip-title:#363;--tip-content:#121}.notice{padding:18px;line-height:24px;margin-bottom:24px;border-radius:4px;color:var(--root-color);background:var(--root-background)}.notice p:last-child{margin-bottom:0}.notice-title{margin:-18px -18px 12px;padding:4px 18px;border-radius:4px 4px 0 0;font-weight:700;color:var(--title-color);background:var(--title-background)}.notice.warning .notice-title{background:var(--warning-title)}.notice.warning{background:var(--warning-content)}.notice.info .notice-title{background:var(--info-title)}.notice.info{background:var(--info-content)}.notice.note .notice-title{background:var(--note-title)}.notice.note{background:var(--note-content)}.notice.tip .notice-title{background:var(--tip-title)}.notice.tip{background:var(--tip-content)}.icon-notice{display:inline-flex;align-self:center;margin-right:8px}.icon-notice img,.icon-notice svg{height:1em;width:1em;fill:currentColor}.icon-notice img,.icon-notice.baseline svg{top:.125em;position:relative}&lt;/style>
&lt;div>&lt;svg width="0" height="0" display="none" xmlns="http://www.w3.org/2000/svg">&lt;symbol id="tip-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"/>&lt;/symbol>&lt;symbol id="note-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>&lt;/symbol>&lt;symbol id="warning-notice" viewBox="0 0 576 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>&lt;/symbol>&lt;symbol id="info-notice" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">&lt;path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"/>&lt;/symbol>&lt;/svg>&lt;/div>&lt;div class="notice warning" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#warning-notice">&lt;/use>&lt;/svg>&lt;/span>Warning&lt;/p>&lt;p>While I use Clang as a system-wide compiler on Gentoo systems in production, it is not without its problems.
First and foremost, GCC is the defacto standard compiler on Gentoo.
While Clang support does exist, it is not a high priority and as such I do not recommend removing GCC as an alternative compiler.
This is because many packages still refuse to compile (or run after being built) with Clang, although that number is shrinking.&lt;/p>
&lt;p>Additionally, for those problematic packages that do not build cleanly, there are a series of workarounds that you must employ in order to get them to build, all of which I will detail in this guide.
I do not, however, consider any of these practices recommended for use by an inexperienced Gentoo user who is afraid of potentially breaking their system.&lt;/p>&lt;/div>
&lt;p>To get started, we need to initially build the entire Clang/LLVM toolchain using GCC.
I find it is much easier to create a package set so that we can emerge the set as opposed to each package individually.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/sets/llvm-toolchain&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-devel/llvm&lt;span style="color:#f92672">[&lt;/span>abi_x86_32,gold&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-devel/clang&lt;span style="color:#f92672">[&lt;/span>abi_x86_32,default-compiler-rt,default-libcxx,default-lld,static-analyzer&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-devel/lld
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-devel/clang-runtime&lt;span style="color:#f92672">[&lt;/span>abi_x86_32,compiler-rt,libcxx,sanitize&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-libs/compiler-rt&lt;span style="color:#f92672">[&lt;/span>clang&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-libs/compiler-rt-sanitizers&lt;span style="color:#f92672">[&lt;/span>clang,asan,cfi,dfsan,gwp-asan,hwasan,libfuzzer,lsan,memprof,msan,profile,safestack,scudo,tsan,ubsan,xray&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-libs/libcxx&lt;span style="color:#f92672">[&lt;/span>abi_x86_32,libunwind,static-libs&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-libs/libcxxabi&lt;span style="color:#f92672">[&lt;/span>abi_x86_32,libunwind,static-libs&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-libs/libunwind&lt;span style="color:#f92672">[&lt;/span>abi_x86_32,static-libs&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="notice note" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#note-notice">&lt;/use>&lt;/svg>&lt;/span>Note&lt;/p>&lt;p>The text inside square brackets ([]) next to each package name denotes USE flags required in this set.
&lt;code>abi_x86_32&lt;/code> is the USE flag to enable 32-bit support if you intend on using Clang to build 32-bit packages.
If you do not need this, remove the &lt;code>abi_x86_32&lt;/code> USE flag.&lt;/p>&lt;/div>
&lt;div class="notice note" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#note-notice">&lt;/use>&lt;/svg>&lt;/span>Note&lt;/p>&lt;p>The &lt;code>compiler-rt&lt;/code> and &lt;code>compiler-rt-sanitizers&lt;/code> packages and USE flags allow Clang to use its own static analyzer when performing compile-time sanitization.
The &lt;code>libcxx&lt;/code> and &lt;code>libcxxabi&lt;/code> packages and USE flags allow Clang to use &lt;code>libc++&lt;/code> as the default C++ standard library instead of GCC&amp;rsquo;s &lt;code>stdlibc++&lt;/code>.
We will need these if you want to set up CFI support later, but they are otherwise optional.&lt;/p>
&lt;p>It should be noted that switching between &lt;code>libc++&lt;/code> and &lt;code>stdlibc++&lt;/code> should not be taken lightly, as they are not ABI-compatible. However, some packages (namely Chromium) refuse to build with CFI unless its dependencies are built with &lt;code>libc++&lt;/code>.&lt;/p>&lt;/div>
&lt;div class="notice note" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#note-notice">&lt;/use>&lt;/svg>&lt;/span>Note&lt;/p>&lt;p>&lt;code>llvm-libunwind&lt;/code> is the better option over &lt;code>libunwind&lt;/code>.
However, there are several packages that still hard-depend on &lt;code>libunwind&lt;/code> as opposed to offerring &lt;code>llvm-libunwind&lt;/code> as an alternative, namely &lt;a href="https://bugs.gentoo.org/791349">Samba&lt;/a>.
If you do not use any of these problematic packages, you are encouraged to use &lt;code>llvm-libunwind&lt;/code> instead and enable the corresponding USE flags.&lt;/p>&lt;/div>
&lt;p>After that, enable the USE flags in this set, either globally or on a per-package basis.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/make.conf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>USE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm clang gold libcxx libcxxabi
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> default-libcxx compiler-rt
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> default-compiler-rt default-lld libunwind&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, we can emerge the set.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>emerge -av @llvm-toolchain
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Before we begin using it, the Clang toolchain needs to be bootstrapped, or in other words, rebuilt using Clang itself.
We need to set Clang and the LLVM tools as the defaults for the system.
Additionally, we should start enabling the relevant &lt;code>CFLAGS&lt;/code> and &lt;code>CXXFLAGS&lt;/code>.
It is imperative that we enable LTO now if we intend to use it, as Clang or LLVM may emit spurious errors when building LTO-enabled packages when they themselves are not built with LTO (also, we get a nice performance boost to compilation).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/make.conf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Use clang instead of gcc&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CC&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;clang&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXX&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;clang++&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LD&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ld.lld&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Use the proper tools capable of dealing with LLVM bitcode&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>AR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-ar&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NM&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-nm&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>RANLIB&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-ranlib&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRIP&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-strip&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJDUMP&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-objdump&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJCOPY&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-objcopy&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJSIZE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-objsize&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRINGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-strings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>READELF&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;llvm-readelf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Standard flags that normally don&amp;#39;t cause problems&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>COMMON_FLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-march=native -mtune=native -O3 -pipe -fomit-frame-pointer&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Flags for compile-time hardening&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>HARDENED_FLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>COMMON_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fstack-clash-protection&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># LTO flags. We use LTO_FLAGS_THIN here but we declare LTO_FLAGS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># with full LTO as it will be easier to switch to later&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LTO_FLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-flto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LTO_FLAGS_THIN&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-flto=thin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS_THIN&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Use libc++ as the standard C++ library&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXXFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS_THIN&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -stdlib=libc++&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Hardened LDFLAGS and use lld as the default linker&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LDFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-Wl,-O1 -Wl,--as-needed -Wl,-S -Wl,-z,now -Wl,-z,relro -fuse-ld=lld -Wl,-unwindlib=libunwind&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="notice note" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#note-notice">&lt;/use>&lt;/svg>&lt;/span>Note&lt;/p>&lt;p>If you do not intend to use &lt;code>libc++&lt;/code> as the standard C++ library, omit the corresponding argument from &lt;code>CXXFLAGS&lt;/code>.&lt;/p>&lt;/div>
&lt;p>After that, rebuild your toolchain.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>emerge -av @llvm-toolchain
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>At this point you should now have a functioning Clang toolchain.
But, we need to set up our environment to work around various problematic packages.
To do this, we create package env files in &lt;code>/etc/portage/env&lt;/code> with various flags that override our defaults in &lt;code>make.conf&lt;/code>.
Then, we can tell Portage to use these overrides in &lt;code>/etc/portage/package.env&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/env/compiler-gcc&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CC&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;gcc&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXX&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;g++&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>AR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ar&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NM&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;nm&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>RANLIB&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ranlib&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRIP&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;strip&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJDUMP&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;objdump&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJCOPY&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;objcopy&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJSIZE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;objsize&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRINGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;strings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>READELF&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;readelf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXXFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -nostdinc++ -I/usr/include/c++/v1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>FCFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>FFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LDFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-Wl,-O1 -Wl,--as-needed -Wl,-S -Wl,-z,now -Wl,-z,relro -fuse-ld=lld -nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This env file overrides various flags in &lt;code>make.conf&lt;/code> when building a package.
To apply this to a package, we provide it in an entry in &lt;code>/etc/portage/package.env&lt;/code> like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/package.env/podman&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>app-emulation/podman compiler-gcc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above env file tells Portage to use GCC as the compiler, but still using &lt;code>lld&lt;/code> as the linker and &lt;code>libc++&lt;/code> as the standard C++ library.
Not all packages can be built this way, so we simply narrow down the flags closer to the Gentoo defaults until it builds.
This is usually a series of trial and error steps, but in my experience I have only found a small handful of packages that can only be built with the defaults.&lt;/p>
&lt;div class="notice tip" >
&lt;p class="first notice-title">&lt;span class="icon-notice baseline">&lt;svg>&lt;use href="#tip-notice">&lt;/use>&lt;/svg>&lt;/span>Tip&lt;/p>&lt;p>You can stack env flags on a package by declaring more than one in &lt;code>/etc/portage/package.env&lt;/code>.
When this is done, the flags will be applied in order from left to right.
You can use this to your advantage by keeping your env files slim and only containing the flags for a specific purpose.&lt;/p>&lt;/div>
&lt;p>What follows are additional env files I use that can help with this entire procedure.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/env/linker-gold&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This env tells Portage to use the `gold` linker.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># While `gold` is technically deprecated, it is still&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># functional and supports LTO, unlike the `bfd` linker&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># which is the Gentoo default.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LD&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ld.gold&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LDFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LDFLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -fuse-ld=gold&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/env/no-lto&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This env disables LTO completely for the package.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Some packages simply refuse to build with LTO.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>CFLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -fno-lto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXXFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>CXXFLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -fno-lto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/env/linker-bfd&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This env tells Portage to use the `bfd` linker.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LD&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ld.bfd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LDFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LDFLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -fuse-ld=bfd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/env/with-lomp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This tells Portage to explicitly link the package&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># with `libomp`.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># For some reason, some packages do not declare all&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># required shared objects during the link phase when&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># built with Clang, even though they compile fine&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># otherwise (Audacity is one of these).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># If you get any compilation errors that say things&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># like &amp;#34;unresolved symbol&amp;#34;, try identifying what&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># shared object provides that symbol and link to it&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># explicitly like above. Some other libraries I have&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># seen affected by this include `libm`, `libz`, and&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># `libdl`, but these are usually rare.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>CFLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -lomp&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXXFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>CXXFLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> -lomp&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/portage/env/compiler-gcc-libstdc++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Use GCC as the compiler with `libstdc++` as the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># standard C++ library. There isn&amp;#39;t really an easy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># way to explicitly specify the standard C++ library&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># with GCC like you can with Clang&amp;#39;s `-stdlib=`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># argument, so unfortuantely we have to declare&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># these flags in combination with setting GCC.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CC&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;gcc&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXX&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;g++&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>AR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ar&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NM&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;nm&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>RANLIB&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ranlib&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRIP&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;strip&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJDUMP&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;objdump&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJCOPY&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;objcopy&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OBJSIZE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;objsize&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRINGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;strings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>READELF&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;readelf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CXXFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>HARDENED_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>LTO_FLAGS&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LDFLAGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-Wl,-O1 -Wl,--as-needed -Wl,-S -Wl,-z,now -Wl,-z,relro -fuse-ld=gold&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Whenever troubleshooting a problematic package, I usually follow this order of flags, adding on additional ones until the package builds.&lt;/p>
&lt;ol>
&lt;li>Disable LTO.&lt;/li>
&lt;li>Use GCC as the compiler.&lt;/li>
&lt;li>Use &lt;code>gold&lt;/code> as the linker.&lt;/li>
&lt;li>Use GCC as the compiler and &lt;code>libstdc++&lt;/code> as the standard C++ library.&lt;/li>
&lt;li>Use &lt;code>bfd&lt;/code> as the linker.&lt;/li>
&lt;/ol>
&lt;p>In the next part of this series of guides we will move into building packages with CFI, and then finally I will detail my process for building Ungoogled Chromium with CFI as well.&lt;/p>
&lt;p>See you next time!&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://clang.llvm.org/">https://clang.llvm.org/&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://www.llvm.org/docs/LinkTimeOptimization.html">https://www.llvm.org/docs/LinkTimeOptimization.html&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>&lt;a href="https://clang.llvm.org/docs/ThinLTO.html">https://clang.llvm.org/docs/ThinLTO.html&lt;/a>&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>&lt;a href="https://clang.llvm.org/docs/ControlFlowIntegrity.html">https://clang.llvm.org/docs/ControlFlowIntegrity.html&lt;/a>&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>&lt;a href="http://lkml.iu.edu/hypermail/linux/kernel/2104.3/01746.html">http://lkml.iu.edu/hypermail/linux/kernel/2104.3/01746.html&lt;/a>&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:6">
&lt;p>&lt;a href="https://github.com/samitolvanen/linux/tree/clang-cfi">https://github.com/samitolvanen/linux/tree/clang-cfi&lt;/a>&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:7">
&lt;p>&lt;a href="https://wiki.gentoo.org/wiki/Clang">https://wiki.gentoo.org/wiki/Clang&lt;/a>&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></content></item><item><title>Nextcloud cron with SELinux</title><link>https://concord.sh/posts/2020/10/nextcloud-cron-with-selinux/</link><pubDate>Sat, 24 Oct 2020 13:10:00 -0400</pubDate><guid>https://concord.sh/posts/2020/10/nextcloud-cron-with-selinux/</guid><description>&lt;p>If you run your own Nextcloud instance, one of the things you will need to do when finalizing setup is to configure Nextcloud&amp;rsquo;s &lt;a href="https://docs.nextcloud.com/server/20/admin_manual/configuration_server/background_jobs_configuration.html">internal cron service&lt;/a>.&lt;/p>
&lt;p>The default and least reliable option is AJAX, which will run the cron service each time a Nextcloud page is requested. The immediate problem here is that if your Nextcloud instance does not have much continuous usage (like mine), especially from a web browser, the cron service will not run as often as it needs to.&lt;/p></description><content>&lt;p>If you run your own Nextcloud instance, one of the things you will need to do when finalizing setup is to configure Nextcloud&amp;rsquo;s &lt;a href="https://docs.nextcloud.com/server/20/admin_manual/configuration_server/background_jobs_configuration.html">internal cron service&lt;/a>.&lt;/p>
&lt;p>The default and least reliable option is AJAX, which will run the cron service each time a Nextcloud page is requested. The immediate problem here is that if your Nextcloud instance does not have much continuous usage (like mine), especially from a web browser, the cron service will not run as often as it needs to.&lt;/p>
&lt;p>The recommended option is system cron, which requires setting up a system cronjob like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>*/5 * * * * nginx php -f /var/www/nextcloud/htdocs/cron.php
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This cronjob will call the &lt;code>cron.php&lt;/code> service directly running under the &lt;code>nginx&lt;/code> user. On typical systems this is fine, but if you are using SELinux then you will notice some problems like the following:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-plain" data-lang="plain">&lt;span style="display:flex;">&lt;span>node=megumin type=AVC msg=audit(1603560001.338:3684): avc: denied { execmem } for pid=30481 comm=&amp;#34;php&amp;#34; scontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tcontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tclass=process permissive=1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node=megumin type=AVC msg=audit(1603560001.338:3684): avc: denied { execstack } for pid=30481 comm=&amp;#34;php&amp;#34; scontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tcontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tclass=process permissive=1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>What&amp;rsquo;s happening here is the cron service is running under the system cron context, which does not have permissions to execute writable memory, which is required for PHP to work.&lt;/p>
&lt;p>These are two very sensitive and potentially dangerous permissions, so if you are like me, you may not want to simply grant these permissions to the system cron context. Instead, you think to try and create a stub script in order to set up a process transition like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/sh
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>php -f /var/www/nextcloud/htdocs/cron.php
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-plain" data-lang="plain">&lt;span style="display:flex;">&lt;span>type phpfpm_cron_exec_t;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>application_executable_file(phpfpm_cron_exec_t)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cron_system_entry(phpfpm_t, phpfpm_cron_exec_t)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we can label our script as &lt;code>phpfpm_cron_exec_t&lt;/code>, make it executable, and tell our cronjob to execute this file.&lt;/p>
&lt;p>But now we have new problems:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-plain" data-lang="plain">&lt;span style="display:flex;">&lt;span>node=megumin type=AVC msg=audit(1603558690.194:3611): avc: denied { map } for pid=27906 comm=&amp;#34;sh&amp;#34; path=&amp;#34;/bin/bash&amp;#34; dev=&amp;#34;sda4&amp;#34; ino=13238332 scontext=system_u:system_r:phpfpm_t:s0 tcontext=system_u:object_r:shell_exec_t:s0 tclass=file permissive=1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node=megumin type=AVC msg=audit(1603558690.194:3611): avc: denied { execute_no_trans } for pid=27906 comm=&amp;#34;php-fpm&amp;#34; path=&amp;#34;/bin/bash&amp;#34; dev=&amp;#34;sda4&amp;#34; ino=13238332 scontext=system_u:system_r:phpfpm_t:s0 tcontext=system_u:object_r:shell_exec_t:s0 tclass=file permissive=1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node=megumin type=AVC msg=audit(1603558690.194:3611): avc: denied { read open } for pid=27906 comm=&amp;#34;php-fpm&amp;#34; path=&amp;#34;/bin/bash&amp;#34; dev=&amp;#34;sda4&amp;#34; ino=13238332 scontext=system_u:system_r:phpfpm_t:s0 tcontext=system_u:object_r:shell_exec_t:s0 tclass=file permissive=1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node=megumin type=AVC msg=audit(1603558690.194:3611): avc: denied { execute } for pid=27906 comm=&amp;#34;php-fpm&amp;#34; name=&amp;#34;bash&amp;#34; dev=&amp;#34;sda4&amp;#34; ino=13238332 scontext=system_u:system_r:phpfpm_t:s0 tcontext=system_u:object_r:shell_exec_t:s0 tclass=file permissive=1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>phpfpm_t&lt;/code> type does not have the permissions needed to run a shell and execute the &lt;code>php&lt;/code> binary.&lt;/p>
&lt;p>So that takes us back to square one. Let&amp;rsquo;s take another look at our options again. We also have the option of using a Webcron service. It took me a minute to figure this out since I had never heard of it before, but essentially you can use a third-party service which will send HTTP GET requests (or whatever you configure) to endpoints on your webserver, which will trigger PHP to do something on the backend. After realizing what this could do for us, I came up with the following solution.&lt;/p>
&lt;p>We can use the Webcron service and simply &lt;code>curl&lt;/code> our &lt;code>cron.php&lt;/code> internally using the system cron. Easy!&lt;/p>
&lt;p>So we create a cronjob like so:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>*/5 * * * * root curl https://nextcloud.example.com/cron.php &amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then we tell Nextcloud that we are using a Webcron. That&amp;rsquo;s it!&lt;/p>
&lt;p>Additionally, you could even restrict the cron service endpoint to the local host or network only. To do this, you can insert this block into your Nextcloud&amp;rsquo;s server definition in Nginx:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">location&lt;/span> = &lt;span style="color:#e6db74">/cron.php&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">allow&lt;/span> &lt;span style="color:#ae81ff">127&lt;/span>&lt;span style="color:#e6db74">.0.0.1/32&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">deny&lt;/span> &lt;span style="color:#e6db74">all&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, we have Nextcloud&amp;rsquo;s cron service set up, fully working, and playing nice with SELinux.&lt;/p></content></item><item><title>Wrong run_init Authentication</title><link>https://concord.sh/posts/2020/09/wrong-run_init-authentication/</link><pubDate>Tue, 22 Sep 2020 15:11:42 -0400</pubDate><guid>https://concord.sh/posts/2020/09/wrong-run_init-authentication/</guid><description>&lt;p>Today I noticed that for some reason on one of my Gentoo boxes, I needed to authenticate as root in order to start and stop services, when on my other boxes I would authenticate as my currently logged in user. Normally I like to run &lt;code>sudo -i&lt;/code> or &lt;code>sudo -s&lt;/code> in order to run multiple tasks in the same session, and this was never previously a problem until I recently locked down the root account such that I could no longer enter its password (it no longer had one).&lt;/p></description><content>&lt;p>Today I noticed that for some reason on one of my Gentoo boxes, I needed to authenticate as root in order to start and stop services, when on my other boxes I would authenticate as my currently logged in user. Normally I like to run &lt;code>sudo -i&lt;/code> or &lt;code>sudo -s&lt;/code> in order to run multiple tasks in the same session, and this was never previously a problem until I recently locked down the root account such that I could no longer enter its password (it no longer had one).&lt;/p>
&lt;p>On Gentoo at least, when you need to execute some action on some service, the usage of &lt;code>run_init&lt;/code> is required. The purpose of this utility is to change SELinux contexts from a user context to a system context for the purpose of running some action on some service. The reason for this is that doing this requires a change to the SELinux system user, role, and type, a highly privileged action. You can read more about this &lt;a href="https://wiki.gentoo.org/wiki/SELinux/Tutorials/Linux_services_and_the_system_u_SELinux_user">here&lt;/a>. With this in mind, I started digging through my SELinux configuration, looking for anything out of the ordinary. Everything was in place. My SELinux login mapping was correct and I had access to all the correct roles. Then, I started looking through PAM. &lt;code>run_init&lt;/code> is configured to authenticate through PAM using the configuration in &lt;code>/etc/pam.d/run_init&lt;/code> which had no differences between both of my systems. Also checking &lt;code>/etc/pam.d/system-auth&lt;/code> turned up no differences.&lt;/p>
&lt;p>At this point I was beginning to pull my hair out a little, and went down the path of running &lt;code>strace&lt;/code> against &lt;code>run_init&lt;/code> to see what exactly was going on. I noticed that on the system where &lt;code>run_init&lt;/code> was working as I was expecting, by asking me for my credentials instead of root&amp;rsquo;s, &lt;code>run_init&lt;/code> was reading the contents of &lt;code>/proc/self/loginuid&lt;/code>, and the other system was not. Immediately after this file was read, PAM was invoked using the UID present in this file. That&amp;rsquo;s when I had a vague realization of what was happening.&lt;/p>
&lt;p>I did a quick search for what package was providing the &lt;code>run_init&lt;/code> binary and thought to check its USE flags.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># equery b `which run_init`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * Searching &lt;span style="color:#66d9ef">for&lt;/span> /usr/sbin/run_init ...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sys-apps/policycoreutils-3.1 &lt;span style="color:#f92672">(&lt;/span>/usr/sbin/run_init&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># equery u policycoreutils&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> Legend : U - final flag setting &lt;span style="color:#66d9ef">for&lt;/span> installation&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> : I - package is installed with flag &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> Colors : set, unset &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> * Found these USE flags &lt;span style="color:#66d9ef">for&lt;/span> sys-apps/policycoreutils-3.1:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> U I
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - - audit : Enable support &lt;span style="color:#66d9ef">for&lt;/span> sys-process/audit and use the audit_* functions &lt;span style="color:#f92672">(&lt;/span>like audit_getuid instead of
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> getuid&lt;span style="color:#f92672">())&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - - dbus : Enable dbus support &lt;span style="color:#66d9ef">for&lt;/span> anything that needs it &lt;span style="color:#f92672">(&lt;/span>gpsd, gnomemeeting, etc&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> + + pam : Add support &lt;span style="color:#66d9ef">for&lt;/span> PAM &lt;span style="color:#f92672">(&lt;/span>Pluggable Authentication Modules&lt;span style="color:#f92672">)&lt;/span> - DANGEROUS to arbitrarily flip
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - - python_targets_python3_6 : Build with Python 3.6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> + + python_targets_python3_7 : Build with Python 3.7
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ah ha! Sure enough, on the system where my user was being authenticated, the &lt;code>audit&lt;/code> USE flag was set, and here it wasn&amp;rsquo;t. A quick flip of this flag and a rebuild of &lt;code>policycoreutils&lt;/code> fixed the problem.&lt;/p>
&lt;p>This was a little bit of an oddity at first. I feel like this functionality should be separated from the &lt;code>audit&lt;/code> USE flag in some way, as it looks like &lt;code>run_init&lt;/code> checks what user is invoking some action in order to log it, but this information is also passed along to PAM. Without this check, &lt;code>run_init&lt;/code> seems to assume that the root user is the one performing the action and does not authenticate the actual user against PAM. In any case, this simple change implemented the exact behavior I was looking for.&lt;/p></content></item><item><title>Quick Word on Gitea Dump</title><link>https://concord.sh/posts/2020/07/quick-word-on-gitea-dump/</link><pubDate>Sat, 18 Jul 2020 22:04:15 -0400</pubDate><guid>https://concord.sh/posts/2020/07/quick-word-on-gitea-dump/</guid><description>&lt;p>Only today did I notice that my Gitea instance was unable to create new repositories. A furious search turned up &lt;a href="https://github.com/go-gitea/gitea/issues/4407">this issue&lt;/a> regarding the issue. &lt;a href="https://github.com/go-gitea/gitea/issues/4407#issuecomment-469031232">This comment&lt;/a> explains it in more detail. The fix is to run this on the Gitea database:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.access_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#66d9ef">access&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.access_token_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.access_token;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.action_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.action;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.attachment_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.attachment;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.collaboration_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.collaboration;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.comment_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#66d9ef">comment&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.commit_status_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.commit_status;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.deleted_branch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.deleted_branch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.deploy_key_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.deploy_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.email_address_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.email_address;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.follow_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.follow;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.gpg_key_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.gpg_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.hook_task_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.hook_task;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_assignees_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_assignees;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_dependency_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_dependency;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_label_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_label;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_user;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_watch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_watch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.label_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.label;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.lfs_lock_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.lfs_lock;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.lfs_meta_object_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.lfs_meta_object;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.login_source_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.login_source;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.milestone_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.milestone;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.mirror_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.mirror;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.notice_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.notice;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.notification_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.notification;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.org_user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.org_user;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.protected_branch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.protected_branch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.public_key_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.public_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.pull_request_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.pull_request;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.reaction_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.reaction;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.release_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.release;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repo_indexer_status_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repo_indexer_status;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repo_redirect_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repo_redirect;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repo_unit_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repo_unit;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repository_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repository;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.review_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.review;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.star_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.star;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.stopwatch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.stopwatch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_repo_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team_repo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_unit_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team_unit;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team_user;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.topic_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.topic;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.tracked_time_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.tracked_time;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.two_factor_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.two_factor;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.u2f_registration_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.u2f_registration;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.upload_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.upload;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#e6db74">&amp;#34;user&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.user_open_id_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.user_open_id;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.version_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#66d9ef">version&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.watch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.watch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.webhook_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.webhook;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description><content>&lt;p>Only today did I notice that my Gitea instance was unable to create new repositories. A furious search turned up &lt;a href="https://github.com/go-gitea/gitea/issues/4407">this issue&lt;/a> regarding the issue. &lt;a href="https://github.com/go-gitea/gitea/issues/4407#issuecomment-469031232">This comment&lt;/a> explains it in more detail. The fix is to run this on the Gitea database:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.access_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#66d9ef">access&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.access_token_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.access_token;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.action_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.action;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.attachment_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.attachment;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.collaboration_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.collaboration;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.comment_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#66d9ef">comment&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.commit_status_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.commit_status;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.deleted_branch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.deleted_branch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.deploy_key_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.deploy_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.email_address_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.email_address;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.follow_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.follow;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.gpg_key_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.gpg_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.hook_task_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.hook_task;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_assignees_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_assignees;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_dependency_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_dependency;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_label_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_label;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_user;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.issue_watch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.issue_watch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.label_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.label;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.lfs_lock_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.lfs_lock;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.lfs_meta_object_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.lfs_meta_object;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.login_source_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.login_source;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.milestone_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.milestone;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.mirror_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.mirror;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.notice_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.notice;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.notification_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.notification;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.org_user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.org_user;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.protected_branch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.protected_branch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.public_key_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.public_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.pull_request_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.pull_request;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.reaction_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.reaction;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.release_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.release;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repo_indexer_status_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repo_indexer_status;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repo_redirect_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repo_redirect;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repo_unit_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repo_unit;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.repository_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.repository;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.review_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.review;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.star_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.star;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.stopwatch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.stopwatch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_repo_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team_repo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_unit_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team_unit;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.team_user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.team_user;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.topic_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.topic;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.tracked_time_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.tracked_time;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.two_factor_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.two_factor;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.u2f_registration_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.u2f_registration;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.upload_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.upload;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.user_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#e6db74">&amp;#34;user&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.user_open_id_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.user_open_id;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.version_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.&lt;span style="color:#66d9ef">version&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.watch_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.watch;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> SETVAL(&lt;span style="color:#e6db74">&amp;#39;public.webhook_id_seq&amp;#39;&lt;/span>, COALESCE(&lt;span style="color:#66d9ef">MAX&lt;/span>(id), &lt;span style="color:#ae81ff">1&lt;/span>) ) &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span>.webhook;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></content></item><item><title>Welcome</title><link>https://concord.sh/posts/2020/07/welcome/</link><pubDate>Sat, 18 Jul 2020 18:37:00 -0400</pubDate><guid>https://concord.sh/posts/2020/07/welcome/</guid><description>&lt;p>And so as of the time of writing this, my blog is now officially live. I am still adding content to my other pages and will soon add a &lt;a href="https://concord.sh/links/">links&lt;/a> page, but for now I leave any readers with this notice and a wide future of upcoming content. I also anticipate uploading the full source of the site to a public Git repository.&lt;/p>
&lt;p>Until next time, see ya.&lt;/p></description><content>&lt;p>And so as of the time of writing this, my blog is now officially live. I am still adding content to my other pages and will soon add a &lt;a href="https://concord.sh/links/">links&lt;/a> page, but for now I leave any readers with this notice and a wide future of upcoming content. I also anticipate uploading the full source of the site to a public Git repository.&lt;/p>
&lt;p>Until next time, see ya.&lt;/p></content></item></channel></rss>