Merge ~juliank/shim/+git/shim-signed:alternatives into ~ubuntu-core-dev/shim/+git/shim-signed:master

Proposed by Julian Andres Klode
Status: Needs review
Proposed branch: ~juliank/shim/+git/shim-signed:alternatives
Merge into: ~ubuntu-core-dev/shim/+git/shim-signed:master
Diff against target: 336 lines (+190/-9)
12 files modified
Makefile (+7/-3)
debian/changelog (+18/-0)
debian/control (+2/-2)
debian/kernel-postinst.d/zz-shim (+6/-0)
debian/shim-signed.install (+4/-1)
debian/shim-signed.postinst (+91/-3)
debian/shim-signed.triggers (+1/-0)
debian/tests/control (+3/-0)
debian/tests/test-is-not-revoked (+6/-0)
external-shimaa64.efi.previous (+1/-0)
external-shimx64.efi.previous (+1/-0)
is-not-revoked (+50/-0)
Reviewer Review Type Date Requested Status
Steve Langasek Approve
Ubuntu Stable Release Updates Team Pending
Review via email: mp+436050@code.launchpad.net

Description of the change

A way to ease the pain of key rotation using alternatives

To post a comment you must log in.
Revision history for this message
Julian Andres Klode (juliank) :
Revision history for this message
Julian Andres Klode (juliank) wrote :

on_secure_boot and most of have_non_revoked_kernel are copied from grub-check-signatures (which would fail postinst with a debconf dialog, which is not actually meaningful as the files are unpacked and would be used). We should evaluate unifying things in the future, but this avoids both tying in a grub2 SRU (there is one in progress already) and our is-not-revoked helper can be used for build-time testing.

Revision history for this message
Julian Andres Klode (juliank) wrote :

I need to actually copy in the bugs closed to the changelog but the implementation is ready for reviews now.

be6be0f... by Julian Andres Klode

Release 1.52~ppa7

Revision history for this message
Julian Andres Klode (juliank) :
Revision history for this message
Julian Andres Klode (juliank) wrote :

Regarding the design decisions, please see the ubuntu-devel thread. I think most of the complexity is in actually checking if we are good to install, so this is not a lot more complex than aborting in preinst but means it works fine if kernels and shim are upgraded in the same upgrade run, like setup_alternatives + hooking it into the kernel postinst.d is less code than putting up a debconf dialog with an error message :)

In a month or so, when we're sure everyone has upgraded their kernel we could remove the alternatives again and abort in preinst so that people can find out more easily that they're actually using shim 15.7 and not the old version.

Revision history for this message
Steve Langasek (vorlon) :
review: Needs Fixing
Revision history for this message
Julian Andres Klode (juliank) :
Revision history for this message
Steve Langasek (vorlon) :
review: Approve

Unmerged commits

be6be0f... by Julian Andres Klode

Release 1.52~ppa7

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/Makefile b/Makefile
2index 5c24871..aab638f 100644
3--- a/Makefile
4+++ b/Makefile
5@@ -14,8 +14,9 @@ all:
6 sbattach --attach external-$(EFI_ARCH_LOWER).p7c $(SHIM_VERSION)/$(SHIM_BASE).signed
7
8 # Copy external & dualsigned shims
9- cp $(SHIM_VERSION)/$(SHIM_BASE) build/$(SHIM_BASE).signed
10+ cp $(SHIM_VERSION)/$(SHIM_BASE) build/$(SHIM_BASE).signed.latest
11 cp $(SHIM_VERSION)/$(SHIM_BASE).signed build/$(SHIM_BASE).dualsigned
12+ cp external-shim$(EFI_ARCH_LOWER).efi.previous build/$(SHIM_BASE).signed.previous
13
14 # Move archive signed fb*.efi & mm*.efi
15 mv $(SHIM_VERSION)/$(FB_BASE).signed build/$(FB_BASE)
16@@ -26,13 +27,16 @@ all:
17
18 check:
19 # Verify all signatures
20- sbverify --verbose --cert external.pem build/$(SHIM_BASE).signed
21+ sbverify --verbose --cert external.pem build/$(SHIM_BASE).signed.latest
22+ sbverify --verbose --cert external.pem build/$(SHIM_BASE).signed.previous
23 sbverify --verbose --cert external.pem build/$(SHIM_BASE).dualsigned
24 sbverify --verbose --cert $(SHIM_VERSION)/control/uefi.crt build/$(SHIM_BASE).dualsigned
25 sbverify --verbose --cert $(SHIM_VERSION)/control/uefi.crt build/$(FB_BASE)
26 sbverify --verbose --cert $(SHIM_VERSION)/control/uefi.crt build/$(MM_BASE)
27 # verify sbattach binary output matches the externally-signed binary
28- cmp external-shim$(EFI_ARCH_LOWER).efi build/$(SHIM_BASE).signed
29+ cmp external-shim$(EFI_ARCH_LOWER).efi build/$(SHIM_BASE).signed.latest
30+ # Check that we are not signed with revoked keys
31+ ./is-not-revoked build/$(FB_BASE) build/$(MM_BASE) build/$(SHIM_BASE).dualsigned
32
33 clean:
34 rm -rf build $(SHIM_VERSION) external-$(EFI_ARCH_LOWER).p7c
35diff --git a/debian/changelog b/debian/changelog
36index 1b31422..abed987 100644
37--- a/debian/changelog
38+++ b/debian/changelog
39@@ -1,3 +1,21 @@
40+shim-signed (1.52~ppa7) kinetic; urgency=medium
41+
42+ * New upstream version 15.7 (LP: #1996503)
43+ - SBAT level: shim,3
44+ - SBAT policy bumped to for grub,2 in previous and grub,3 in latest:
45+ SBAT policy: latest="shim,2\ngrub,3\n" previous="grub,2\n"
46+ * SECURITY FIX: Buffer overflow when loading crafted EFI images.
47+ - CVE-2022-28737
48+ * debian/control: Depend on new grub versions (1.191 on lunar+, 1.187.2 elsewhere)
49+ * Break fwupd-signed signed with old keys
50+ * Check for revoked fb,mm binaries in build, grubs, fwupd in autopkgtest
51+ * Install both previous and latest shim as alternatives. On secure boot
52+ systems, if the current kernel or any newer one is revoked, the previous
53+ shim will continue to be used until current kernel and all newer ones
54+ are signed with a non-revoked key.
55+
56+ -- Julian Andres Klode <juliank@ubuntu.com> Thu, 26 Jan 2023 13:03:25 +0100
57+
58 shim-signed (1.51) impish; urgency=medium
59
60 * Update to shim 15.4-0ubuntu9
61diff --git a/debian/control b/debian/control
62index 1ecec76..ae3c7b7 100644
63--- a/debian/control
64+++ b/debian/control
65@@ -9,8 +9,8 @@ Vcs-Browser: https://git.launchpad.net/~ubuntu-core-dev/shim/+git/shim-signed
66
67 Package: shim-signed
68 Architecture: amd64 arm64
69-Depends: ${misc:Depends}, grub-efi-amd64-signed | grub-efi-arm64-signed, grub2-common (>= 2.04-1ubuntu24), mokutil (>= 0.3.0+1538710437.fb6250f-0ubuntu2), sbsigntool
70-Breaks: shim (<< 15.3)
71+Depends: ${misc:Depends}, grub-efi-amd64-signed (>= 1.191~) | grub-efi-arm64-signed (>= 1.191~) | base-files (<< 12.3), grub-efi-amd64-signed (>= 1.187.2~) | grub-efi-arm64-signed (>= 1.187.2~), grub2-common (>= 2.04-1ubuntu24), mokutil (>= 0.3.0+1538710437.fb6250f-0ubuntu2), sbsigntool
72+Breaks: shim (<< 15.3), fwupd-signed (<< 1.44.1~)
73 Replaces: shim (<< 15.3)
74 Recommends: secureboot-db
75 Built-Using: shim (= ${shim:Version})
76diff --git a/debian/kernel-postinst.d/zz-shim b/debian/kernel-postinst.d/zz-shim
77new file mode 100755
78index 0000000..93a41e6
79--- /dev/null
80+++ b/debian/kernel-postinst.d/zz-shim
81@@ -0,0 +1,6 @@
82+#!/bin/sh
83+# Try to update shim alternative if pointing to previous shim
84+if update-alternatives --query shimx64.efi.signed | grep "Best: /usr/lib/shim/shimx64.efi.signed.previous" -q; then
85+ dpkg-trigger shim-kernel-check
86+fi
87+
88diff --git a/debian/shim-signed.install b/debian/shim-signed.install
89index 6037db5..c6179e9 100755
90--- a/debian/shim-signed.install
91+++ b/debian/shim-signed.install
92@@ -4,8 +4,11 @@ build/${SHIM_BASE} /usr/lib/shim
93 build/${FB_BASE} /usr/lib/shim
94 build/${MM_BASE} /usr/lib/shim
95 build/BOOT${EFI_ARCH}.CSV /usr/lib/shim
96-build/${SHIM_BASE}.signed /usr/lib/shim
97+build/${SHIM_BASE}.signed.latest /usr/lib/shim
98+build/${SHIM_BASE}.signed.previous /usr/lib/shim
99 build/${SHIM_BASE}.dualsigned /usr/lib/shim
100 openssl.cnf /usr/lib/shim/mok
101 debian/source_shim-signed.py /usr/share/apport/package-hooks/
102+debian/kernel-postinst.d/zz-shim /etc/kernel/postinst.d/
103 update-secureboot-policy /usr/sbin/
104+is-not-revoked /usr/lib/shim
105diff --git a/debian/shim-signed.postinst b/debian/shim-signed.postinst
106old mode 100644
107new mode 100755
108index ebc0c42..497ba66
109--- a/debian/shim-signed.postinst
110+++ b/debian/shim-signed.postinst
111@@ -4,6 +4,75 @@ set -e
112 # Must load the confmodule for our template to be installed correctly.
113 . /usr/share/debconf/confmodule
114
115+efivars=/sys/firmware/efi/efivars
116+secureboot_var=SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c
117+moksbstatert_var=MokSBStateRT-605dab50-e046-4300-abb6-3dd810dd8b23
118+
119+on_secure_boot() {
120+ # Validate any queued actions before we go try to do them.
121+ local moksbstatert=0
122+
123+ if ! [ -d $efivars ]; then
124+ return 1
125+ fi
126+
127+ if ! [ -f $efivars/$secureboot_var ] \
128+ || [ "$(od -An -t u1 $efivars/$secureboot_var | awk '{ print $NF }')" -ne 1 ]
129+ then
130+ return 1
131+ fi
132+
133+ if [ -f /proc/sys/kernel/moksbstate_disabled ]; then
134+ moksbstatert=$(cat /proc/sys/kernel/moksbstate_disabled 2>/dev/null || echo 0)
135+ elif [ -f $efivars/$moksbstatert_var ]; then
136+ # MokSBStateRT set to 1 means validation is disabled
137+ moksbstatert=$(od -An -t u1 $efivars/$moksbstatert_var | \
138+ awk '{ print $NF; }')
139+ fi
140+
141+ if [ $moksbstatert -eq 1 ]; then
142+ return 1
143+ fi
144+
145+ return 0
146+}
147+
148+# Check that our current kernel and every newer one has not been revoked
149+find_revoked() {
150+ uname_r="$(uname -r)"
151+ exit=1
152+ for kernel in $(ls -1 /boot/vmlinuz-* | sort -V -r); do
153+ # no kernels :(
154+ if [ "$kernel" = "/boot/vmlinuz-*" ]; then
155+ break
156+ fi
157+ this_uname_r="$(echo "$kernel" | sed -r 's#^/boot/vmlinuz-(.*)#\1#; s#\.efi\.signed$##')"
158+ if dpkg --compare-versions "$this_uname_r" lt "$uname_r"; then
159+ continue
160+ fi
161+ if [ -e "$kernel.efi.signed" ]; then
162+ continue
163+ fi
164+ if ! /usr/lib/shim/is-not-revoked "$kernel"; then
165+ exit=0
166+ fi
167+ done
168+ return $exit
169+}
170+
171+setup_alternatives() {
172+ for efi_arch in x64 aa64; do
173+ test -e /usr/lib/shim/shim${efi_arch}.efi.signed.latest || continue
174+ if ! on_secure_boot || ! find_revoked; then
175+ update-alternatives --install /usr/lib/shim/shim${efi_arch}.efi.signed shimx64.efi.signed /usr/lib/shim/shim${efi_arch}.efi.signed.latest 100
176+ update-alternatives --install /usr/lib/shim/shim${efi_arch}.efi.signed shimx64.efi.signed /usr/lib/shim/shim${efi_arch}.efi.signed.previous 50
177+ else
178+ update-alternatives --install /usr/lib/shim/shim${efi_arch}.efi.signed shimx64.efi.signed /usr/lib/shim/shim${efi_arch}.efi.signed.latest 50
179+ update-alternatives --install /usr/lib/shim/shim${efi_arch}.efi.signed shimx64.efi.signed /usr/lib/shim/shim${efi_arch}.efi.signed.previous 100
180+ fi
181+ done
182+}
183+
184 config_item ()
185 {
186 if [ -f /etc/default/grub ]; then
187@@ -54,13 +123,32 @@ case $(dpkg --print-architecture) in
188 grubarch=arm64-efi
189 ;;
190 esac
191-case $1 in
192- triggered)
193+case "$1:$2" in
194+ triggered:shim-secureboot-policy)
195 if [ -e /var/lib/shim-signed/mok/MOK.priv ]; then
196 SHIM_NOTRIGGER=y update-secureboot-policy --enroll-key
197 fi
198 ;;
199- configure)
200+ triggered:shim-kernel-check)
201+ setup_alternatives
202+ # If we did not switch to the latest shim, do not reinstall shim and grub.
203+ if update-alternatives --query shimx64.efi.signed | grep "Best: /usr/lib/shim/shimx64.efi.signed.previous" -q; then
204+ exit 0
205+ fi
206+ bootloader_id="$(config_item GRUB_DISTRIBUTOR | tr A-Z a-z | \
207+ cut -d' ' -f1)"
208+ case $bootloader_id in
209+ kubuntu) bootloader_id=ubuntu ;;
210+ esac
211+ # Check /boot/grub to see if we previously installed to an ESP. We don't
212+ # want to trigger the install code just by installing the package,
213+ # normally the installer installs grub itself first.
214+ if [ -e /boot/grub/${grubarch}/core.efi ]; then
215+ /usr/lib/grub/grub-multi-install --target=${grubarch} --auto-nvram
216+ fi
217+ ;;
218+ configure:*)
219+ setup_alternatives
220 bootloader_id="$(config_item GRUB_DISTRIBUTOR | tr A-Z a-z | \
221 cut -d' ' -f1)"
222 case $bootloader_id in
223diff --git a/debian/shim-signed.triggers b/debian/shim-signed.triggers
224index 2b33128..e3c63ad 100644
225--- a/debian/shim-signed.triggers
226+++ b/debian/shim-signed.triggers
227@@ -1 +1,2 @@
228 interest-noawait shim-secureboot-policy
229+interest-noawait shim-kernel-check
230diff --git a/debian/tests/control b/debian/tests/control
231new file mode 100644
232index 0000000..b3525ab
233--- /dev/null
234+++ b/debian/tests/control
235@@ -0,0 +1,3 @@
236+Tests: test-is-not-revoked
237+Restrictions: allow-stderr, needs-root
238+Depends: shim-signed, grub-efi-amd64-signed | grub-efi-arm64-signed, fwupd-signed, sbsigntool
239diff --git a/debian/tests/test-is-not-revoked b/debian/tests/test-is-not-revoked
240new file mode 100755
241index 0000000..2ab4e63
242--- /dev/null
243+++ b/debian/tests/test-is-not-revoked
244@@ -0,0 +1,6 @@
245+#!/bin/sh
246+exec /usr/lib/shim/is-not-revoked \
247+ /usr/lib/grub/*-signed/*.signed \
248+ /usr/libexec/fwupd/efi/*.efi.signed \
249+ /usr/lib/shim/fb*.efi \
250+ /usr/lib/shim/mm*.efi
251diff --git a/external-shimaa64.efi.previous b/external-shimaa64.efi.previous
252new file mode 120000
253index 0000000..d1dae88
254--- /dev/null
255+++ b/external-shimaa64.efi.previous
256@@ -0,0 +1 @@
257+microsoft-shimaa64.efi.previous
258\ No newline at end of file
259diff --git a/external-shimx64.efi.previous b/external-shimx64.efi.previous
260new file mode 120000
261index 0000000..3b6f052
262--- /dev/null
263+++ b/external-shimx64.efi.previous
264@@ -0,0 +1 @@
265+microsoft-shimx64.efi.previous
266\ No newline at end of file
267diff --git a/is-not-revoked b/is-not-revoked
268new file mode 100755
269index 0000000..1ed1423
270--- /dev/null
271+++ b/is-not-revoked
272@@ -0,0 +1,50 @@
273+#!/bin/bash
274+set -e
275+# we need to set lastpipe so we can read the signers into the signers array below
276+shopt -s lastpipe
277+
278+exit=0
279+
280+quiet=""
281+if [ "$1" = "-q" ]; then
282+ quiet=true
283+ shift
284+fi
285+
286+for signed_binary in "$@"; do
287+ if [ ! -e "$signed_binary" ]; then
288+ echo "E: $signed_binary: file not found">&2
289+ exit=1
290+ continue
291+ fi
292+
293+ sbverify --list "$signed_binary" | grep subject: | grep -E -o "CN=([^/]|\\/)*" | readarray -t signers
294+ if [ -z "$signers" ]; then
295+ echo "E: $signed_binary: Could not finder signing subject, sbverify output follows:">&2
296+ sbverify --list "$signed_binary" >&2
297+ exit=1
298+ continue
299+ fi
300+
301+ for signer in "${signers[@]}"; do
302+ revoked=$(grep -xF "$signer" << EOF
303+CN=Canonical Ltd. Secure Boot Signing
304+CN=Canonical Ltd. Secure Boot Signing (2017)
305+CN=Canonical Ltd. Secure Boot Signing (ESM 2018)
306+CN=Canonical Ltd. Secure Boot Signing (2019)
307+CN=Canonical Ltd. Secure Boot Signing (Ubuntu Core 2019)
308+CN=Canonical Ltd. Secure Boot Signing (2021 v1)
309+CN=Canonical Ltd. Secure Boot Signing (2021 v2)
310+CN=Canonical Ltd. Secure Boot Signing (2021 v3)
311+EOF
312+ ) || true
313+
314+ if [ "$revoked" ]; then
315+ if [ -z "$quiet" ]; then
316+ echo "E: $signed_binary: revoked key $revoked used">&2
317+ fi
318+ exit=1
319+ fi
320+ done
321+done
322+exit $exit
323diff --git a/microsoft-shimaa64.efi b/microsoft-shimaa64.efi
324index c1650a2..ca2da42 100644
325Binary files a/microsoft-shimaa64.efi and b/microsoft-shimaa64.efi differ
326diff --git a/microsoft-shimaa64.efi.previous b/microsoft-shimaa64.efi.previous
327new file mode 100644
328index 0000000..c1650a2
329Binary files /dev/null and b/microsoft-shimaa64.efi.previous differ
330diff --git a/microsoft-shimx64.efi b/microsoft-shimx64.efi
331index e75c6cc..e18de43 100644
332Binary files a/microsoft-shimx64.efi and b/microsoft-shimx64.efi differ
333diff --git a/microsoft-shimx64.efi.previous b/microsoft-shimx64.efi.previous
334new file mode 100644
335index 0000000..e75c6cc
336Binary files /dev/null and b/microsoft-shimx64.efi.previous differ

Subscribers

People subscribed via source and target branches