Hi All,
Following is a brief series to change the F18 kernel over to using the "Rusty" style signed modules. This takes David's 'modsign-rusty' branch and applies it in place of the currently used 'modsign' patch set. There is one notable change I've done, which is to replace David's:
MODSIGN: Sign modules during the build process
patch with a different one. The new patch adds a new 'modules_sign' make target and allows us to still utilize RPM's debuginfo generation with signed modules. I've attached just that patch below for closer review.
To spare people's inboxes, patch 3/3 won't contain the full modsign-rusty-jwb and secure-boot patchsets. Those can be found here:
http://jwboyer.fedorapeople.org/pub/modsign-rusty-jwb.patch http://jwboyer.fedorapeople.org/pub/secure-boot-20120830.patch
Most of the overall change in these patches is dealing with moving some of the modules-extra handling around to make it easier. The rest should be fairly self-explanatory.
I've tested this on both x86_64 and i686/PAE KVM guests using the kernel command line options to verify things. The modules are indeed still signed after install, and the debuginfo seems to still work properly via gdb in that gdb can find the correct .debug files for modules, etc.
Comments/questions welcome.
josh
---
From d992574c734c346760a370b32a28580d47729f7c Mon Sep 17 00:00:00 2001
From: Josh Boyer jwboyer@redhat.com Date: Fri, 14 Sep 2012 11:58:01 -0400 Subject: [PATCH 21/27] MODSIGN: Add modules_sign make target
If CONFIG_MODULE_SIG is set, and 'make modules_sign' is called then this patch will cause the modules to get a signature installed. The make target is intended to be run after 'make modules_install', and will modify the modules in-place in the installed location.
The signature will be appended to the module, along with the payload size, the signature size and a magic string. This requires private and public keys to be available. By default these are expected to be found in PGP keyring files called modsign.sec (the secret key) and modsign.pub (the public key) in the build root.
If signing occurs, lines like the following will be seen:
SIGN [M] <install path>/fs/foo/foo.ko
will appear in the build log. If the signature step will be skipped and the following will be seen:
NO SIGN [M] <install path>/fs/foo/foo.ko
NOTE! After the signature step, the signed module must not be passed through strip. If you wish to strip or otherwise modify the kernel modules, use the built-in stripping capabilities with 'make modules_install' or perform said modifications before calling this make target. This restriction may affect packaging tools (such as rpmbuild) and initramfs composition tools.
Note that I do not agree with this method of attaching signatures to modules. Based on work by David Howells dhowells@redhat.com
Signed-off-by: Josh Boyer jwboyer@redhat.com --- Makefile | 6 +++ scripts/Makefile.modsign | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 scripts/Makefile.modsign
diff --git a/Makefile b/Makefile index a347b81..a708eae 100644 --- a/Makefile +++ b/Makefile @@ -965,6 +965,12 @@ _modinst_post: _modinst_ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst $(call cmd,depmod)
+ifeq ($(CONFIG_MODULE_SIG), y) +PHONY += modules_sign +modules_sign: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign +endif + else # CONFIG_MODULES
# Modules not configured diff --git a/scripts/Makefile.modsign b/scripts/Makefile.modsign new file mode 100644 index 0000000..3ee7d3a --- /dev/null +++ b/scripts/Makefile.modsign @@ -0,0 +1,98 @@ +# ========================================================================== +# Signing modules +# ========================================================================== + +PHONY := __modsign +__modsign: + +include scripts/Kbuild.include + +__modules := $(sort $(shell grep -h '.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) + +PHONY += $(modules) +__modsign: $(modules) + @: + +MODSECKEY = ./modsign.sec +MODPUBKEY = ./modsign.pub +KEYFLAGS = --no-default-keyring --secret-keyring $(MODSECKEY) --keyring $(MODPUBKEY) --no-default-keyring --homedir . --no-options --no-auto-check-trustdb --no-permission-warning + +ifdef CONFIG_MODULE_SIG_SHA1 +KEYFLAGS += --digest-algo=SHA1 +else +ifdef CONFIG_MODULE_SIG_SHA224 +KEYFLAGS += --digest-algo=SHA224 +else +ifdef CONFIG_MODULE_SIG_SHA256 +KEYFLAGS += --digest-algo=SHA256 +else +ifdef CONFIG_MODULE_SIG_SHA384 +KEYFLAGS += --digest-algo=SHA384 +else +ifdef CONFIG_MODULE_SIG_SHA512 +KEYFLAGS += --digest-algo=SHA512 +else +endif +endif +endif +endif +endif + +ifdef MODKEYNAME +KEYFLAGS += --default-key $(MODKEYNAME) +endif + +ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) +ifeq ($(KBUILD_SRC),) + # no O= is being used + SCRIPTS_DIR := scripts +else + SCRIPTS_DIR := $(KBUILD_SRC)/scripts +endif +SIGN_MODULES := 1 +else +SIGN_MODULES := 0 +endif + +# only sign if it's an in-tree module +ifneq ($(KBUILD_EXTMOD),) +SIGN_MODULES := 0 +endif + +ifeq ($(SIGN_MODULES),1) +KEYRING_DEP := modsign.sec modsign.pub +quiet_cmd_sign_ko = SIGN [M] $(2)/$(notdir $@) + cmd_sign_ko = \ + rm -f $(2)/$(notdir $@).sig && \ + gpg --batch --no-greeting $(KEYFLAGS) -b $(2)/$(notdir $@) && \ + ( \ + cat $(2)/$(notdir $@) $(2)/$(notdir $@).sig && \ + stat --printf %-5s $(2)/$(notdir $@).sig && \ + echo -n "This Is A Crypto Signed Module" \ + ) >$(2)/$(notdir $@).signed && \ + mv $(2)/$(notdir $@).signed $(2)/$(notdir $@) && \ + rm -f $(2)/$(notdir $@).sig +else +KEYRING_DEP := +quiet_cmd_sign_ko = NO SIGN [M] $@ + cmd_sign_ko = \ + true +endif + +#quiet_cmd_modules_sign = SIGN $@ +# cmd_modules_sign = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) + +# Modules built outside the kernel source tree go into extra by default +INSTALL_MOD_DIR ?= extra +ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) + +modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) + +$(modules): + $(call cmd,sign_ko,$(MODLIB)/$(modinst_dir)) + +# Declare the contents of the .PHONY variable as phony. We keep that +# # information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY)
--- kernel.spec | 68 +++++++----------------------------------------------------- mod-extra.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 61 deletions(-) create mode 100755 mod-extra.sh
diff --git a/kernel.spec b/kernel.spec index 22184d0..f0b25d1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching @@ -563,6 +563,7 @@ Source11: genkey
Source15: merge.pl Source16: mod-extra.list +Source17: mod-extra.sh
Source19: Makefile.release Source20: Makefile.config @@ -1753,66 +1754,8 @@ BuildKernel() {
rm -f modinfo modnames
- pushd $RPM_BUILD_ROOT/lib/modules/$KernelVer/ - rm -rf modnames - find . -name "*.ko" -type f > modnames - # Look through all of the modules, and throw any that have a dependency in - # our list into the list as well. - rm -rf dep.list dep2.list - rm -rf req.list req2.list - touch dep.list req.list - cp %{SOURCE16} . - for dep in `cat modnames` - do - depends=`modinfo $dep | grep depends| cut -f2 -d":" | sed -e 's/^[ \t]*//'` - [ -z "$depends" ] && continue; - for mod in `echo $depends | sed -e 's/,/ /g'` - do - match=`grep "^$mod.ko" mod-extra.list` ||: - if [ -z "$match" ] - then - continue - else - # check if the module we're looking at is in mod-extra too. if so - # we don't need to mark the dep as required - mod2=`basename $dep` - match2=`grep "^$mod2" mod-extra.list` ||: - if [ -n "$match2" ] - then - continue - #echo $mod2 >> notreq.list - else - echo $mod.ko >> req.list - fi - fi - done - done - - sort -u req.list > req2.list - sort -u mod-extra.list > mod-extra2.list - join -v 1 mod-extra2.list req2.list > mod-extra3.list - - for mod in `cat mod-extra3.list` - do - # get the path for the module - modpath=`grep /$mod modnames` ||: - [ -z "$modpath" ] && continue; - echo $modpath >> dep.list - done - - sort -u dep.list > dep2.list - - # now move the modules into the extra/ directory - for mod in `cat dep2.list` - do - newpath=`dirname $mod | sed -e 's/kernel//extra//'` - mkdir -p $newpath - mv $mod $newpath - done - - rm modnames dep.list dep2.list req.list req2.list - rm mod-extra.list mod-extra2.list mod-extra3.list - popd + # Call the modules-extra script to move things around + %{SOURCE17} $RPM_BUILD_ROOT/lib/modules/$KernelVer %{SOURCE16}
# remove files that will be auto generated by depmod at rpm -i time for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap devname softdep @@ -2321,6 +2264,9 @@ fi # ||----w | # || || %changelog +* Fri Sep 14 2012 Josh Boyer jwboyer@redhat.com +- Move the modules-extra processing to a script + * Fri Sep 14 2012 Dave Jones davej@redhat.com - Fix license tag. (rhbz 450492)
diff --git a/mod-extra.sh b/mod-extra.sh new file mode 100755 index 0000000..115950b --- /dev/null +++ b/mod-extra.sh @@ -0,0 +1,66 @@ +#! /bin/bash + +Dir=$1 +List=$2 + +pushd $Dir +rm -rf modnames +find . -name "*.ko" -type f > modnames +# Look through all of the modules, and throw any that have a dependency in +# our list into the list as well. +rm -rf dep.list dep2.list +rm -rf req.list req2.list +touch dep.list req.list +cp $2 . + +for dep in `cat modnames` +do + depends=`modinfo $dep | grep depends| cut -f2 -d":" | sed -e 's/^[ \t]*//'` + [ -z "$depends" ] && continue; + for mod in `echo $depends | sed -e 's/,/ /g'` + do + match=`grep "^$mod.ko" mod-extra.list` ||: + if [ -z "$match" ] + then + continue + else + # check if the module we're looking at is in mod-extra too. if so + # we don't need to mark the dep as required + mod2=`basename $dep` + match2=`grep "^$mod2" mod-extra.list` ||: + if [ -n "$match2" ] + then + continue + #echo $mod2 >> notreq.list + else + echo $mod.ko >> req.list + fi + fi + done +done + +sort -u req.list > req2.list +sort -u mod-extra.list > mod-extra2.list +join -v 1 mod-extra2.list req2.list > mod-extra3.list + +for mod in `cat mod-extra3.list` +do + # get the path for the module + modpath=`grep /$mod modnames` ||: + [ -z "$modpath" ] && continue; + echo $modpath >> dep.list +done + +sort -u dep.list > dep2.list + +# now move the modules into the extra/ directory +for mod in `cat dep2.list` +do + newpath=`dirname $mod | sed -e 's/kernel//extra//'` + mkdir -p $newpath + mv $mod $newpath +done + +rm modnames dep.list dep2.list req.list req2.list +rm mod-extra.list mod-extra2.list mod-extra3.list +popd
--- kernel.spec | 4 +++- mod-extra-sign.sh | 40 ++++++++++++++++++++++++++++++++++++++++ mod-extra.sh | 14 ++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100755 mod-extra-sign.sh
diff --git a/kernel.spec b/kernel.spec index f0b25d1..f9af46e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching @@ -564,6 +564,7 @@ Source11: genkey Source15: merge.pl Source16: mod-extra.list Source17: mod-extra.sh +Source18: mod-extra-sign.sh
Source19: Makefile.release Source20: Makefile.config @@ -2266,6 +2267,7 @@ fi %changelog * Fri Sep 14 2012 Josh Boyer jwboyer@redhat.com - Move the modules-extra processing to a script +- Add a script to allow us to sign modules in modules-extra
* Fri Sep 14 2012 Dave Jones davej@redhat.com - Fix license tag. (rhbz 450492) diff --git a/mod-extra-sign.sh b/mod-extra-sign.sh new file mode 100755 index 0000000..57a0fb0 --- /dev/null +++ b/mod-extra-sign.sh @@ -0,0 +1,40 @@ +#! /bin/bash + +# We need to sign modules we've moved from <path>/kernel/ to <path>/extra/ +# during mod-extra processing by hand. The 'modules_sign' Kbuild target can +# "handle" out-of-tree modules, but it does that by not signing them. Plus, +# the modules we've moved aren't actually out-of-tree. We've just shifted +# them to a different location behind Kbuild's back because we are mean. + +# This essentially duplicates the 'modules_sign' Kbuild target and runs the +# same commands for those modules. + +moddir=$1 + +modules=`find $moddir -name *.ko` + +MODSECKEY="./modsign.sec" +MODPUBKEY="./modsign.pub" +KEYFLAGS="--no-default-keyring --secret-keyring ${MODSECKEY} --keyring ${MODPUBKEY} --no-default-keyring --homedir . --no-options --no-auto-check-trustdb --no-permission-warning" + +# We need to figure out which --digest-algo= option to pass. Forutnately, we +# can derive that from the config. NOTE: if the config options change names +# we need to rework this. + +DIGEST=`grep CONFIG_MODULE_SIG_.*=y .config | sed -e 's/CONFIG_MODULE_SIG_//' | sed -e 's/=y//'` + +for mod in $modules +do + dir=`dirname $mod` + file=`basename $mod` + + rm -f ${dir}/${file}.sig + gpg --batch --no-greeting ${KEYFLAGS} --digest-algo=${DIGEST} -b ${dir}/${file} + ( + cat ${dir}/${file} ${dir}/${file}.sig && + stat --printf %-5s ${dir}/${file}.sig && + echo -n "This Is A Crypto Signed Module" + ) >${dir}/${file}.signed + mv ${dir}/${file}.signed ${dir}/${file} + rm -f ${dir}/${file}.sig +done diff --git a/mod-extra.sh b/mod-extra.sh index 115950b..d121bd0 100755 --- a/mod-extra.sh +++ b/mod-extra.sh @@ -61,6 +61,20 @@ do mv $mod $newpath done
+popd + +# If we're signing modules, we can't leave the .mod files for the .ko files +# we've moved in .tmp_versions/. Remove them so the Kbuild 'modules_sign' +# target doesn't try to sign a non-existent file. This is kinda ugly, but +# so is modules-extra. + +for mod in `cat ${Dir}/dep2.list` +do + modfile=`basename $mod | sed -e 's/.ko/.mod/'` + rm .tmp_versions/$modfile +done + +pushd $Dir rm modnames dep.list dep2.list req.list req2.list rm mod-extra.list mod-extra2.list mod-extra3.list popd
Hopefully match what gets used upstream
--- kernel.spec | 72 +- modsign-20120816.patch | 10434 ------------------------------------------- modsign-rusty-jwb.patch | 8425 ++++++++++++++++++++++++++++++++++ secure-boot-20120809.patch | 734 --- secure-boot-20120830.patch | 734 +++ 5 files changed, 9219 insertions(+), 11180 deletions(-) delete mode 100644 modsign-20120816.patch create mode 100644 modsign-rusty-jwb.patch delete mode 100644 secure-boot-20120809.patch create mode 100644 secure-boot-20120830.patch
diff --git a/kernel.spec b/kernel.spec index f9af46e..617a69a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching @@ -680,10 +680,10 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch
# crypto/ -Patch900: modsign-20120816.patch +Patch900: modsign-rusty-jwb.patch
# secure boot -Patch1000: secure-boot-20120809.patch +Patch1000: secure-boot-20120830.patch
# Improve PCI support on UEFI Patch1100: handle-efi-roms.patch @@ -1395,10 +1395,10 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch
# crypto/ -ApplyPatch modsign-20120816.patch +ApplyPatch modsign-rusty-jwb.patch
# secure boot -ApplyPatch secure-boot-20120809.patch +ApplyPatch secure-boot-20120830.patch
# Improved PCI support for UEFI ApplyPatch handle-efi-roms.patch @@ -1628,13 +1628,6 @@ BuildKernel() { # we'll get it from the linux-firmware package and we don't want conflicts make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=$KernelVer mod-fw=
-%if %{signmodules} - if [ -z "$(readelf -n $(find fs/ -name *.ko | head -n 1) | grep module.sig)" ]; then - echo "ERROR: modules are NOT signed" >&2; - exit 1; - fi -%endif - %ifarch %{vdso_arches} make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=$KernelVer if [ ! -s ldconfig-kernel.conf ]; then @@ -1758,6 +1751,12 @@ BuildKernel() { # Call the modules-extra script to move things around %{SOURCE17} $RPM_BUILD_ROOT/lib/modules/$KernelVer %{SOURCE16}
+%if %{signmodules} + # Save off the .tmp_versions/ directory. We'll use it in the + # __debug_install_post macro below to sign the right things + cp -r .tmp_versions .tmp_versions.sign${Flavour:+.${Flavour}} +%endif + # remove files that will be auto generated by depmod at rpm -i time for i in alias alias.bin builtin.bin ccwmap dep dep.bin ieee1394map inputmap isapnpmap ofmap pcimap seriomap symbols symbols.bin usbmap devname softdep do @@ -1880,9 +1879,56 @@ find Documentation -type d | xargs chmod u+w # This macro is used by %%install, so we must redefine it before that. %define debug_package %{nil}
+# In the modsign case, we do 3 things. 1) We check the "flavour" and hard +# code the value in the following invocations. This is somewhat sub-optimal +# but we're doing this inside of an RPM macro and it isn't as easy as it +# could be because of that. 2) We restore the .tmp_versions/ directory from +# the one we saved off in BuildKernel above. This is to make sure we're +# signing the modules we actually built/installed in that flavour. 3) We +# grab the arch and invoke 'make modules_sign' and the mod-extra-sign.sh +# commands to actually sign the modules. +# +# We have to do all of those things _after_ find-debuginfo runs, otherwise +# that will strip the signature off of the modules. + %if %{with_debuginfo} %define __debug_install_post \ /usr/lib/rpm/find-debuginfo.sh %{debuginfo_args} %{_builddir}/%{?buildsubdir}\ + if [ "%{signmodules}" == "1" ]; \ + then \ + if [ "%{with_pae}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-PAE.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign.PAE .tmp_versions \ + make ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.PAE \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.PAE/extra/ \ + fi \ + if [ "%{with_debug}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-debug.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign.debug .tmp_versions \ + make ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.debug \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.debug/extra/ \ + fi \ + if [ "%{with_pae_debug}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}-PAEdebug.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign.PAEdebug .tmp_versions \ + make ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL}.PAEdebug \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}.PAEdebug/extra/ \ + fi \ + if [ "%{with_up}" != "0" ]; \ + then \ + Arch=`head -1 configs/kernel-%{version}-%{_target_cpu}.config | cut -b 3-` \ + rm -rf .tmp_versions \ + mv .tmp_versions.sign .tmp_versions \ + make ARCH=$Arch V=1 INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_sign KERNELRELEASE=%{KVERREL} \ + %{SOURCE18} $RPM_BUILD_ROOT/lib/modules/%{KVERREL}/extra/ \ + fi \ + fi \ %{nil}
%ifnarch noarch @@ -2268,6 +2314,8 @@ fi * Fri Sep 14 2012 Josh Boyer jwboyer@redhat.com - Move the modules-extra processing to a script - Add a script to allow us to sign modules in modules-extra +- Switch to using the modsign-rusty code to hopefully match what gets used + upstream
* Fri Sep 14 2012 Dave Jones davej@redhat.com - Fix license tag. (rhbz 450492)
On Mon, Sep 17, 2012 at 10:00:26AM -0400, Josh Boyer wrote:
From d992574c734c346760a370b32a28580d47729f7c Mon Sep 17 00:00:00 2001 From: Josh Boyer jwboyer@redhat.com Date: Fri, 14 Sep 2012 11:58:01 -0400 Subject: [PATCH 21/27] MODSIGN: Add modules_sign make target
Makefile | 6 +++ scripts/Makefile.modsign | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 scripts/Makefile.modsign
This is whitespace mangled for some reason. Sigh. Ignore that part.
josh
kernel@lists.fedoraproject.org