<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Jacob Garber</title>
    <link rel="self" type="application/atom+xml" href="https://www.jwgarber.ca/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.jwgarber.ca"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-07-03T00:00:00+00:00</updated>
    <id>https://www.jwgarber.ca/atom.xml</id>
    <entry xml:lang="en">
        <title>Bootstrapping a Highly Available Container Registry</title>
        <published>2025-07-03T00:00:00+00:00</published>
        <updated>2025-07-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/bootstrapping-a-highly-available-container-registry/"/>
        <id>https://www.jwgarber.ca/blog/bootstrapping-a-highly-available-container-registry/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/bootstrapping-a-highly-available-container-registry/">&lt;p&gt;Deploying a bare-metal Kubernetes cluster is very much a build-your-own adventure: kubeadm will create a cluster for you, but fundamental building blocks like the load-balancer, persistent storage, and ingress you need to setup yourself. In addition, what if you are running in an air-gapped environment? No incoming or outgoing internet connections, at best you get to SSH in.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Since you can&#x27;t access DockerHub or Quay, you need to setup a registry somewhere locally. Furthermore, this registry needs to be highly-available, but since we are bootstrapping a cluster we can&#x27;t take advantage of any of the HA machinery that Kubernetes gives us since it doesn&#x27;t exist yet (sorry &lt;a href=&quot;https:&#x2F;&#x2F;goharbor.io&#x2F;docs&#x2F;2.13.0&#x2F;install-config&#x2F;harbor-ha-helm&#x2F;&quot;&gt;Harbor&lt;&#x2F;a&gt;). It took me a fair bit of head-scratching to figure out how to solve this.&lt;&#x2F;p&gt;
&lt;p&gt;To set the stage, let&#x27;s say you are deploying onto three nodes inside a private network, and are going to implement fail-over using a virtual IP managed at Layer 2 (ARP or NDP). Broadly speaking we can split the deployment into three parts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A backend that stores the container image layers and replicates them amongst the other replicas.&lt;&#x2F;li&gt;
&lt;li&gt;A frontend that serves client requests (&lt;abbr&gt;e.g.&lt;&#x2F;abbr&gt; push&#x2F;pull) and dispatches them to the backend.&lt;&#x2F;li&gt;
&lt;li&gt;A virtual IP manager that checks the health of the previous two components and will move the VIP to a different node if they are not healthy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For the frontend I found two main options:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;distribution.github.io&#x2F;distribution&#x2F;&quot;&gt;Distribution Registry&lt;&#x2F;a&gt;: This is the original container registry developed by Docker and has since been donated to the CNCF. It&#x27;s fairly bare-bones but the de facto way of running a registry yourself.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;zotregistry.dev&#x2F;&quot;&gt;Zot Registry&lt;&#x2F;a&gt; is a bit of a new comer here and seems to have been developed by Cisco before being open sourced. Zot comes with many more features than the distribution registry, including a GUI. (Also, &lt;a href=&quot;https:&#x2F;&#x2F;zotregistry.dev&#x2F;v2.1.5&#x2F;articles&#x2F;retention&#x2F;&quot;&gt;retention policies!&lt;&#x2F;a&gt; Never manually delete old images again!) One potential hiccup with this registry is that it strictly conforms to the OCI specifications, and so you will be unable to push container images to it using &lt;code&gt;docker push&lt;&#x2F;code&gt;, since that uses the docker format. This is easy to fix though by using Podman or skopeo, which let you push images in the OCI format.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If it isn&#x27;t clear already I like Zot quite a bit: it strikes a nice balance between features and simplicity, plus the GUI is nice too.&lt;&#x2F;p&gt;
&lt;p&gt;The backend is the heart of the system and is the most difficult to setup. In general, replicated storage can be done at two levels:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Block Storage. This operates at a very low level and replicates the individual blocks of your file system. Due to this generality, replicated block storage systems such &lt;a href=&quot;https:&#x2F;&#x2F;ceph.io&#x2F;en&#x2F;&quot;&gt;Ceph&lt;&#x2F;a&gt; are often very complicated and resource intensive. Not the choice here.&lt;&#x2F;li&gt;
&lt;li&gt;Object Storage. This operates at a high level and replicates invididual &quot;objects&quot;, which are just blobs of data. Most object stores use the S3 API, and fortunately Zot supports it as a backend. There are several good options here:&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;garagehq.deuxfleurs.fr&#x2F;&quot;&gt;Garage&lt;&#x2F;a&gt;. An interesting project, unlike many other systems it uses &lt;a href=&quot;https:&#x2F;&#x2F;garagehq.deuxfleurs.fr&#x2F;blog&#x2F;2023-11-thoughts-on-leaderless-consensus&#x2F;&quot;&gt;CRDTs&lt;&#x2F;a&gt; for replication instead of a consensus algorithm like Raft.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seaweedfs&#x2F;seaweedfs&quot;&gt;SeaweedFS&lt;&#x2F;a&gt;. I&#x27;ve heard excellent things about this and people have been able to run it with &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=39236027&quot;&gt;billions of files&lt;&#x2F;a&gt;. Definitely a good choice, however Garage seemed simpler to deploy so that&#x27;s what I went with.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally, managing the virtual IP. Keepalived is the simplest and traditional choice here, though (self-plug!) if you want more resilient leader election you could try &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;jwgarber&#x2F;kayak&quot;&gt;kayak&lt;&#x2F;a&gt; too.&lt;&#x2F;p&gt;
&lt;p&gt;All together then:&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;registry.svg&quot; alt=&quot;A diagram showing how zot, garage, and keepalived interact on three nodes with arrows indicating how they communicate with each other.&quot;&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;For deployment, all of the above programs are static binaries and can be easily run using systemd. Another option could be Podman quadlets.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There are more things you can add to this setup that would be useful in production (&lt;abbr&gt;e.g.&lt;&#x2F;abbr&gt; a reverse proxy to load balance between the nodes and do TLS termination), but that&#x27;s the fundamental idea. In practice it works pretty well!&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Which itself is actually fairly liberating through the magic of port forwards and SOCKS proxies.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;MinIO is not one of them.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;If doing this, be careful about running Podman and Kubernetes on the same node. Podman will try to set up its own firewall rules and they might conflict with what Kubernetes or your CNI does. I &lt;em&gt;think&lt;&#x2F;em&gt; Podman doesn&#x27;t create firewall rules if you run the containers with host network mode, so that might work. I know for sure this does not work with Docker.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;For the containerization purists out there, in theory you can avoid the firewall issues if you deploy these as static pods with kubeadm instead. However, this creates a bootstrapping loop with the other control plane pods, you won&#x27;t be able to use your registry if you nuke your cluster to re-install it, and there&#x27;s a strong chance a cluster problem could lead to cascading failures.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;In other words, just use systemd. systemd is great! The kubelet and CRI use systemd! You can do it, I believe!&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Does Kubernetes Work With SELinux?</title>
        <published>2025-07-02T00:00:00+00:00</published>
        <updated>2025-07-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/does-kubernetes-work-with-selinux/"/>
        <id>https://www.jwgarber.ca/blog/does-kubernetes-work-with-selinux/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/does-kubernetes-work-with-selinux/">&lt;p&gt;&lt;strong&gt;Yes.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;setup&#x2F;production-environment&#x2F;tools&#x2F;kubeadm&#x2F;install-kubeadm&#x2F;#installing-kubeadm-kubelet-and-kubectl&quot;&gt;official instructions&lt;&#x2F;a&gt; for kubeadm say to disable SELinux before doing the installation and give a big fat warning that:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Setting SELinux in permissive mode by running &lt;code&gt;setenforce 0&lt;&#x2F;code&gt; and &lt;code&gt;sed ...&lt;&#x2F;code&gt; effectively disables it. This is required to allow containers to access the host filesystem; for example, some cluster network plugins require that. You have to do this until SELinux support is improved in the kubelet.&lt;&#x2F;li&gt;
&lt;li&gt;You can leave SELinux enabled if you know how to configure it but it may require settings that are not supported by kubeadm.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The second sentence essentially tells the story: there are a few steps you need to do to make Kubernetes and SELinux interact happily, but it’s not something that kubeadm can do by itself, so the devs are preemptively disabling SELinux to avoid floods of GitHub issues of why people’s clusters aren’t working. With a little bit of effort (and I mean only a little), it is perfectly possible to make Kubernetes work with SELinux. The existing documentation about it is not great, so it me quite a while to realize that. For simplicity here I will assume you are using a RHEL-based system.&lt;&#x2F;p&gt;
&lt;p&gt;A quick recap: in &lt;a href=&quot;https:&#x2F;&#x2F;docs.redhat.com&#x2F;en&#x2F;documentation&#x2F;red_hat_enterprise_linux&#x2F;10&#x2F;html-single&#x2F;using_selinux&#x2F;index&quot;&gt;SELinux&lt;&#x2F;a&gt;, every process, file, and port have a &lt;em&gt;type&lt;&#x2F;em&gt;, and policies define which process types are allowed to access which file and port types. There are many different policies that come pre-installed on a RHEL system, and fortunately there is the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containers&#x2F;container-selinux&quot;&gt;container-selinux&lt;&#x2F;a&gt; package that comes with policies for containers. There are two container types relevant to us:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;container_t&lt;&#x2F;code&gt;: This is the default type that most containers run with, and it lets them access container file types. An SELinux compatible CRI will automatically launch most containers in the cluster with this type, and except for a few exceptions it will “just work”.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;spc_t&lt;&#x2F;code&gt;: This is a “super privileged container”—it is unconfined by SELinux and can do whatever it wants. Clearly we want to minimize the number of containers that run with this type, so it should only be used by administrative containers that interact with the host to manage the cluster itself.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let’s install a cluster then. Here we will be using &lt;a href=&quot;https:&#x2F;&#x2F;cri-o.io&#x2F;&quot;&gt;CRI-O&lt;&#x2F;a&gt;, which is a CRI developed by RedHat that is of course very compatible with SELinux (though I think containerd works too).&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Install container-selinux, cri-o, kubelet, kubeadm, and kubectl using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cri-o&#x2F;packaging&#x2F;blob&#x2F;main&#x2F;README.md#usage&quot;&gt;these instructions&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;setup&#x2F;production-environment&#x2F;tools&#x2F;kubeadm&#x2F;create-cluster-kubeadm&#x2F;&quot;&gt;Bootstrap&lt;&#x2F;a&gt; a cluster with kubeadm like normal. CRI-O will launch the control pods as &lt;code&gt;spc_t&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Install a CNI like &lt;a href=&quot;https:&#x2F;&#x2F;docs.cilium.io&#x2F;en&#x2F;stable&#x2F;gettingstarted&#x2F;k8s-install-default&#x2F;&quot;&gt;Cilium&lt;&#x2F;a&gt;. The Cilium pods are set to run as &lt;code&gt;spc_t&lt;&#x2F;code&gt; since they need to interact with the host network.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;And that’s it? Almost. For security reasons, containers with the &lt;code&gt;container_t&lt;&#x2F;code&gt; type are not allowed to access the underlying host, but on a bare-metal cluster we usually need to install extra administrative pods that do need access (&lt;abbr&gt;e.g.&lt;&#x2F;abbr&gt; a PersistentVolume provider). Some of these containers will run as &lt;code&gt;spc_t&lt;&#x2F;code&gt; automatically, such as ones that set &lt;code&gt;privileged: true&lt;&#x2F;code&gt; like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;topolvm&#x2F;topolvm&quot;&gt;TopoLVM&lt;&#x2F;a&gt;, but some won’t. For example, &lt;a href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;alloy&#x2F;latest&#x2F;&quot;&gt;Alloy&lt;&#x2F;a&gt; attempts to mount &lt;code&gt;hostPath&lt;&#x2F;code&gt; volumes to scrape your host logs, and a quick look at the audit logs using &lt;code&gt;ausearch -m AVC,USER_AVC -ts recent -i&lt;&#x2F;code&gt; shows a denial.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;----
type=PROCTITLE msg=audit(2025-07-03 03:34:58.695:2086) : proctitle=&amp;#x2F;bin&amp;#x2F;alloy run &amp;#x2F;etc&amp;#x2F;alloy&amp;#x2F;config.alloy --storage.path=&amp;#x2F;tmp&amp;#x2F;alloy --server.http.listen-addr=0.0.0.0:12345 --server.http.ui-path-p
type=SYSCALL msg=audit(2025-07-03 03:34:58.695:2086) : arch=x86_64 syscall=bpf success=no exit=EACCES(Permission denied) a0=BPF_MAP_CREATE a1=0xc000b1fd90 a2=0x50 a3=0x0 items=0 ppid=7511 pid=7513 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=alloy exe=&amp;#x2F;usr&amp;#x2F;bin&amp;#x2F;alloy subj=system_u:system_r:container_t:s0:c269,c920 key=(null)
type=AVC msg=audit(2025-07-03 03:34:58.695:2086) : avc:  denied  { map_create } for  pid=7513 comm=alloy scontext=system_u:system_r:container_t:s0:c269,c920 tcontext=system_u:system_r:container_t:s0:c269,c920 tclass=bpf permissive=0
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The simplest way to fix this is to manually override its &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;security-context&#x2F;#assign-selinux-labels-to-a-container&quot;&gt;security context&lt;&#x2F;a&gt; to run as &lt;code&gt;spc_t&lt;&#x2F;code&gt; in the Helm chart.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;alloy:
  securityContext:
    seLinuxOptions:
      type: spc_t
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course this is somewhat of a blunt instrument, since &lt;code&gt;spc_t&lt;&#x2F;code&gt; removes all SELinux restrictions, not just the ones that Alloy needs relaxed. Ideally you’d create a custom policy using something like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containers&#x2F;udica&quot;&gt;udica&lt;&#x2F;a&gt; that is tailored for your specific application.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Using &lt;code&gt;spc_t&lt;&#x2F;code&gt; though works in a pinch and is much better than disabling SELinux entirely.&lt;&#x2F;p&gt;
&lt;p&gt;For curiosity’s sake, you can run &lt;code&gt;ps -eZ | grep -e spc_t -e container_t&lt;&#x2F;code&gt; on the host see the SELinux types of the container processes. Here we can see the control plane pods, cilium, and alloy running as &lt;code&gt;spc_t&lt;&#x2F;code&gt; as expected, and core-dns and a utility pod running as &lt;code&gt;container_t&lt;&#x2F;code&gt; since they don’t need host access.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;system_u:system_r:spc_t:s0         3642 ?        00:02:08 kube-controller
system_u:system_r:spc_t:s0         3653 ?        00:01:30 kube-scheduler
system_u:system_r:spc_t:s0         3668 ?        00:02:58 etcd
system_u:system_r:spc_t:s0         3684 ?        00:05:36 kube-apiserver
system_u:system_r:spc_t:s0         3777 ?        00:00:01 kube-proxy
system_u:system_r:spc_t:s0         4977 ?        00:00:12 cilium-operator
system_u:system_r:spc_t:s0         5026 ?        00:01:30 cilium-agent
system_u:system_r:spc_t:s0         5384 ?        00:00:00 cilium-health-r
system_u:system_r:spc_t:s0         5467 ?        00:00:00 cilium-envoy-st
system_u:system_r:spc_t:s0         5471 ?        00:00:12 cilium-envoy
system_u:system_r:container_t:s0:c120,c730 5523 ? 00:00:07 coredns
system_u:system_r:container_t:s0:c321,c358 5536 ? 00:00:07 coredns
system_u:system_r:spc_t:s0:c51,c687 8739 ?       00:00:00 alloy
system_u:system_r:container_t:s0:c51,c687 8751 ? 00:00:00 prometheus-conf
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And there you have it, now you can run a Kubernetes cluster with &lt;a href=&quot;https:&#x2F;&#x2F;stopdisablingselinux.com&#x2F;&quot;&gt;one less tear&lt;&#x2F;a&gt; from Dan Walsh.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;You may need to restart the cri-o and kubelet systemd services to pick up the new CNI.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;For example, RKE2 runs its control plane pods with a &lt;a href=&quot;https:&#x2F;&#x2F;docs.rke2.io&#x2F;security&#x2F;selinux&quot;&gt;custom type&lt;&#x2F;a&gt; that is more restricted than &lt;code&gt;spc_t&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Blocking Sudo Exploits with fapolicyd</title>
        <published>2025-07-01T00:00:00+00:00</published>
        <updated>2025-07-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/blocking-sudo-exploits-with-fapolicyd/"/>
        <id>https://www.jwgarber.ca/blog/blocking-sudo-exploits-with-fapolicyd/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/blocking-sudo-exploits-with-fapolicyd/">&lt;p&gt;There’s a joke that goes around my office: if corporate ever tries to lock down root access on our workstations, we’ll just use the latest sudo vulnerability to get it back. This is not an idle threat. &lt;a href=&quot;https:&#x2F;&#x2F;www.stratascale.com&#x2F;vulnerability-alert-CVE-2025-32463-sudo-chroot&quot;&gt;CVE-2025-32463&lt;&#x2F;a&gt; has just been announced, and it allows arbitrary unprivileged users to acquire root privileges on most Linux systems out-of-the-box. This is an all-too-common story: a bug in an SUID binary allows unchecked privilege escalation. Once an attacker acquires root privileges the game is over: MAC systems can be disabled (&lt;code&gt;setenforce 0&lt;&#x2F;code&gt;), your firewall rules can be changed (&lt;code&gt;nft flush ruleset&lt;&#x2F;code&gt;), and the attacker can read arbitrary files (&lt;code&gt;cat &#x2F;etc&#x2F;shadow&lt;&#x2F;code&gt;). With one command all additional security measures can be bypassed, leading to a complete compromise of your system. Scary stuff!&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, patching these vulnerabilities is playing a game of Whac-A-Mole. You may be able to patch some after the fact, but other vulnerabilities of this sort almost certainly remain. In cases like this, &lt;em&gt;proactive&lt;&#x2F;em&gt; measures are much better than &lt;em&gt;reactive&lt;&#x2F;em&gt; ones. How then can we prevent these vulnerabilities when we have little idea where the next one will show up?&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;Modern_Problems_Require_Modern_Solutions.jpg&quot; alt=&quot;Dave Chappelle pointing his finger at the viewer, with the meme in yellow letters captioned below.&quot;&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;Many local privilege escalation vulnerabilities require executing custom binaries on the target system. What if we just … block executing everything by default? This is exactly the approach that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;linux-application-whitelisting&#x2F;fapolicyd&quot;&gt;fapolicyd&lt;&#x2F;a&gt; uses. It may seem extreme, but it is effective. fapolicyd maintains a database of trusted files on the system (by default those installed by your package manager), and &lt;em&gt;all&lt;&#x2F;em&gt; attempts to open or execute a file are checked against that database. Any access of a potentially dangerous file (&lt;abbr&gt;e.g.&lt;&#x2F;abbr&gt; an executable, shared library, or even Python script) is denied if that file is not on the trusted list.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; (For extra security, fapolicyd can also optionally track the SHA-256 hashes of trusted files and deny the access if that hash has changed.)&lt;&#x2F;p&gt;
&lt;p&gt;Let’s recreate the privilege escalation with a vulnerable version of sudo, and then see how fapolicyd blocks it. The exploit itself is quite clever: it creates a custom shared library that execs a root shell, and then tricks sudo into loading it via &lt;code&gt;chroot(2)&lt;&#x2F;code&gt;. For a testing system I will be using CentOS Stream 10 with sudo version 1.9.15p5.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;As root, create an unprivileged user that isn’t in the wheel group: &lt;code&gt;useradd -m lowpriv&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Set the password for that user: &lt;code&gt;passwd lowpriv&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Switch to that user account: &lt;code&gt;su -l lowpriv&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;As the unprivileged user, copy the &lt;code&gt;sudo-chwoot.sh&lt;&#x2F;code&gt; script and run it. You should now have a root shell.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre&gt;&lt;code&gt;[lowpriv@localhost ~]$ .&amp;#x2F;sudo-chwoot.sh
woot!
[root@localhost &amp;#x2F;]# id
uid=0(root) gid=0(root) groups=0(root),1001(lowpriv) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we can see how fapolicyd blocks this. Assuming you are on a RHEL-based system, &lt;a href=&quot;https:&#x2F;&#x2F;docs.redhat.com&#x2F;en&#x2F;documentation&#x2F;red_hat_enterprise_linux&#x2F;10&#x2F;html&#x2F;security_hardening&#x2F;blocking-and-allowing-applications-by-using-fapolicyd#deploying-fapolicyd&quot;&gt;install fapolicyd&lt;&#x2F;a&gt; and then start it. Re-running the exploit will now show the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[lowpriv@localhost ~]$ .&amp;#x2F;sudo-chwoot.sh
woot!
[sudo] password for lowpriv:
Sorry, try again.
[sudo] password for lowpriv:
Sorry, try again.
[sudo] password for lowpriv:
sudo: 3 incorrect password attempts
[lowpriv@localhost ~]$
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No dice—the exploit failed. We can see what happened using &lt;code&gt;ausearch -i -ts recent -m FANOTIFY&lt;&#x2F;code&gt; to view the audit log.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;----
type=PROCTITLE msg=audit(07&amp;#x2F;01&amp;#x2F;2025 19:31:57.613:39571) : proctitle=sudo -R woot woot
type=PATH msg=audit(07&amp;#x2F;01&amp;#x2F;2025 19:31:57.613:39571) : item=0 name=libnss_&amp;#x2F;woot1337.so.2 inode=10034633 dev=fd:00 mode=file,755 ouid=lowpriv ogid=lowpriv rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(07&amp;#x2F;01&amp;#x2F;2025 19:31:57.613:39571) : cwd=&amp;#x2F;tmp&amp;#x2F;sudowoot.stage.eaL5jR
type=SYSCALL msg=audit(07&amp;#x2F;01&amp;#x2F;2025 19:31:57.613:39571) : arch=x86_64 syscall=openat success=no exit=EPERM(Operation not permitted) a0=AT_FDCWD a1=0x643319d81e10 a2=O_RDONLY|O_CLOEXEC a3=0x0 items=1 ppid=119624 pid=119634 auid=admin uid=lowpriv gid=lowpriv euid=root suid=root fsuid=root egid=lowpriv sgid=lowpriv fsgid=lowpriv tty=pts3 ses=33 comm=sudo exe=&amp;#x2F;usr&amp;#x2F;bin&amp;#x2F;sudo subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=FANOTIFY msg=audit(07&amp;#x2F;01&amp;#x2F;2025 19:31:57.613:39571) : resp=deny fan_type=rule_info fan_info=8 subj_trust=unknown obj_trust=no
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output is a little abstruse, but it shows that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A user tried to execute the vulnerable sudo command&lt;&#x2F;li&gt;
&lt;li&gt;That sudo command tried to open &lt;code&gt;libnss_&#x2F;woot1337.so.2&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;openat&lt;&#x2F;code&gt; syscall on that path failed with &lt;code&gt;EPERM&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;fapolicyd denied the access because the subject (the shared library) was untrusted.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The system overhead of fapolicyd is non-neglible: it evaluates all open and exec calls against the trust database, and it can be tricky to setup. However, given the existence of these privilege escalation vulnerabilies that allow trivial takeover of your entire system, you cannot run a secure system without it.&lt;&#x2F;p&gt;
&lt;p&gt;P.S. fapolicyd would also block the recent &lt;a href=&quot;https:&#x2F;&#x2F;blog.qualys.com&#x2F;vulnerabilities-threat-research&#x2F;2025&#x2F;06&#x2F;17&#x2F;qualys-tru-uncovers-chained-lpe-suse-15-pam-to-full-root-via-libblockdev-udisks&quot;&gt;CVE-2025-6019&lt;&#x2F;a&gt;, since the root shell that udisks2 is tricked into mounting would not be trusted.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;I mean, $10 there’ll be another one in sudo, but it’s not the only problem.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;I didn’t want to say it, but fapolicyd is similar in spirit to an anti-virus, except those use an allow-by-default-deny-if-suspicious approach (and are usually crap), while fapolicyd maintains a much more strict (and thus effective) deny-by-default-allow-if-trusted one.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Installing KOReader on a Kobo</title>
        <published>2024-12-21T00:00:00+00:00</published>
        <updated>2024-12-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/installing-koreader-kobo/"/>
        <id>https://www.jwgarber.ca/blog/installing-koreader-kobo/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/installing-koreader-kobo/">&lt;p&gt;I was recently interested in getting an e-reader, and there are two main options: a Kindle, or a Kobo. The Kindle only supports their proprietary &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Kindle_File_Format&quot;&gt;file format&lt;&#x2F;a&gt; and is difficult to &lt;a href=&quot;https:&#x2F;&#x2F;www.mobileread.com&#x2F;forums&#x2F;showthread.php?t=320564&quot;&gt;jailbreak&lt;&#x2F;a&gt;. The Kobo on the other hand supports the open &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;EPUB&quot;&gt;EPUB&lt;&#x2F;a&gt; standard and is &lt;a href=&quot;https:&#x2F;&#x2F;www.linux-magazine.com&#x2F;Online&#x2F;Features&#x2F;Basic-Hacks-for-Kobo-E-Readers&quot;&gt;extremely hackable&lt;&#x2F;a&gt;. The choice was thus obvious, and I popped down to the store to get a &lt;a href=&quot;https:&#x2F;&#x2F;ca.kobobooks.com&#x2F;products&#x2F;kobo-clara-bw&quot;&gt;Clara BW&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I had originally hoped to replace the stock firmware with the open source &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Quill-OS&#x2F;quill&quot;&gt;Quill&#x2F;InkBox&lt;&#x2F;a&gt; OS, though unfortunately that project has halted since new Kobos are using secure boot :( Perhaps one day the &lt;a href=&quot;https:&#x2F;&#x2F;pine64.com&#x2F;product&#x2F;pinenote-community-edition-coming-soon&#x2F;&quot;&gt;PineNote&lt;&#x2F;a&gt; or even &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;joeycastillo&#x2F;The-Open-Book&quot;&gt;OpenBook&lt;&#x2F;a&gt; can fulfill that role.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, I settled on installing &lt;a href=&quot;https:&#x2F;&#x2F;koreader.rocks&#x2F;&quot;&gt;KOReader&lt;&#x2F;a&gt;, which is an insanely powerful and customizable ebook reader application. As said before, Kobos are quite easy to modify: simple plug your Kobo into your computer, hit the &lt;i&gt;Connect&lt;&#x2F;i&gt; button on the screen, and now you can mount the Kobo file system as a regular external drive. The &lt;a href=&quot;https:&#x2F;&#x2F;www.mobileread.com&#x2F;forums&#x2F;showthread.php?t=314220&quot;&gt;standard way&lt;&#x2F;a&gt; to install KOReader is to download an all-in-one zip and copy it onto the drive, but that&#x27;s no fun. Instead I decided to “pop the hood” and do it manually, which was very easy after following &lt;a href=&quot;https:&#x2F;&#x2F;uwuu.ca&#x2F;kobo&#x2F;guide&#x2F;custom-software&#x2F;&quot;&gt;this guide&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, we need to prevent the default Nickel firmware from indexing the hidden directories where we are going to install our new software. Edit the &lt;code&gt;&#x2F;.kobo&#x2F;Kobo&#x2F;Kobo eReader.conf&lt;&#x2F;code&gt; file and add the following section to the bottom:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[FeatureSettings]
ExcludeSyncFolders=(\\.(?!kobo|adobe).+|([^.][^&amp;#x2F;]*&amp;#x2F;)+\\..+)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we need to install a launcher to run our custom software. There are two main ones currently: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;NiLuJe&#x2F;kfmon&quot;&gt;KFMon&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;pgaskin.net&#x2F;NickelMenu&#x2F;&quot;&gt;NickelMenu&lt;&#x2F;a&gt;. NickelMenu has the advantage of persisting between firmware upgrades, so that&#x27;s the route I chose. Installation is quite easy:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Download the latest &lt;code&gt;KoboRoot.tgz&lt;&#x2F;code&gt; from the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgaskin&#x2F;NickelMenu&#x2F;releases&#x2F;&quot;&gt;releases page&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Copy the &lt;code&gt;KoboRoot.tgz&lt;&#x2F;code&gt; into the &lt;code&gt;&#x2F;.kobo&lt;&#x2F;code&gt; directory on the mounted drive. (&lt;em&gt;Do not&lt;&#x2F;em&gt; extract the file, just copy it.)&lt;&#x2F;li&gt;
&lt;li&gt;Unmount your Kobo and unplug it. It should reboot, and now you will have NickelMenu in the bottom right corner.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Next it&#x27;s time to install KOReader!&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Download the latest &lt;code&gt;koreader-kobo&lt;&#x2F;code&gt; zip file from the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;baskerville&#x2F;plato&#x2F;releases&#x2F;&quot;&gt;releases page&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Unzip the KOReader release, and copy the extracted &lt;code&gt;koreader&lt;&#x2F;code&gt; directory to &lt;code&gt;&#x2F;.adds&#x2F;koreader&lt;&#x2F;code&gt; on your Kobo.&lt;&#x2F;li&gt;
&lt;li&gt;Create a file called &lt;code&gt;&#x2F;.adds&#x2F;nm&#x2F;koreader&lt;&#x2F;code&gt; with the following contents:&lt;pre&gt;&lt;code&gt;menu_item :main :KOReader :cmd_spawn :quiet:exec &amp;#x2F;mnt&amp;#x2F;onboard&amp;#x2F;.adds&amp;#x2F;koreader&amp;#x2F;koreader.sh
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Unmount your Kobo, and now you can use NickelMenu to launch KOReader.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;As a bonus, we can use the same technique to install &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;baskerville&#x2F;plato&quot;&gt;Plato&lt;&#x2F;a&gt;, which is a simple ebook reader designed specifically for Kobo.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Download the latest Plato zip file from the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;baskerville&#x2F;plato&#x2F;releases&#x2F;&quot;&gt;releases page&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Unzip the Plato release, and copy the extracted contents to &lt;code&gt;&#x2F;.adds&#x2F;plato&lt;&#x2F;code&gt; on your Kobo.&lt;&#x2F;li&gt;
&lt;li&gt;Create a file called &lt;code&gt;&#x2F;.adds&#x2F;nm&#x2F;plato&lt;&#x2F;code&gt; with the following contents:&lt;pre&gt;&lt;code&gt;menu_item :main :Plato :cmd_spawn :quiet:exec &amp;#x2F;mnt&amp;#x2F;onboard&amp;#x2F;.adds&amp;#x2F;plato&amp;#x2F;plato.sh
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Unmount your Kobo, and now you can use NickelMenu to launch Plato.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;And that&#x27;s it! Now go get some nice &lt;a href=&quot;https:&#x2F;&#x2F;standardebooks.org&#x2F;&quot;&gt;ebooks&lt;&#x2F;a&gt; and start reading!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Crushing Complexity of the GPL3</title>
        <published>2021-12-23T00:00:00+00:00</published>
        <updated>2021-12-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/crushing-complexity-gpl3/"/>
        <id>https://www.jwgarber.ca/blog/crushing-complexity-gpl3/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/crushing-complexity-gpl3/">&lt;p&gt;I recently released my first &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;jwgarber&#x2F;napa&quot;&gt;open source project&lt;&#x2F;a&gt; and had to choose a license. Being an advocate of free software principles, my first choice was the &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;licenses&#x2F;gpl-3.0.en.html&quot;&gt;GPL3&lt;&#x2F;a&gt;. However, I decided out of curiosity to read the license first—I think it’s reasonable that if I’m going to use a license I should understand what it requires. A good forty-five minutes later, I had a single conclusion: the GPL3 is complicated—horribly, mind-numbingly complicated. I think a simple picture will illustrate:&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;licenses.svg&quot; alt=&quot;A bar chart of license word counts&quot;&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;One of these things is not like the others. But if the length of the GPL3 is intimidating, here is a &lt;a href=&quot;https:&#x2F;&#x2F;copyleft.org&#x2F;guide&#x2F;comprehensive-gpl-guidech10.html#x13-650009&quot;&gt;13,000 word explanation&lt;&#x2F;a&gt; of the differences of the GPL3 from the GPL2!&lt;&#x2F;p&gt;
&lt;p&gt;To give just a small example, consider the following requirement for Conveyance from section 5:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The definition of “Appropriate Legal Notices” is provided in section 0:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So … if the work has interactive user interfaces, then it must display Appropriate Legal Notices, but if it doesn’t display Appropriate Legal Notices, apparently that’s fine? So do I need legal notices or not? And even if I do, why on earth would the license try to dictate such a nitpicky thing?&lt;&#x2F;p&gt;
&lt;p&gt;Here is another section that defines what code you are obligated to release under the license:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;As a baseline, the Corresponding Source not only includes the work itself, but &lt;em&gt;all&lt;&#x2F;em&gt; code needed to generate, install, run, and modify the work! That’s like, everything on your computer from the ground up! Exceptions are carved out for general-purpose tools or System Libraries, which are defined in the previous paragraph as:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Major Component and Standard Interface are then defined as … it just goes on and on. (Also, I like the phrase “intimate data communication.” Try defining that in court!)&lt;&#x2F;p&gt;
&lt;p&gt;This is merely the tip of the iceberg. The GPL3 also includes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;provisions for contracting GPL3 software from third-parties&lt;&#x2F;li&gt;
&lt;li&gt;anti-DMCA clauses to nullify article 11 of the 1996 WIPO copyright treaty&lt;&#x2F;li&gt;
&lt;li&gt;anti-DRM clauses, which attempt to define what a “User Product” is&lt;&#x2F;li&gt;
&lt;li&gt;explicit permission to distribute the software through peer-to-peer networks (apparently the GPL2 has problems with that)&lt;&#x2F;li&gt;
&lt;li&gt;a weird exception for patent agreements done before 28 March 2007 due to a lawsuit settlement between &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Novell#Legal_actions_and_reactions&quot;&gt;Novell and Microsoft&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And there is so much more. To appreciate the complexity of the GPL3 you must read the license yourself. For a taste of the legal intricacies that a lawyer would subject this to, here is Ken Mitchell’s &lt;a href=&quot;https:&#x2F;&#x2F;writing.kemitchell.com&#x2F;2021&#x2F;01&#x2F;24&#x2F;Reading-AGPL.htmlhttps:&#x2F;&#x2F;writing.kemitchell.com&#x2F;2021&#x2F;01&#x2F;24&#x2F;Reading-AGPL.html&quot;&gt;analysis&lt;&#x2F;a&gt; of &lt;em&gt;one&lt;&#x2F;em&gt; paragraph in the AGPL3 that is different from the GPL3.&lt;&#x2F;p&gt;
&lt;p&gt;It was not always this way. In 2005, Lawrence Rosen updated his own &lt;a href=&quot;https:&#x2F;&#x2F;rosenlaw.com&#x2F;OSL3.0-explained.htm&quot;&gt;Open Software License&lt;&#x2F;a&gt; to version 3 with the explicit goal to “express clearly the licensing objectives of software copyright and patent owners.” However, this goal of simplicity was not shared by the authors of the GPL3. Allison Randal &lt;a href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20210203230947&#x2F;http:&#x2F;&#x2F;radar.oreilly.com&#x2F;2007&#x2F;05&#x2F;gplv3-clarity-and-simplicity.html&quot;&gt;lamented&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don’t know that clarity and simplicity was ever a goal that Richard Stallman, Eben Moglen, or any of the GPLv3 team desired to achieve. Looking at the near-finished draft, I have to say it’s unlikely that they ever considered simplicity a priority, if they considered it at all.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In hindsight, ensuring the GPL3 covered every last corner-case of software licensing ended up &lt;a href=&quot;https:&#x2F;&#x2F;opensource.com&#x2F;article&#x2F;18&#x2F;6&#x2F;gplv3-anniversary&quot;&gt;missing the forest for the trees&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Largely because of its complexity and baroqueness, GPLv3 was a lost opportunity to create a strong copyleft license that would appeal very broadly to modern individual software authors and corporate licensors. I believe individual developers today tend to prefer short, simple, easy to understand, minimalist licenses, the most obvious example of which is the MIT License.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A shame, but so it is.&lt;&#x2F;p&gt;
&lt;p&gt;What, then, is a good copyleft license for modern usage? The &lt;a href=&quot;https:&#x2F;&#x2F;commission.europa.eu&#x2F;about&#x2F;departments-and-executive-agencies&#x2F;digital-services&#x2F;open-source-strategy-history&#x2F;european-union-public-licence_en&quot;&gt;EUPL&lt;&#x2F;a&gt; is a noble effort: it’s simple, written with an explicit attention to legal detail, and even includes compatibility with other copyleft licenses! However, there is one major flaw: the definition of “Derivative Works” defers to the copyright law of whichever EU state you’re in (or Belgium, if you’re not &lt;code&gt;¯\_(ツ)_&#x2F;¯&lt;&#x2F;code&gt;), which leaves it &lt;a href=&quot;https:&#x2F;&#x2F;interoperable-europe.ec.europa.eu&#x2F;collection&#x2F;eupl&#x2F;matrix-eupl-compatible-open-source-licences#section-3&quot;&gt;caught in a quagmire&lt;&#x2F;a&gt; of whether linking creates a derivative work. (They don’t think so, but it’s never been tested in court, so who knows!)&lt;&#x2F;p&gt;
&lt;p&gt;The only copyleft license I’m aware of that is easy to understand, legally unambiguous, and well-established is the &lt;a href=&quot;https:&#x2F;&#x2F;www.mozilla.org&#x2F;en-US&#x2F;MPL&#x2F;2.0&#x2F;&quot;&gt;MPL2&lt;&#x2F;a&gt;. It has a weaker form of copyleft than the GPL that is based purely on source code files, but it is supremely simple, and also interoperates well with the rest of the permissively-licensed open source world. Ultimately, it’s the pragmatic choice, and the license I chose.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Basic C Makefile</title>
        <published>2021-06-13T00:00:00+00:00</published>
        <updated>2021-06-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/basic-c-makefile/"/>
        <id>https://www.jwgarber.ca/blog/basic-c-makefile/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/basic-c-makefile/">&lt;p&gt;These days I usually use &lt;a href=&quot;https:&#x2F;&#x2F;mesonbuild.com&#x2F;&quot;&gt;Meson&lt;&#x2F;a&gt; for building C and C++ code, but for small projects the simplicity and ubiquity of a Makefile can&#x27;t be beat. In the past I&#x27;d write custom Makefile rules to compile each file individually, but with the power of wildcards we can write a generic Makefile that drops in to any project. Simply set the executable name, customize your compiler options, and off you go.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; class=&quot;language-make &quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;# `make` builds the target
# `make file.o` creates the `file` object file
# `make clean` will rm all object files and the target

TARGET = my-executable

# sample settings
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -g
LDLIBS = -lpthread

SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
OBJECTS = $(SOURCES:.c=.o)

# link the object files to create the target
$(TARGET): $(OBJECTS)
	$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS)

# compile rule for the object files
%.o: %.c $(HEADERS)
	$(CC) $(CFLAGS) -c $&amp;lt; -o $@

.PHONY: clean

clean:
	-rm $(OBJECTS) $(TARGET)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Final Update</title>
        <published>2019-08-22T00:00:00+00:00</published>
        <updated>2019-08-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/final-update/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/final-update/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/final-update/">&lt;p&gt;It is now the final week of GSoC, and it is time for me to write my final blog post. Over the past summer I have worked on fixing the &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;coreboot&quot;&gt;Coverity scan&lt;&#x2F;a&gt; issues in coreboot, with the goal of making the code base “Coverity clean”. This has involved writing a substantial number of patches, the vast majority of which are in coreboot, with a sprinkling in a few other projects:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca+repo:coreboot+before:2019-08-26+status:merged&quot;&gt;146&lt;&#x2F;a&gt; patches in coreboot&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca+repo:flashrom+before:2019-08-26+status:merged&quot;&gt;6&lt;&#x2F;a&gt; patches in flashrom&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chromium-review.googlesource.com&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca+status:merged+before:2019-08-26&quot;&gt;6&lt;&#x2F;a&gt; patches in vboot&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chromium-review.googlesource.com&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca+status:merged+before:2019-08-26&quot;&gt;3&lt;&#x2F;a&gt; patches in Chromium EC&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lists.infradead.org&#x2F;pipermail&#x2F;opensbi&#x2F;2019-August&#x2F;000350.html&quot;&gt;4&lt;&#x2F;a&gt; patches in OpenSBI&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca+repo:em100+before:2019-08-26+status:merged&quot;&gt;2&lt;&#x2F;a&gt; patches in em100&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.kernel.org&#x2F;pub&#x2F;scm&#x2F;linux&#x2F;kernel&#x2F;git&#x2F;torvalds&#x2F;linux.git&#x2F;commit&#x2F;?id=b9d1a8e9302e68ee03571a286aadeb8041e0b2ca&quot;&gt;1&lt;&#x2F;a&gt; in the Linux kernel&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At the time of writing, a few of my patches are still &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca+status:open+before:2019-08-26&quot;&gt;under review&lt;&#x2F;a&gt; on Gerrit, so it is possible (and hopeful!) that this list will increase over the next few weeks.&lt;&#x2F;p&gt;
&lt;p&gt;In total, these patches resolved 172 Coverity issue reports of actual bugs. However, Coverity also isn’t always right, and some issues weren’t actually problems that required patches. These issues, 91 in total, were either false positives or intentional and were ignored. At the moment, there are currently 223 remaining reports in the issue tracker for coreboot. Despite being a substantial number, this is almost entirely composed of issues from third-party projects (such as OpenSBI or vboot, which probably shouldn’t be counted in the coreboot tracker anyway), and the AMD vendorcode. The original plan at the beginning of the summer was to work on the AMD vendorcode; however, after discussion with my mentors we decided to skip it, since with the upcoming deprecations for coreboot 4.11 it might not be around much longer. Aside from this, there are roughly 20 remaining issues, which mostly required refactoring or technical knowledge that I don’t have.&lt;&#x2F;p&gt;
&lt;p&gt;With the summary out of the way, I’d like to give everyone a sample of the sort of bugs I’ve worked on during the project, and hopefully give advice for avoiding them in the future. Here is a list of the most common, nasty, or subtle types of bugs I’ve found over the summer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;missing-break-statements&quot;&gt;Missing Break Statements&lt;&#x2F;h3&gt;
&lt;p&gt;In switch statements in C, every case statement implicitly falls through to the next one. However, this is almost never the desired behavior, and so to avoid this every case needs to be manually terminated by a break to prevent the fall-through. This unfortunately is very tedious to do and is often accidentally left out. For a prototypical example, let’s look at &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;32180&quot;&gt;CB:32180&lt;&#x2F;a&gt; from the AGESA vendorcode.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;switch (AccessWidth) {
        case AccessS3SaveWidth8:
                RegValue = *(UINT8 *) Value;
                break;
        case AccessS3SaveWidth16:
                RegValue = *(UINT16 *) Value;
                break;
        case AccessS3SaveWidth32:
                RegValue = *(UINT32 *) Value;
        default:
                ASSERT (FALSE);
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this switch there is a missing break after the &lt;code&gt;AccessS3SaveWidth32&lt;&#x2F;code&gt; case, which will then fall-through to the false assertion. Clearly not intentional! Other examples of this, though not as severe, can be found in &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;32088&quot;&gt;CB:32088&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34293&quot;&gt;CB:34293&lt;&#x2F;a&gt;. Fortunately, these errors today can be prevented by the compiler. GCC recently added the &lt;code&gt;-Wimplicit-fallthrough&lt;&#x2F;code&gt; option, which will warn on all implicit fall throughs and alert to a potentially missing break. However, some fall throughs are intentional, and these can be annotated by a &lt;code&gt;&#x2F;* fall through *&#x2F;&lt;&#x2F;code&gt; comment to silence the warning. Since &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34297&quot;&gt;CB:34297&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34300&quot;&gt;CB:34300&lt;&#x2F;a&gt; this warning has been enabled in coreboot, so this should be the last we see of missing break statements.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;off-by-one-errors&quot;&gt;Off-by-One Errors&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Everyone has been bitten by off-by-one errors. Let’s take a look at &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;32125&quot;&gt;CB:32125&lt;&#x2F;a&gt; from the Baytrail graphics code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;static void gfx_lock_pcbase(struct device *dev)
{
        const u16 gms_size_map[17] = { 0, 32, 64, 96, 128, 160, 192, 224, 256,
                                       288, 320, 352, 384, 416, 448, 480, 512 };
        ...
        u32 gms, gmsize, pcbase;
        gms = pci_read_config32(dev, GGC) &amp;amp; GGC_GSM_SIZE_MASK;
        gms &amp;gt;&amp;gt;= 3;
        if (gms &amp;gt; ARRAY_SIZE(gms_size_map))
                return;
        gmsize = gms_size_map[gms];
        ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here we have an array &lt;code&gt;gms_size_map&lt;&#x2F;code&gt; of 17 elements, and a bounds check on the &lt;code&gt;gms&lt;&#x2F;code&gt; variable before it is used to index into the array. However, there’s a problem. The bounds check misses the case when &lt;code&gt;gms == ARRAY_SIZE(gms_size_map) == 17&lt;&#x2F;code&gt;, which is one past 16—the index of the last array element. The fix is to use &lt;code&gt;&amp;gt;=&lt;&#x2F;code&gt; in the check instead of &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;. This exact error when performing a bounds check is &lt;em&gt;very&lt;&#x2F;em&gt; common: see at least &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;32244&quot;&gt;CB:32244&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34498&quot;&gt;CB:34498&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;chromium-review.googlesource.com&#x2F;c&#x2F;chromiumos&#x2F;platform&#x2F;vboot_reference&#x2F;+&#x2F;1752766&quot;&gt;CL:1752766&lt;&#x2F;a&gt; for other examples.&lt;&#x2F;p&gt;
&lt;p&gt;Another nasty place where off-by-one errors strike is with strings—in particular, when making sure they are null terminated. Here is &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34374&quot;&gt;CB:34374&lt;&#x2F;a&gt; from the ACPI setup of the Getac P470.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;static long acpi_create_ecdt(acpi_ecdt_t * ecdt)
{
        ...
        static const char ec_id[] = &amp;quot;\_SB.PCI0.LPCB.EC0&amp;quot;;
        ...
        strncpy((char *)ecdt-&amp;gt;ec_id, ec_id, strlen(ec_id));
        ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem is that &lt;code&gt;strncpy()&lt;&#x2F;code&gt; will only copy at most &lt;code&gt;strlen(ec_id)&lt;&#x2F;code&gt; characters, which excludes the null character. The author might have been thinking of the similar &lt;code&gt;strlcpy()&lt;&#x2F;code&gt;, which &lt;em&gt;does&lt;&#x2F;em&gt; explicitly null terminate the string buffer even if it never reaches a null character. In this case none of the string-copying functions are needed, since &lt;code&gt;ec_id&lt;&#x2F;code&gt; is a string buffer and so can be copied using a simple &lt;code&gt;memcpy()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;boolean-vs-bitwise-operators&quot;&gt;Boolean vs Bitwise Operators&lt;&#x2F;h3&gt;
&lt;p&gt;In C, all integers are implicitly convertible to boolean values and can be used with all boolean operators. While somewhat convenient, this also makes it very easy to mistakenly use a boolean operator when a bitwise one was intended. Let’s take a look at &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33454&quot;&gt;CB:33454&lt;&#x2F;a&gt; from the CIMX southbridge code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;void sb_poweron_init(void)
{
        u8 data;
        ...
        data = inb(0xCD7);
        data &amp;amp;= !BIT0;
        if (!CONFIG(PCIB_ENABLE)) {
                data |= BIT0;
        }
        outb(data, 0xCD7);
        ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here &lt;code&gt;BIT0&lt;&#x2F;code&gt; is the constant &lt;code&gt;0x1&lt;&#x2F;code&gt;, so &lt;code&gt;!BIT0&lt;&#x2F;code&gt; expands to 0, with the net effect of &lt;code&gt;data&lt;&#x2F;code&gt; being completely cleared, regardless of the previous value from &lt;code&gt;inb()&lt;&#x2F;code&gt;. The intended operator to use was the bitwise negation &lt;code&gt;~&lt;&#x2F;code&gt;, which would only clear the lowest bit. For more examples of this sort of bug, see &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34560&quot;&gt;CB:34560&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;riscv&#x2F;opensbi&#x2F;commit&#x2F;3f738f5897a6694b8630d3a9c6751f49c3c7d540&quot;&gt;OpenSBI 3f738f5&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;implicit-integer-conversions&quot;&gt;Implicit Integer Conversions&lt;&#x2F;h3&gt;
&lt;p&gt;C allows implicit conversions between all integer types, which opens the door for many accidental or unintentional bugs. For an extremely subtle example of this, let’s take a look at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;riscv&#x2F;opensbi&#x2F;commit&#x2F;5e4021a2f5ca346d1c12b80d346c1a2e7eb4b501&quot;&gt;OpenSBI 5e4021a&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;void *sbi_memset(void *s, int c, size_t count);

void sbi_fifo_init(struct sbi_fifo *fifo, void *queue_mem,
                   u16 entries, u16 entry_size)
{
        ...
        sbi_memset(fifo-&amp;gt;queue, 0, entries * entry_size);
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do you see the problem? The issue is that &lt;code&gt;entries&lt;&#x2F;code&gt; and &lt;code&gt;entry_size&lt;&#x2F;code&gt; are both 16-bit integers, and by the rules of C are implicitly converted to &lt;code&gt;int&lt;&#x2F;code&gt; before the multiplication. An &lt;code&gt;int&lt;&#x2F;code&gt; cannot hold all possible values of a &lt;code&gt;u16 * u16&lt;&#x2F;code&gt;, and so if the multiplication overflows the intermediate result could be a negative number. On 64-bit platforms &lt;code&gt;size_t&lt;&#x2F;code&gt; will be a &lt;code&gt;u64&lt;&#x2F;code&gt;, and the negative result will then be sign-extended to a massive integer. As the last argument to &lt;code&gt;sbi_memset()&lt;&#x2F;code&gt;, this could lead to a very large out-of-bounds write. The solution is to cast one of the variables to a &lt;code&gt;size_t&lt;&#x2F;code&gt; before the multiplication, which is wide enough to prevent the implicit promotion to &lt;code&gt;int&lt;&#x2F;code&gt;. For other examples of this problem, see &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33986&quot;&gt;CB:33986&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34529&quot;&gt;CB:34529&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another situation where implicit conversions strike is in error handling. Here is &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33962&quot;&gt;CB:33962&lt;&#x2F;a&gt; in the x86 ACPI code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;static ssize_t acpi_device_path_fill(const struct device *dev, char *buf,
                                     size_t buf_len, size_t cur);

const char *acpi_device_path_join(const struct device *dev, const char *name)
{
        static char buf[DEVICE_PATH_MAX] = {};
        size_t len;
        if (!dev)
                return NULL;

        &amp;#x2F;* Build the path of this device *&amp;#x2F;
        len = acpi_device_path_fill(dev, buf, sizeof(buf), 0);
        if (len &amp;lt;= 0)
                return NULL;
        ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the function prototype right there, the problem is obvious: &lt;code&gt;acpi_device_path_fill()&lt;&#x2F;code&gt; returns negative values in a &lt;code&gt;ssize_t&lt;&#x2F;code&gt; to indicate errors, but &lt;code&gt;len&lt;&#x2F;code&gt; is a &lt;code&gt;size_t&lt;&#x2F;code&gt;, so all those negative error values are converted to extremely large integers, thus passing the subsequent error check. During code review this may not at all be obvious though.&lt;&#x2F;p&gt;
&lt;p&gt;Both these errors could be prevented using the &lt;code&gt;-Wconversion&lt;&#x2F;code&gt; compiler option, which will warn about all implicit integer conversions. However, there are an incredible number of such conversions in coreboot, and it would be a mammoth task to fix them all.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;null-pointers&quot;&gt;Null Pointers&lt;&#x2F;h3&gt;
&lt;p&gt;Null pointers need no introduction—they are well known to cause all sorts of problems. For a simple example, let’s take a look at &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33134&quot;&gt;CB:33134&lt;&#x2F;a&gt; from the HiFive Unleashed mainboard.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;static void fixup_fdt(void *unused)
{
        void *fdt_rom;
        struct device_tree *tree;

        &amp;#x2F;* load flat dt from cbfs *&amp;#x2F;
        fdt_rom = cbfs_boot_map_with_leak(&amp;quot;fallback&amp;#x2F;DTB&amp;quot;, CBFS_TYPE_RAW, NULL);

        &amp;#x2F;* Expand DT into a tree *&amp;#x2F;
        tree = fdt_unflatten(fdt_rom);
        ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code attempts to load a device tree from a location in the CBFS. However, &lt;code&gt;cbfs_boot_map_with_leak()&lt;&#x2F;code&gt; will return a null pointer if the object in the CBFS can’t be found, which will then be dereferenced in the call to &lt;code&gt;fdt_unflatten()&lt;&#x2F;code&gt;. On most systems dereferencing a null pointer will lead to a segfault, since the operating system has set up permissions that prevent accessing the memory at address 0. However, coreboot runs before the operating systems has even started, so there are no memory permissions at all! If &lt;code&gt;fdt_rom&lt;&#x2F;code&gt; is a null pointer, &lt;code&gt;fdt_unflatten()&lt;&#x2F;code&gt; will attempt to expand the device tree from whatever memory is at address 0, leading to who knows what problems. A simple null check will avoid this, but requires the programmer to always remember to put them in.&lt;&#x2F;p&gt;
&lt;p&gt;Another common issues with null pointers is that even if you do a check, it might not actually matter if the pointer has already been dereferenced. For example, here is a problem with the EDID parser in &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;32055&quot;&gt;CB:32055&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;int decode_edid(unsigned char *edid, int size, struct edid *out)
{
        ...
        dump_breakdown(edid);

        memset(out, 0, sizeof(*out));

        if (!edid || memcmp(edid, &amp;quot;\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00&amp;quot;, 8)) {
                printk(BIOS_SPEW, &amp;quot;No header found\n&amp;quot;);
                return EDID_ABSENT;
        }
        ...
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case the EDID is dumped before doing the null pointer check, but at worst there should only be a wonky dump if &lt;code&gt;edid&lt;&#x2F;code&gt; is null, right? Not necessarily. Since dereferencing a null pointer is undefined behavior, the compiler is allowed to assume that &lt;em&gt;no null pointer dereferences occur in the program&lt;&#x2F;em&gt;. In this case, dereferencing the &lt;code&gt;edid&lt;&#x2F;code&gt; pointer in &lt;code&gt;dump_breakdown()&lt;&#x2F;code&gt; is an implicit assertion that &lt;code&gt;edid&lt;&#x2F;code&gt; is not null, so an over-zealous compiler could remove the following null check! This optimization can be disabled using &lt;code&gt;-fno-delete-null-pointer-checks&lt;&#x2F;code&gt; (which is done in coreboot), but does not prevent any problems that could have happened in the null dereference before the check took place. See this article in &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;342330&#x2F;&quot;&gt;LWN&lt;&#x2F;a&gt; for details on how a vulnerability from this problem was dealt with in the Linux kernel.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;C has always had the mantra of “trust the programmer”, which makes mistakes and errors very easy to do. Some of these errors can be prevented at compile time using compiler warnings, but many cannot. Coverity and other static analyzers like it are very useful and powerful tools for catching bugs that slip past the compiler and through peer review. However, it is no silver bullet. All of these errors were present in production code that were only caught after the fact, and there are certainly bugs of this sort left that Coverity hasn’t found. What do we do about them, and how can we ever be sure that we’ve caught them all? Today, there are new languages designed from the beginning to enable safe and correct programming. For example, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreboot&#x2F;libgfxinit&quot;&gt;libgfxinit&lt;&#x2F;a&gt; is written in SPARK, a subset of Ada that can be formally verified at compile time to avoid essentially all of the above errors. There is also the new &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;oreboot&#x2F;oreboot&quot;&gt;oreboot&lt;&#x2F;a&gt; project written in Rust, which has similar compile time guarantees due to its extensive type system. I hope to see these languages and others increasingly used in the future so that at some point, this job will have become obsolete. 🙂&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Weeks 11–12</title>
        <published>2019-08-16T00:00:00+00:00</published>
        <updated>2019-08-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks11-12/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks11-12/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks11-12/">&lt;p&gt;Hello again! For the past two weeks I have been working on Coverity issues in various third party repositories, notably &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;flashrom?tab=overview&quot;&gt;flashrom&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;vboot?tab=overview&quot;&gt;vboot&lt;&#x2F;a&gt;. The majority of issues in both repositories are now fixed, with the remaining ones mostly being memory leaks. Also, support for &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;riscv&#x2F;opensbi&quot;&gt;OpenSBI&lt;&#x2F;a&gt; (a RISC-V supervisor binary interface) was recently added to coreboot, and Coverity picked up &lt;a href=&quot;https:&#x2F;&#x2F;lists.infradead.org&#x2F;pipermail&#x2F;opensbi&#x2F;2019-August&#x2F;000350.html&quot;&gt;several issues&lt;&#x2F;a&gt; in that. With one more week left in the summer, the plan now is to tidy up the last few remaining issues in vboot, and shepherd my still in-progress patches through review. As usual, you can see the current status of my patches on &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;owner:jgarber1%2540ualberta.ca&quot;&gt;Gerrit&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Following up from my post last week about neutralizing the ME, this week I decided to try replacing SeaBIOS with GRUB. While originally designed as a bootloader, GRUB can be compiled as a coreboot payload, which removes the need of having a BIOS or UEFI interface at all. Not only does this mean having a legacy-free boot process, but GRUB also has an incredible amount of flexibility over the previous systems. For example, one problem with current full disk encryption schemes is that the bootloader must always remain unencrypted, since factory BIOS&#x2F;UEFI implementations are unable of unlocking encrypted disks. By embedding GRUB in the coreboot image we can move it off the hard drive and avoid this problem entirely.&lt;&#x2F;p&gt;
&lt;p&gt;With this in mind, I decided to try installing GRUB on a system with a single LUKS 1 partition formatted with Btrfs. (GRUB currently doesn’t support LUKS 2, which is what many distributions use by default.) This setup will require two configuration files: one embedded in the coreboot image with instructions on how to unlock the partition, and one on the hard drive for booting the kernel. The first configuration file has to be hand-written, while the second can be generated using &lt;code&gt;grub-mkconfig -o &#x2F;boot&#x2F;grub&#x2F;grub.cfg&lt;&#x2F;code&gt;. The advantage of this two-stage system is that the first configuration file only has to be flashed once, and then all subsequent changes (e.g. adding kernel parameters) can be done with the system file. After tinkering around with the official GRUB &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;grub&#x2F;manual&#x2F;grub&#x2F;grub.html&quot;&gt;documentation&lt;&#x2F;a&gt;, the &lt;a href=&quot;https:&#x2F;&#x2F;www.coreboot.org&#x2F;GRUB2&quot;&gt;coreboot wiki&lt;&#x2F;a&gt;, and this &lt;a href=&quot;https:&#x2F;&#x2F;bisco.org&#x2F;notes&#x2F;coreboot-on-the-x230&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt;, I pieced together the following bare-bones config file for the payload:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# Tell GRUB where to find its modules
set prefix=(memdisk)&amp;#x2F;boot&amp;#x2F;grub

# Keep the same screen resolution when switching to Linux
set gfxpayload=keep

# I&amp;#x27;m not exactly sure what these do, but they look important
terminal_output --append cbmemc
terminal_output --append gfxterm

# Default to first option, automatically boot after 3 seconds
set default=&amp;quot;0&amp;quot;
set timeout=3

# Enable the pager when viewing large files
set pager=1

menuentry &amp;#x27;Load Operating System&amp;#x27; {

        # Load the LUKS and Btrfs modules
        insmod luks
        insmod btrfs

        # Unlock all crypto devices (should only be one)
        cryptomount -a

        # Load the system GRUB file from the first crypto device
        set root=(crypto0)
        configfile &amp;#x2F;boot&amp;#x2F;grub&amp;#x2F;grub.cfg
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using &lt;code&gt;menuconfig&lt;&#x2F;code&gt;, we can now configure coreboot to use GRUB as a payload.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Payload ---&amp;gt; Add a Payload ---&amp;gt; GRUB2
        ---&amp;gt; GRUB2 version ---&amp;gt; 2.04
        ---&amp;gt; Extra modules to include in GRUB image
             (luks btrfs gcry_sha256 gcry_rijndael all_video cat)
             [*] Include GRUB2 runtime config file into ROM image
                 (grub.cfg)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We need to add a few modules to the GRUB image to enable all the features we want: &lt;code&gt;luks&lt;&#x2F;code&gt; and &lt;code&gt;btrfs&lt;&#x2F;code&gt; are self-explanatory, &lt;code&gt;gcry_sha256&lt;&#x2F;code&gt; and &lt;code&gt;gcry_rijndael&lt;&#x2F;code&gt; add support for SHA256 and AES (the default hash and cipher for LUKS), &lt;code&gt;all_video&lt;&#x2F;code&gt; adds support for more video and graphics drivers, and &lt;code&gt;cat&lt;&#x2F;code&gt; is useful for printing config files during debugging. We also set here the path to the above &lt;code&gt;grub.cfg&lt;&#x2F;code&gt; file, which by default is in the root of the coreboot tree.&lt;&#x2F;p&gt;
&lt;p&gt;After flashing the new coreboot image, you will be greeted by two GRUB menus after booting: the above one for unlocking the partition, and then the system one for booting the kernel.&lt;&#x2F;p&gt;
&lt;p&gt;The above GRUB config file is extremely basic, and although all advanced functionality can be done manually by dropping to the GRUB command line, this is very inconvenient. Let’s add two menu entries to the config file for shutting down and rebooting the system. Fortunately, this can be done without rebuilding the ROM from scratch. By default, the GRUB config file is stored as &lt;code&gt;etc&#x2F;grub.cfg&lt;&#x2F;code&gt; in the &lt;a href=&quot;https:&#x2F;&#x2F;www.coreboot.org&#x2F;CBFS&quot;&gt;CBFS&lt;&#x2F;a&gt; (coreboot file system), which is used to store objects in the coreboot image. We can print the layout of the CBFS using the &lt;code&gt;cbfstool&lt;&#x2F;code&gt; utility:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ cbfstool coreboot.rom print
FMAP REGION: COREBOOT
Name                           Offset     Type           Size   Comp
cbfs master header             0x0        cbfs header        32 none
fallback&amp;#x2F;romstage              0x80       stage           58068 none
cpu_microcode_blob.bin         0xe3c0     microcode      122880 none
fallback&amp;#x2F;ramstage              0x2c440    stage          105072 none
config                         0x45f00    raw               488 none
revision                       0x46140    raw               674 none
cmos.default                   0x46440    cmos_default      256 none
vbt.bin                        0x46580    raw              1412 LZMA (3863 decompressed)
cmos_layout.bin                0x46b40    cmos_layout      1808 none
fallback&amp;#x2F;postcar               0x472c0    stage           18540 none
fallback&amp;#x2F;dsdt.aml              0x4bb80    raw             15257 none
fallback&amp;#x2F;payload               0x4f780    simple elf     470937 none
etc&amp;#x2F;grub.cfg                   0xc2780    raw               670 none
(empty)                        0xc2a80    null          7523608 none
bootblock                      0x7ef7c0   bootblock        1512 none
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This shows all the objects located in the image, including the stages (bootblock, romstage, ramstage, and payload) and various other configuration files and binaries. Next, we extract the existing config file from this image:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ cbfstool coreboot.rom extract -n etc&amp;#x2F;grub.cfg -f grub.cfg
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now add the following two entries to the end of the extracted file:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;menuentry &amp;#x27;Poweroff&amp;#x27; {
        halt
}

menuentry &amp;#x27;Reboot&amp;#x27; {
        reboot
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we delete the existing configuration file, and then add our new one back in:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ cbfstool coreboot.rom remove -n etc&amp;#x2F;grub.cfg
$ cbfstool coreboot.rom add -n etc&amp;#x2F;grub.cfg -f grub.cfg -t raw
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s it! Flash back the new ROM, and you’re good to go.&lt;&#x2F;p&gt;
&lt;p&gt;Even with these changes, we still have a very basic configuration file. For more advanced setups (such as booting from a live USB, LVM support, signing kernels with GPG, etc.) I recommend looking at the comprehensive &lt;a href=&quot;https:&#x2F;&#x2F;notabug.org&#x2F;libreboot&#x2F;libreboot&#x2F;src&#x2F;master&#x2F;resources&#x2F;grub&#x2F;config&#x2F;menuentries&#x2F;common.cfg&quot;&gt;Libreboot&lt;&#x2F;a&gt; GRUB file and its &lt;a href=&quot;https:&#x2F;&#x2F;libreboot.org&#x2F;docs&#x2F;gnulinux&#x2F;grub_hardening.html&quot;&gt;hardening guide&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Weeks 8–10</title>
        <published>2019-08-07T00:00:00+00:00</published>
        <updated>2019-08-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks8-10/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks8-10/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks8-10/">&lt;p&gt;Hello everyone! Coverity has come back online again after its long upgrade, and with it a pile of new scan issues (over 100). I put aside a week to fix all the new issues in parts of the code base I had already worked through, and then spent the next two weeks finishing soc and the Cavium vendorcode. Referring to the &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;coreboot?tab=overview&quot;&gt;overview page&lt;&#x2F;a&gt;, there are now 300 scan issues left in the code base. While a considerable number, this consists almost entirely of patches still going through review, vboot, and the AMD vendorcode—everything outside of this is done. At this point, the plan at the beginning of the summer was to continue working on the AMD vendorcode, but after discussing with my mentors we have decided to do something else. The AMD vendorcode is extremely dense, and with the upcoming deprecations in 4.11 it may not be around for much longer. The plan now is to work on &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;vboot?tab=overview&quot;&gt;vboot&lt;&#x2F;a&gt; and the recently resurrected scan page for &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;flashrom?tab=overview&quot;&gt;flashrom&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, enough with the boring schedule stuff. I finally got around this week to wiping the ME on my T500, and like last time it was a lot more involved than I expected. Onwards!&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Intel_Management_Engine&quot;&gt;Intel Management Engine&lt;&#x2F;a&gt; (ME) is an autonomous coprocessor integrated into all Intel chipsets since 2006. Providing the basis for Intel features such as &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Intel_Active_Management_Technology&quot;&gt;AMT&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;mjg59.dreamwidth.org&#x2F;33981.html&quot;&gt;Boot Guard&lt;&#x2F;a&gt;, and Protected Audio Video Path (used for DRM), the ME has complete access to the system memory and networking. The ME runs continuously as long as the system has power, even if the computer is asleep or turned off, and on systems with AMT can even be accessed remotely. Naturally, this is an incredible security risk. On modern systems it is impossible to disable the ME completely, since any attempt to do so will start a watchdog timer that will shutdown the computer after 30 minutes. However, in older chipsets (such as the one in the T500), no such timer exists, allowing attempts to disable it entirely.&lt;&#x2F;p&gt;
&lt;p&gt;The ME firmware is located in the SPI flash chip, which is divided into multiple regions. Using the coreboot utility &lt;code&gt;ifdtool&lt;&#x2F;code&gt;, we can analyze a dumped ROM to check the regions in the layout along with their offsets within the flash image.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ ifdtool -f layout.txt factory.rom
File factory.rom is 8388608 bytes
Wrote layout to layout.txt
$ cat layout.txt
00000000:00000fff fd
00600000:007fffff bios
00001000:005f5fff me
005f6000:005f7fff gbe
005f8000:005fffff pd
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These regions are as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Intel Flash Descriptor (&lt;code&gt;fd&lt;&#x2F;code&gt;) – Describes the layout of the rest of the flash chip, as well as various chipset configuration options. This &lt;a href=&quot;https:&#x2F;&#x2F;blogs.coreboot.org&#x2F;blog&#x2F;2019&#x2F;06&#x2F;25&#x2F;gsoc-ghidra-firmware-utilities-week-5&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; by Alex James has further information about the IFD.&lt;&#x2F;li&gt;
&lt;li&gt;BIOS (&lt;code&gt;bios&lt;&#x2F;code&gt;) – Contains the factory BIOS. Normally this is the only part of the flash chip that you overwrite when installing coreboot.&lt;&#x2F;li&gt;
&lt;li&gt;Management Engine (&lt;code&gt;me&lt;&#x2F;code&gt;) – Firmware for the ME coprocessor, including a kernel (ThreadX on older models, MINIX 3 on newer ones), as well as a variety of other modules for network access and remote management.&lt;&#x2F;li&gt;
&lt;li&gt;Gigabit Ethernet (&lt;code&gt;gbe&lt;&#x2F;code&gt;) – Configuration for the Gigabit Ethernet controller, including the system’s MAC address.&lt;&#x2F;li&gt;
&lt;li&gt;Platform Data (&lt;code&gt;pd&lt;&#x2F;code&gt;) – Other miscellaneous data for the factory BIOS, which coreboot doesn’t use.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The IFD also contains read and write permissions for the rest of the flash chip, which we can analyze using &lt;code&gt;ifdtool&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ ifdtool -d factory.rom
...
FLMSTR1:   0x1a1b0000 (Host CPU&amp;#x2F;BIOS)
   Platform Data Region Write Access: enabled
   GbE Region Write Access:           enabled
   Intel ME Region Write Access:      disabled
   Host CPU&amp;#x2F;BIOS Region Write Access: enabled
   Flash Descriptor Write Access:     disabled
   Platform Data Region Read Access:  enabled
   GbE Region Read Access:            enabled
   Intel ME Region Read Access:       disabled
   Host CPU&amp;#x2F;BIOS Region Read Access:  enabled
   Flash Descriptor Read Access:      enabled
   Requester ID:                      0x0000
...
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unfortunately, ME write access is disabled for the host CPU, which prevents us from overwriting it using an internal flash—we’re gonna have to get out the external programmer. If you recall from last time, accessing the SOIC of the T500 required a laborious process of extracting the motherboard from the case, so this time I cut a little hole in the frame to make flashing easier. As it turned out, having this easy access port was very handy.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;flash-1.jpg&quot; alt=&quot;BeagleBone Black with Pomona clip attached to T500 motherboard&quot;&gt;
  &lt;figcaption&gt;The old way.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;hole-1.jpg&quot; alt=&quot;Hole cut in T500 frame to expose SOIC chip&quot;&gt;
  &lt;figcaption&gt;The new—a bit hacky, but it works.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;After reading back the ROM image, I decided to use try using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;corna&#x2F;me_cleaner&quot;&gt;me_cleaner&lt;&#x2F;a&gt;, a tool for partially deblobbing the ME firmware on newer laptops, and for mine removing it entirely. Following the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;corna&#x2F;me_cleaner&#x2F;wiki&#x2F;External-flashing&quot;&gt;instructions&lt;&#x2F;a&gt; for an external flash, we use the &lt;code&gt;-S&lt;&#x2F;code&gt; flag to clean the firmware.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ python me_cleaner.py -S -O coreboot-nome.rom coreboot-orig.rom
Full image detected
Found FPT header at 0x1010
Found 13 partition(s)
Found FTPR header: FTPR partition spans from 0xd2000 to 0x142000
ME&amp;#x2F;TXE firmware version 4.1.3.1038 (generation 1)
Public key match: Intel ME, firmware versions 4.x.x.x
The meDisable bit in ICHSTRP0 is NOT SET, setting it now...
The meDisable bit in MCHSTRP0 is NOT SET, setting it now...
Disabling the ME region...
Wiping the ME region...
Done! Good luck!
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After wiping the image, we can use &lt;code&gt;ifdtool&lt;&#x2F;code&gt; again to see that the ME region has been completely erased.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;00000000:00000fff fd
00600000:007fffff bios
005f6000:005f7fff gbe
005f8000:005fffff pd
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this is the most sure-fire way to ensure the ME has been disabled, it’s not perfect—on boot the ME coprocessor will still attempt to read from its firmware in the flash region, and finding it not there will hang in an error state. However, it has been discovered through reverse engineering that Intel has incorporated various &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;corna&#x2F;me_cleaner&#x2F;wiki&#x2F;HAP-AltMeDisable-bit&quot;&gt;bits&lt;&#x2F;a&gt; into the IFD that will disable the ME soon after boot. (One of these, the &lt;a href=&quot;http:&#x2F;&#x2F;blog.ptsecurity.com&#x2F;2017&#x2F;08&#x2F;disabling-intel-me.html&quot;&gt;High Assurance Platform&lt;&#x2F;a&gt; “HAP” bit, was incorporated at the request of the US government, which also understands the security risks of an unfettered ME.) For my laptop, this consists of setting two bits in the &lt;code&gt;ICHSTRP&lt;&#x2F;code&gt; and &lt;code&gt;MCHSTRP&lt;&#x2F;code&gt;, which &lt;code&gt;me_cleaner&lt;&#x2F;code&gt; does by default. After enabling this, the ME should gracefully shutdown after boot, which hopefully will cause the fewest system stability issues.&lt;&#x2F;p&gt;
&lt;p&gt;Finally after all that, let’s use &lt;code&gt;ifdtool&lt;&#x2F;code&gt; again to unlock all regions of the flash chip, which should ideally negate the need of ever doing an external flash again.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ ifdtool -u coreboot-nome.rom
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s write it! Unlike last time we write the entire image, not just the BIOS region.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ flashrom -p linux_spi:dev=&amp;#x2F;dev&amp;#x2F;spidev1.0,spispeed=4096 -w coreboot-nome-unlock.rom
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the moment of truth. After hitting the power button … nothing. Gah.&lt;&#x2F;p&gt;
&lt;p&gt;Well, not exactly nothing. The screen doesn’t turn on, but the CD drive is making noises, so it’s not completely dead. Hmmm, let’s try again, but this time only setting the disable bits without wiping the ME region. This can be done using the &lt;code&gt;-s&lt;&#x2F;code&gt; flag of &lt;code&gt;me_cleaner&lt;&#x2F;code&gt; (which incidentally has a bug that required a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;corna&#x2F;me_cleaner&#x2F;pull&#x2F;288&quot;&gt;small patch&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ python me_cleaner.py -s -O coreboot-nome.rom coreboot-orig.rom
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reflashing again … same problem. Nothing.&lt;&#x2F;p&gt;
&lt;p&gt;Not completely sure what to do and worried that the ME was actually needed to boot, I decided to flash a pre-compiled &lt;a href=&quot;https:&#x2F;&#x2F;libreboot.org&#x2F;docs&#x2F;install&#x2F;t500_external.html&quot;&gt;Libreboot&lt;&#x2F;a&gt; image on the laptop, which has the ME disabled out of the box and should hopefully Just Work. … And it did! The computer booted gracefully into the OS with no glitches or stability issues that I could see. Perfect. So disabling the ME is technically possible, but how exactly do I do it? Asking around a bit on IRC, I was directed to the coreboot &lt;code&gt;bincfg&lt;&#x2F;code&gt; utility, which is capable of generating an ME-less IFD from scratch. Following this &lt;a href=&quot;https:&#x2F;&#x2F;www.coreboot.org&#x2F;Board:lenovo&#x2F;x200#Without_ME_firmware_updates.2FAMT&quot;&gt;similar guide&lt;&#x2F;a&gt; for the X200, I was able to piece together a complete ROM.&lt;&#x2F;p&gt;
&lt;p&gt;First, we need to generate a new IFD. The &lt;code&gt;bincfg&lt;&#x2F;code&gt; directory contains configuration files for the X200, which we can fortunately re-use since the T500 has the same controller hub.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ bincfg ifd-x200.spec ifd-x200.set ifd.bin
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This IFD comes with only three regions, and has the ME disable bits set by default.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;00000000:00000fff fd
00003000:007fffff bios
00001000:00002fff gbe
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are also configuration files for generating a new GbE region, but that requires certain fiddlings with the MAC address that I don’t know how to do—for now we can re-use the GbE from the old ROM, using &lt;code&gt;ifdtool&lt;&#x2F;code&gt; to chop it out.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ ifdtool -x coreboot-orig.rom
File coreboot-orig.rom is 8388608 bytes
  Flash Region 0 (Flash Descriptor): 00000000 - 00000fff
  Flash Region 1 (BIOS): 00600000 - 007fffff
  Flash Region 2 (Intel ME): 00001000 - 005f5fff
  Flash Region 3 (GbE): 005f6000 - 005f7fff
  Flash Region 4 (Platform Data): 005f8000 - 005fffff
$ mv flashregion_3_gbe.bin gbe.bin
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we place the IFD and GbE regions in a &lt;code&gt;blobs&lt;&#x2F;code&gt; directory in the root of the coreboot tree, and then direct the build system to use them when generating an image. Here are the &lt;code&gt;menuconfig&lt;&#x2F;code&gt; settings:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;General setup ---&amp;gt; [*] Use CMOS for configuration values
              ---&amp;gt; [*] Allow use of binary-only repository
Mainboard ---&amp;gt; Mainboard vendor ---&amp;gt; Lenovo
          ---&amp;gt; Mainboard model ---&amp;gt; ThinkPad T500
          ---&amp;gt; Size of CBFS filesystem in ROM (0x7fd000)
Chipset ---&amp;gt; [*] Add Intel descriptor.bin file (blobs&amp;#x2F;ifd.bin)
        ---&amp;gt; [*] Add gigabit ethernet configuration (blobs&amp;#x2F;gbe.bin)
        ---&amp;gt; Protect flash regions ---&amp;gt; Unlock flash regions
Devices ---&amp;gt; Display ---&amp;gt; Linear &amp;quot;high-resolution&amp;quot; framebuffer
Payloads ---&amp;gt; Add a payload ---&amp;gt; SeaBIOS
         ---&amp;gt; SeaBIOS version ---&amp;gt; master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that since the ME and Platform Data regions have been deleted from the new layout, we can expand the CBFS to the entire &lt;code&gt;bios&lt;&#x2F;code&gt; size—&lt;code&gt;0x7fd000&lt;&#x2F;code&gt; bytes, nearly the entire flash chip. This will allow in the future installing bigger and more interesting payloads, such as &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;grub&#x2F;index.html&quot;&gt;GRUB&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;www.linuxboot.org&#x2F;&quot;&gt;LinuxBoot&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, I wrote this new image to the flash chip. It worked. Huzzah!&lt;&#x2F;p&gt;
&lt;p&gt;After installation, we can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;corna&#x2F;me_cleaner&#x2F;wiki&#x2F;Get-the-status-of-Intel-ME&quot;&gt;check the status&lt;&#x2F;a&gt; of the ME using &lt;code&gt;intelmetool&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo intelmetool -m
Can&amp;#x27;t find ME PCI device
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Weeks 5–7</title>
        <published>2019-07-16T00:00:00+00:00</published>
        <updated>2019-07-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks5-7/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks5-7/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/weeks5-7/">&lt;p&gt;Hello again! It’s been three weeks since my last post (well, one of those weeks I was on vacation, so more like two weeks), so there are many many updates to write about. If you recall from my last post, Coverity has been down for maintenance, so I started looking around for other things to do. Here is a list of some of the highlights:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Coverity isn’t the only static analyzer we use—coreboot also runs &lt;a href=&quot;https:&#x2F;&#x2F;www.coreboot.org&#x2F;scan-build&#x2F;&quot;&gt;nightly scans&lt;&#x2F;a&gt; using the &lt;a href=&quot;https:&#x2F;&#x2F;clang-analyzer.llvm.org&#x2F;&quot;&gt;Clang Static Analyzer&lt;&#x2F;a&gt;, an open source tool from the LLVM project. The results from these scans aren’t as detailed as Coverity and unfortunately contain many duplicates and false positives, but I was able to &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;topic:%22scan-build%22+(status:open%20OR%20status:merged)&quot;&gt;submit patches&lt;&#x2F;a&gt; for some of the issues. Usability of the analyzer is also still somewhat limited, since we have no way of recording fixes for past issues or ignoring false positives. (A framework like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Ericsson&#x2F;codechecker&quot;&gt;CodeChecker&lt;&#x2F;a&gt; might be able to help with this.)&lt;&#x2F;li&gt;
&lt;li&gt;coreboot will (hopefully) soon be (almost) &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33821&quot;&gt;VLA free&lt;&#x2F;a&gt;! &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Variable-length_array&quot;&gt;Variable length arrays&lt;&#x2F;a&gt; (VLAs) were a feature added in C99 that allows the length of an array to be determined at run time, rather than compile time. While convenient, this is also very dangerous, since it allows use of an unlimited amount of stack memory, potentially leading to stack overflow. This is especially dangerous in coreboot, which often has very little stack space to begin with. Fortunately, almost all of the VLAs in coreboot can be replaced with small fixed-sized buffers, aside from one tricky exception that will require a larger rewrite. This patch was inspired by a &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;749064&#x2F;&quot;&gt;similar one&lt;&#x2F;a&gt; for Linux, and is currently under review.&lt;&#x2F;li&gt;
&lt;li&gt;Similar to the above, coreboot will also soon be free of &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34297&quot;&gt;implicit fall throughs&lt;&#x2F;a&gt;! Switches in C have the unfortunate property of each case statement implicitly falling through to the next one, which has led to untold number of bugs over the decades and at least 38 in coreboot itself (by Coverity’s count). GCC however &lt;a href=&quot;https:&#x2F;&#x2F;developers.redhat.com&#x2F;blog&#x2F;2017&#x2F;03&#x2F;10&#x2F;wimplicit-fallthrough-in-gcc-7&#x2F;&quot;&gt;recently added&lt;&#x2F;a&gt; the &lt;code&gt;-Wimplicit-fallthrough&lt;&#x2F;code&gt; warning, which we can use to banish them for good. As of &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34297&quot;&gt;this patch&lt;&#x2F;a&gt;, all accidental fall throughs have been eliminated, with the intentional ones marked with the &lt;code&gt;&#x2F;* fall through *&#x2F;&lt;&#x2F;code&gt; comment. Hopefully this is the last we see of this type of bug.&lt;&#x2F;li&gt;
&lt;li&gt;coreboot now has a &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;34075&quot;&gt;single implementation&lt;&#x2F;a&gt; of &lt;code&gt;&amp;lt;stdint.h&amp;gt;&lt;&#x2F;code&gt;. Previously, each of the six supported architectures (arm, arm64, mips, ppc64, riscv, and x86) had their own custom headers with arch-specific quirks, but now they’ve all been tidied up and merged together. This should make implementing further standard library headers easier to do (such as &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33823&quot;&gt;&lt;code&gt;&amp;lt;inttypes.h&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Finally, many coreboot utilities and tools such as &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;flashrom&#x2F;+&#x2F;33670&#x2F;2&quot;&gt;flashrom&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33866&quot;&gt;coreinfo&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33949&#x2F;2&quot;&gt;nvramtool&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33946&quot;&gt;inteltool&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33861&quot;&gt;ifdtool&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;c&#x2F;coreboot&#x2F;+&#x2F;33853&quot;&gt;cbmem&lt;&#x2F;a&gt; have stricter compiler warnings, mostly from &lt;code&gt;-Wmissing-prototypes&lt;&#x2F;code&gt; and &lt;code&gt;-Wextra&lt;&#x2F;code&gt;. Fixing and adding compiler warnings like these are very easy to do, and make great first time contributions (&lt;code&gt;-Wconversion&lt;&#x2F;code&gt; and &lt;code&gt;-Wsign-compare&lt;&#x2F;code&gt; in particular can always use more work).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That’s it for this week! Thankfully Coverity is back online now, so expect more regular blog posts in the future.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Week 4</title>
        <published>2019-06-20T00:00:00+00:00</published>
        <updated>2019-06-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/week-4/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/week-4/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/week-4/">&lt;p&gt;Hello again! If you recall from my last post, the schedule this week is to fix the issues in &lt;code&gt;northbridge&#x2F;via&lt;&#x2F;code&gt; and &lt;code&gt;southbridge&lt;&#x2F;code&gt;. However, Coverity is going through a major internal upgrade, and so the issue tracker has been offline all week. Luckily though I was able to fix most of these issues last week, so assuming the upgrade finishes soon I won’t be behind schedule. In the mean time, I decided to try flashing coreboot onto my T500, since the last component I was waiting for arrived last week. Here is a little mini-guide to my (sometimes harrowing) flashing experience.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;supplies&quot;&gt;Supplies&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;ThinkPad T500&lt;&#x2F;li&gt;
&lt;li&gt;BeagleBone Black&lt;&#x2F;li&gt;
&lt;li&gt;5V 2A power adapter for the BBB&lt;&#x2F;li&gt;
&lt;li&gt;Jumper Wires&lt;&#x2F;li&gt;
&lt;li&gt;Pomona 5252 Test Clip&lt;&#x2F;li&gt;
&lt;li&gt;Atheros AR9462 Wireless Card&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;updating-the-ec&quot;&gt;Updating the EC&lt;&#x2F;h3&gt;
&lt;p&gt;It is generally recommended to update the embedded controller firmware before flashing coreboot, which can only be done during a Lenovo BIOS update. (Unlike Chromebooks, ThinkPads unfortunately do not have open source EC’s.) I was able to find a copy of the latest BIOS on the &lt;a href=&quot;https:&#x2F;&#x2F;download.lenovo.com&#x2F;eol&#x2F;index.html&quot;&gt;Lenovo EOL Portal&lt;&#x2F;a&gt;, and attempted to perform an update … which froze and crashed halfway through. Uh oh. This is OK, as long as I don’t restart the computer I can just try flashing it again, right? Wrong! The next time I tried it Windows ran into a fatal error and decided to force a restart for me (gah!). Upon booting it up again, I was met with absolutely nothing, because the screen wouldn’t even turn on. More than a little concerned that I had bricked it, I searched through online forums until I stumbled across the &lt;a href=&quot;https:&#x2F;&#x2F;thinkwiki.de&#x2F;BIOS&quot;&gt;Crisis Recovery&lt;&#x2F;a&gt; tool. Apparently, old ThinkPads have a method to force-update the BIOS from an external USB stick or floppy (if you have one of those lying around). The recovery tool had to be run in Windows XP Service Pack 3 emulation mode, and seemed to format the USB correctly. My ThinkPad wasn’t so impressed, and obstinately refused to recognize the stick. As a last hope, I asked around on IRC what to do, and Nico Huber informed me that the ThinkPad was likely &lt;em&gt;not&lt;&#x2F;em&gt; dead, and that I could just proceed with flashing coreboot anyway. Well, here goes nothing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;building-coreboot&quot;&gt;Building Coreboot&lt;&#x2F;h3&gt;
&lt;p&gt;So we’re going to flash coreboot, but what options do I pick when compiling it? I scoured around the internet to find tutorials for flashing coreboot onto a T500 and other related ThinkPads, but they all recommended different options, sometimes contradictory. Hmmmm. Once again going back to IRC, Angel Pons helped me configure a very minimal build.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;General setup ---&amp;gt; [*] Use CMOS for configuration values
              ---&amp;gt; [*] Allow use of binary-only repository
Mainboard ---&amp;gt; Mainboard vendor ---&amp;gt; Lenovo
          ---&amp;gt; Mainboard model ---&amp;gt; ThinkPad T500
Devices ---&amp;gt; Display ---&amp;gt; Linear &amp;quot;high-resolution&amp;quot; framebuffer
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, the T500 is a very special laptop, in that it can run coreboot without any binary blobs at all. However, I decided to enable microcode updates anyway, since they provide important stability improvements (like not crashing). This laptop also comes with an Intel ME which can be completely wiped, but I decided to leave that for later. (Now that I know coreboot works, there will be a follow-up post in several weeks when I do that.)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;disassembly-and-flashing&quot;&gt;Disassembly and Flashing&lt;&#x2F;h3&gt;
&lt;p&gt;Like most laptops, the flash IC of the T500 is locked from the factory, and requires an initial external flash to install coreboot (afterwards, subsequent flashes can be done internally). This requires disassembling the laptop to access the SOIC-16, which is buried in the bowels of the T500 case and requires a complete tear-down to access. The &lt;a href=&quot;https:&#x2F;&#x2F;libreboot.org&#x2F;docs&#x2F;install&#x2F;t500_external.html&quot;&gt;Libreboot T500&lt;&#x2F;a&gt; page gives you a feel for the amount of work required to extract the motherboard, which along with the &lt;a href=&quot;http:&#x2F;&#x2F;tim.id.au&#x2F;laptops&#x2F;lenovo&#x2F;thinkpad%20t500%20w500.pdf&quot;&gt;hardware maintenance manual&lt;&#x2F;a&gt; I referred to extensively.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;mobo-1.jpg&quot; alt=&quot;Motherboard of T500&quot;&gt;
  &lt;figcaption&gt;SOIC-16 highlighted in red&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;With the motherboard extracted from the case, the next step is to attach the Pomona 5252 to the SOIC-16 and jumper it to the BBB, which was all made very easy by this &lt;a href=&quot;https:&#x2F;&#x2F;www.chucknemeth.com&#x2F;flash-lenovo-x200-libreboot&#x2F;&quot;&gt;X200 guide&lt;&#x2F;a&gt;. Somewhat blithely following the previous guide, I set up an old ATX PSU to provide 3.3v to the flash chip. However, whenever I connected it to the test clip, it would always power itself off. Strange. Going back to IRC, Nico informed me that this is in fact A VERY BAD AND DANGEROUS THING TO DO. THE INTERNET IS LYING—DO NOT USE AN ATX PSU, YOU COULD FRY YOUR MOTHERBOARD! Oops. After puzzling over how to provide enough power to the chip without the PSU, Patrick Rudolph chimed in that a) the T500 motherboard is basically indestructible (whew!), and b) the flasher itself should be able to provide enough power. Hooking the 3.3v cable into the BBB instead, I tried reading the flash chip.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ flashrom -p linux_spi:dev=&amp;#x2F;dev&amp;#x2F;spidev1.0,spispeed=512
(a bunch of output that I forgot to write down)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It works! Even with a bricked Lenovo BIOS, it is still recommended to keep a backup, so next we read the old factory ROM.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ flashrom -p linux_spi:dev=&amp;#x2F;dev&amp;#x2F;spidev1.0,spispeed=512 -r factory.rom
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do this three times with three distinct images, and compare their SHAsums to make sure they are all identical (otherwise the connection might be faulty). If they all match, keep one as a backup.&lt;&#x2F;p&gt;
&lt;p&gt;Now the moment of truth: writing coreboot.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;$ flashrom -p linux_spi:dev=&amp;#x2F;dev&amp;#x2F;spidev1.0,spispeed=512 --ifd -i bios -w coreboot.rom
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that because I left the ME as-is, it is important to only flash the BIOS region, not the entire chip.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;reassembly-and-testing&quot;&gt;Reassembly and Testing&lt;&#x2F;h3&gt;
&lt;p&gt;Sadly, no instant gratification here—I had to reassemble half the laptop before I could test booting it up. However, after doing so and gingerly pressing the power button, I was greeted by the lovely SeaBIOS boot menu. It actually worked! Huzzah! Finishing reassembly, I replaced the factory Intel wireless card with an Atheros AR9462, which can run without any binary firmware. After installing Debian, I now have a laptop running completely free and open source software, all the way from the BIOS up (well, except for the ME, but I’ll fix that later).&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;debian-1.jpg&quot; alt=&quot;T500 running coreboot and Debian 9&quot;&gt;
  &lt;figcaption&gt;T500 running coreboot and Debian 9&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;For the final icing on the cake, here is a fresh &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;cgit&#x2F;board-status.git&#x2F;commit&#x2F;?id=6913ba86db89fc2fe2ba3cc53f5dc2394ab92fa4&quot;&gt;board status&lt;&#x2F;a&gt; report for the T500. Many thanks to everyone who helped me in this process.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Week 3</title>
        <published>2019-06-13T00:00:00+00:00</published>
        <updated>2019-06-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/week-3/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/week-3/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/week-3/">&lt;p&gt;Hello again! This is a continuation of my posts about fixing the Coverity issues in coreboot. This week’s plan was to tackle the 28 issues in &lt;code&gt;northbridge&#x2F;intel&lt;&#x2F;code&gt;, which turned out to be much easier than I expected, since I’m already done! With that out of the way, I’m going to begin working on &lt;code&gt;northbridge&#x2F;via&lt;&#x2F;code&gt; and &lt;code&gt;southbridge&lt;&#x2F;code&gt;. For the curious, here is the project timeline for entire summer.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Week&lt;&#x2F;th&gt;&lt;th&gt;Components&lt;&#x2F;th&gt;&lt;th&gt;Issues&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;May 6 to 10&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;util&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;22&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;May 13 to 17&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;util, payloads&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;22&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;May 20 to 24&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;arch, drivers&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;May 27 to 31&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;commonlib, cpu, lib, mainboard&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;22&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;June 3 to 7&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;northbridge&#x2F;amd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;21&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;June 10 to 14&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;northbridge&#x2F;intel&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;28&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;June 17 to 21&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;northbridge&#x2F;via, southbridge&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;22&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;June 24 to 28&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;soc&#x2F;intel&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;21&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;July 1 to 5&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;soc&#x2F;rockchip, soc&#x2F;nvidia&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;July 15 to 19&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;soc&#x2F;misc, vendorcode&#x2F;cavium&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;26&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;July 22 to 26&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;vendorcode&#x2F;amd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;21&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;July 29 to Aug 2&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;vendorcode&#x2F;amd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;21&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Aug 5 to 9&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;vendorcode&#x2F;amd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Aug 12 to 16&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;vendorcode&#x2F;amd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Aug 19 to 23&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;vendorcode&#x2F;amd&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;As you can see, there are &lt;em&gt;a lot&lt;&#x2F;em&gt; of issues in the AMD vendorcode. This consists primarily of AGESA, AMD’s framework for initialization of their 64 bit platforms (somewhat similar to Intel’s FSP). This code is somewhat … dense (someone on IRC described it as a “sea of abstraction”), so I made sure to leave plenty of time for it. As always, you can keep up to date on my current progress on &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;Jacob+Garber&quot;&gt;Gerrit&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;PS: As an extra bonus, here is a picture of my new BeagleBone Black!&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;.&#x2F;bbb.jpg&quot; alt=&quot;A BeagleBone Black inside a hard shell&quot;&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;I recently got a ThinkPad T500 to practice installing coreboot on, and I needed some sort of external programmer to flash the SOIC. There are many options available (flashrom has a &lt;a href=&quot;https:&#x2F;&#x2F;www.flashrom.org&#x2F;Supported_programmers&quot;&gt;whole list&lt;&#x2F;a&gt;), but a single-board computer like this is one of the closest you can get to “plug-and-play.” There are many other popular boards (notably the Raspberry Pi), but the BBB doesn’t require any binary blobs to boot, and is &lt;a href=&quot;https:&#x2F;&#x2F;www.oshwa.org&#x2F;&quot;&gt;open source hardware&lt;&#x2F;a&gt; too. The only thing I’m waiting for now is an Atheros ath9k wireless card, which runs without any binary firmware. (Hey, if you’re gonna go freedom, you gotta go all the way.)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introduction</title>
        <published>2019-06-05T00:00:00+00:00</published>
        <updated>2019-06-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/introduction/"/>
        <id>https://www.jwgarber.ca/projects/coreboot/gsoc-2019/introduction/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/projects/coreboot/gsoc-2019/introduction/">&lt;p&gt;Hello everyone! My name is Jacob Garber, and I am a student in this year’s GSoC 2019! My project is on making coreboot Coverity clean. &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;&quot;&gt;Coverity&lt;&#x2F;a&gt; is a free static-analysis tool for open source projects that searches for common coding mistakes and errors, such as buffer overruns, null pointer dereferences, and integer overflow. Coverity automatically analyzes the coreboot codebase and flags issues it finds, and my job is to classify them into bugs and false-positives and patch them if I can. You can check the &lt;a href=&quot;https:&#x2F;&#x2F;scan.coverity.com&#x2F;projects&#x2F;coreboot&quot;&gt;Coverity overview&lt;&#x2F;a&gt; for coreboot, though seeing the issue tracker itself requires registration. At the beginning of the summer, coreboot had over 380 flagged issues, but it’s now down to 303, so we’re making progress! I plan to address 20–30 issues per week depending on the source component, which so far has gone surprisingly well. (Surprising, in the sense that coming into the summer I knew very little about coreboot or firmware development in general.) For the curious, you can see the history and progress of all my changes on &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;Jacob+Garber&quot;&gt;Gerrit&lt;&#x2F;a&gt;. My mentors for this project are Patrick Georgi, Martin Roth, and David Hendricks, who have all been extremely helpful in guiding me through the development process, reviewing my patches, and answering my many questions. Thank you all.&lt;&#x2F;p&gt;
&lt;p&gt;Now, fixing Coverity bugs isn’t the only thing I’d like to do this summer. As I said before, I’d like to learn more about coreboot, and what better way to do that than installing it on a laptop! My current laptop is an old 2011 Macbook Air, which is surprisingly close to getting coreboot support (many thanks to &lt;a href=&quot;https:&#x2F;&#x2F;review.coreboot.org&#x2F;q&#x2F;Evgeny+Zinoviev&quot;&gt;Evgeny Zinoviev&lt;&#x2F;a&gt;). However, I am (slightly) hesitant about installing yet-experimental firmware on my one and only development machine, so until then I picked up an old Thinkpad T500 to practice on. This laptop has the advantage of being able to run blob-free, and if in the very unlikely event I end up bricking it, who cares! (I mean, I’ll care, but it’ll be a worthy sacrifice.) I also bought a &lt;a href=&quot;https:&#x2F;&#x2F;beagleboard.org&#x2F;black&#x2F;&quot;&gt;BeagleBone Black&lt;&#x2F;a&gt; to try out external flashing and was hoping to include a picture today, but the shipping was delayed. You’ll have to wait until next week!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>qsort vs. std::sort</title>
        <published>2016-02-01T00:00:00+00:00</published>
        <updated>2016-02-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.jwgarber.ca/blog/qsort-vs-std-sort/"/>
        <id>https://www.jwgarber.ca/blog/qsort-vs-std-sort/</id>
        
        <content type="html" xml:base="https://www.jwgarber.ca/blog/qsort-vs-std-sort/">&lt;p&gt;When writing high performance code, there are pretty well two options: C and C++.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;C is essentially a portable wrapper around assembly. You can tell exactly how much every action costs, where memory is allocated, and where it is freed. Nothing is hidden. However, because of this direct control, writing C code is very tedious and error prone.&lt;&#x2F;li&gt;
&lt;li&gt;C++ is a bit higher level. You give up some control in exchange for ergonomics. For example, returning a &lt;code&gt;vector&lt;&#x2F;code&gt; from a function is the difference between an O(1) and O(n) operation, depending on if the compiler implements return value optimization. However, C++ templates give the compiler more type information, which it can sometimes use to generate faster code.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A classic example of when C++ outperforms C is sorting. In item 46 of his book &lt;a href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;effective-stl&#x2F;9780321545183&#x2F;&quot;&gt;Effective STL&lt;&#x2F;a&gt;, Scott Meyers claims that &lt;code&gt;std::sort&lt;&#x2F;code&gt; can outperform &lt;code&gt;qsort&lt;&#x2F;code&gt; by up to 670% because C++ will inline the comparison function during template instantiation. Let&#x27;s see how they compare with sorting a vector of a million random integers. Writing and measuring accurate benchmarks is difficult, so we&#x27;re going to let the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libnonius&#x2F;nonius&quot;&gt;Nonius&lt;&#x2F;a&gt; framework do it for us.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;cpp&quot; class=&quot;language-cpp &quot;&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&amp;#x2F;&amp;#x2F; sort.cpp
#define NONIUS_RUNNER
#include &amp;quot;nonius.h++&amp;quot;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;cstdlib&amp;gt;
#include &amp;lt;random&amp;gt;

&amp;#x2F;&amp;#x2F; qsort
static int comp(const void* const a, const void* const b) {
    const int arg1 = *static_cast&amp;lt;const int*&amp;gt;(a);
    const int arg2 = *static_cast&amp;lt;const int*&amp;gt;(b);

    &amp;#x2F;&amp;#x2F; we can&amp;#x27;t simply return a - b, because that might under&amp;#x2F;overflow
    return (arg1 &amp;gt; arg2) - (arg1 &amp;lt; arg2);
}

&amp;#x2F;&amp;#x2F; std::sort with no inlining
struct compare_noinline {
    __attribute__((noinline))
    bool operator()(const int a, const int b) const {
        return a &amp;lt; b;
    }
};

&amp;#x2F;&amp;#x2F; std::sort with inlining
struct compare {
    &amp;#x2F;&amp;#x2F; the compiler will inline this automatically
    bool operator()(const int a, const int b) const {
        return a &amp;lt; b;
    }
};

static std::vector&amp;lt;int&amp;gt; random_vector(const size_t size) {

    std::random_device seed{};
    std::default_random_engine engine{seed()};
    std::uniform_int_distribution&amp;lt;int&amp;gt; dist{std::numeric_limits&amp;lt;int&amp;gt;::min(),
                                            std::numeric_limits&amp;lt;int&amp;gt;::max()};

    std::vector&amp;lt;int&amp;gt; vec(size);
    std::generate(vec.begin(), vec.end(), [&amp;amp;]{ return dist(engine); });

    return vec;
}

&amp;#x2F;&amp;#x2F; generate a vector of a million random integers
constexpr size_t size = 1&amp;#x27;000&amp;#x27;000;
static const auto rand_vec = random_vector(size);

NONIUS_BENCHMARK(&amp;quot;qsort&amp;quot;, [](nonius::chronometer meter) {

    &amp;#x2F;&amp;#x2F; Nonius does multiple runs of the benchmark, and each one needs a new
    &amp;#x2F;&amp;#x2F; copy of the original vector, otherwise we&amp;#x27;d just be sorting the same
    &amp;#x2F;&amp;#x2F; one over and over
    const auto runs = static_cast&amp;lt;size_t&amp;gt;(meter.runs());
    std::vector&amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt; vectors{runs, rand_vec};

    meter.measure([&amp;amp;](const size_t run) {
        auto&amp;amp; current_vec = vectors[run];
        std::qsort(current_vec.data(), current_vec.size(), sizeof(int), comp);
    });
});

NONIUS_BENCHMARK(&amp;quot;std::sort noinline&amp;quot;, [](nonius::chronometer meter) {

    const auto runs = static_cast&amp;lt;size_t&amp;gt;(meter.runs());
    std::vector&amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt; vectors{runs, rand_vec};

    meter.measure([&amp;amp;](const size_t run) {
        auto&amp;amp; current_vec = vectors[run];
        std::sort(current_vec.begin(), current_vec.end(), compare_noinline{});
    });
});

NONIUS_BENCHMARK(&amp;quot;std::sort inline&amp;quot;, [](nonius::chronometer meter) {

    const auto runs = static_cast&amp;lt;size_t&amp;gt;(meter.runs());
    std::vector&amp;lt;std::vector&amp;lt;int&amp;gt;&amp;gt; vectors{runs, rand_vec};

    meter.measure([&amp;amp;](const size_t run) {
        auto&amp;amp; current_vec = vectors[run];
        std::sort(current_vec.begin(), current_vec.end(), compare{});
    });
});
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s compile this bad boy.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;# Apple Clang 8.0.0
# Note that Nonius has a dependency on Boost
$ clang++ -std=c++14 -stdlib=libc++ -O3 -march=native sort.cpp -o sort
$ .&amp;#x2F;sort
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nonius prints out quite a lot of information, so I&#x27;ll summarize the most important bits.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;qsort                253 ms +&amp;#x2F;- 8 ms
std::sort noinline   137 ms +&amp;#x2F;- 6 ms
std::sort inline      88 ms +&amp;#x2F;- 5 ms
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With no inlining, &lt;code&gt;std::sort&lt;&#x2F;code&gt; is already 1.8x faster than &lt;code&gt;qsort&lt;&#x2F;code&gt;. I am unsure why this is, it could be from differences in algorithms. Inlining bumps this up to 2.9x faster: an impressive speedup.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
