It is becoming more common for systems to only allow signed kernel modules to be loaded (e.g. because the kernel is in "lockdown mode" due to secure boot policies). Users who follow the standard configure / make / install process find that the driver does not work after rebooting and often don't know what is wrong.
This commit teaches the configure script and Makefiles a few new tricks: * Detection of when module signing is required by the system * Detection of existing key and cert used for module signing (Ubuntu only) * Ability to manually specify key, cert, and hash algorithm to be used for module signing * Abort configure if signing is required but not possible * New makefile target to add the signature prior to installing Module signing is opportunistic by default. If a key and cert can be found (or are provided to the configure script), the modules will be signed -- even if not otherwise required. If a key and cert aren't available then we will try to build an unsigned driver instead. If the system is set up to require signed modules, we will cowardly error out of the configure script unless the user explicitly requests the driver to be left unsigned. A phony "signature" Makefile target is provided which is called by `make install` and which is available for developers who want/need to sign the module without actually installing it. Users can use `make && sudo make install` while developers can use `make && sudo make signature`. If module signing is disabled the "signature" target does nothing. --- 2.6.32/Makefile.in | 12 +++++- 2.6.38/Makefile.in | 12 +++++- 3.17/Makefile.in | 12 +++++- 3.7/Makefile.in | 12 +++++- 4.5/Makefile.in | 12 +++++- configure.ac | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 5 deletions(-) diff --git a/2.6.32/Makefile.in b/2.6.32/Makefile.in index 38876be..6290771 100644 --- a/2.6.32/Makefile.in +++ b/2.6.32/Makefile.in @@ -20,6 +20,9 @@ PWD := $(shell pwd) WCM_KERNEL_DIR := @WCM_KERNEL_DIR@ MODUTS := @MODUTS@ WCM_KERNEL_VER := @WCM_KERNEL_VER@ +MODSIGN_HASHALGO := @MODSIGN_HASHALGO@ +MODSIGN_PRIVFILE := @MODSIGN_PRIVFILE@ +MODSIGN_CERTFILE := @MODSIGN_CERTFILE@ all: @echo ' Building input-wacom drivers for $(WCM_KERNEL_VER) kernel.' @@ -28,7 +31,13 @@ all: clean: $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) clean -install modules_install: +signature: all + if test -n "$(MODSIGN_HASHALGO)" -a -n "$(MODSIGN_PRIVFILE)" -a -n "$(MODSIGN_CERTFILE)"; then \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom.ko; \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom_w8001.ko; \ + fi + +install modules_install: signature $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) modules_install mkdir -p /etc/depmod.d echo "override wacom * extra" > /etc/depmod.d/input-wacom.conf @@ -59,5 +68,6 @@ distdir: EMPTY_AUTOMAKE_TARGETS = install-data install-exec uninstall install-info EMPTY_AUTOMAKE_TARGETS += installdirs check dvi pdf ps info html tags ctags mostlyclean maintainer-clean +EMPTY_AUTOMAKE_TARGETS += signature .PHONY: $(EMPTY_AUTOMAKE_TARGETS) $(EMPTY_AUTOMAKE_TARGETS): diff --git a/2.6.38/Makefile.in b/2.6.38/Makefile.in index da131dc..4779420 100644 --- a/2.6.38/Makefile.in +++ b/2.6.38/Makefile.in @@ -20,6 +20,9 @@ PWD := $(shell pwd) WCM_KERNEL_DIR := @WCM_KERNEL_DIR@ MODUTS := @MODUTS@ WCM_KERNEL_VER := @WCM_KERNEL_VER@ +MODSIGN_HASHALGO := @MODSIGN_HASHALGO@ +MODSIGN_PRIVFILE := @MODSIGN_PRIVFILE@ +MODSIGN_CERTFILE := @MODSIGN_CERTFILE@ all: @echo ' Building input-wacom drivers for $(WCM_KERNEL_VER) kernel.' @@ -28,7 +31,13 @@ all: clean: $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) clean -install modules_install: +signature: all + if test -n "$(MODSIGN_HASHALGO)" -a -n "$(MODSIGN_PRIVFILE)" -a -n "$(MODSIGN_CERTFILE)"; then \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom.ko; \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom_w8001.ko; \ + fi + +install modules_install: signature $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) modules_install mkdir -p /etc/depmod.d echo "override wacom * extra" > /etc/depmod.d/input-wacom.conf @@ -59,5 +68,6 @@ distdir: EMPTY_AUTOMAKE_TARGETS = install-data install-exec uninstall install-info EMPTY_AUTOMAKE_TARGETS += installdirs check dvi pdf ps info html tags ctags mostlyclean maintainer-clean +EMPTY_AUTOMAKE_TARGETS += signature .PHONY: $(EMPTY_AUTOMAKE_TARGETS) $(EMPTY_AUTOMAKE_TARGETS): diff --git a/3.17/Makefile.in b/3.17/Makefile.in index b3683b7..7077d8c 100644 --- a/3.17/Makefile.in +++ b/3.17/Makefile.in @@ -29,6 +29,9 @@ DRACUT := $(shell command -v dracut 2>/dev/null) WCM_KERNEL_DIR := @WCM_KERNEL_DIR@ MODUTS := @MODUTS@ WCM_KERNEL_VER := @WCM_KERNEL_VER@ +MODSIGN_HASHALGO := @MODSIGN_HASHALGO@ +MODSIGN_PRIVFILE := @MODSIGN_PRIVFILE@ +MODSIGN_CERTFILE := @MODSIGN_CERTFILE@ all: @echo ' Building input-wacom drivers for $(WCM_KERNEL_VER) kernel.' @@ -37,7 +40,13 @@ all: clean: $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) clean -install modules_install: +signature: all + if test -n "$(MODSIGN_HASHALGO)" -a -n "$(MODSIGN_PRIVFILE)" -a -n "$(MODSIGN_CERTFILE)"; then \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom.ko; \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom_w8001.ko; \ + fi + +install modules_install: signature $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) modules_install mkdir -p /etc/depmod.d echo "override wacom * extra" > /etc/depmod.d/input-wacom.conf @@ -78,5 +87,6 @@ distdir: EMPTY_AUTOMAKE_TARGETS = install-data install-exec uninstall install-info EMPTY_AUTOMAKE_TARGETS += installdirs check dvi pdf ps info html tags ctags mostlyclean maintainer-clean +EMPTY_AUTOMAKE_TARGETS += signature .PHONY: $(EMPTY_AUTOMAKE_TARGETS) $(EMPTY_AUTOMAKE_TARGETS): diff --git a/3.7/Makefile.in b/3.7/Makefile.in index f313ca1..7b3290a 100644 --- a/3.7/Makefile.in +++ b/3.7/Makefile.in @@ -21,6 +21,9 @@ DRACUT := $(shell command -v dracut 2>/dev/null) WCM_KERNEL_DIR := @WCM_KERNEL_DIR@ MODUTS := @MODUTS@ WCM_KERNEL_VER := @WCM_KERNEL_VER@ +MODSIGN_HASHALGO := @MODSIGN_HASHALGO@ +MODSIGN_PRIVFILE := @MODSIGN_PRIVFILE@ +MODSIGN_CERTFILE := @MODSIGN_CERTFILE@ all: @echo ' Building input-wacom drivers for $(WCM_VERSION_VER) kernel.' @@ -29,7 +32,13 @@ all: clean: $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) clean -install modules_install: +signature: all + if test -n "$(MODSIGN_HASHALGO)" -a -n "$(MODSIGN_PRIVFILE)" -a -n "$(MODSIGN_CERTFILE)"; then \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom.ko; \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom_w8001.ko; \ + fi + +install modules_install: signature $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) modules_install mkdir -p /etc/depmod.d echo "override wacom * extra" > /etc/depmod.d/input-wacom.conf @@ -63,5 +72,6 @@ distdir: EMPTY_AUTOMAKE_TARGETS = install-data install-exec uninstall install-info EMPTY_AUTOMAKE_TARGETS += installdirs check dvi pdf ps info html tags ctags mostlyclean maintainer-clean +EMPTY_AUTOMAKE_TARGETS += signature .PHONY: $(EMPTY_AUTOMAKE_TARGETS) $(EMPTY_AUTOMAKE_TARGETS): diff --git a/4.5/Makefile.in b/4.5/Makefile.in index 438229b..dd89344 100644 --- a/4.5/Makefile.in +++ b/4.5/Makefile.in @@ -22,6 +22,9 @@ DRACUT := $(shell command -v dracut 2>/dev/null) WCM_KERNEL_DIR := @WCM_KERNEL_DIR@ MODUTS := @MODUTS@ WCM_KERNEL_VER := @WCM_KERNEL_VER@ +MODSIGN_HASHALGO := @MODSIGN_HASHALGO@ +MODSIGN_PRIVFILE := @MODSIGN_PRIVFILE@ +MODSIGN_CERTFILE := @MODSIGN_CERTFILE@ all: @echo ' Building input-wacom drivers for $(WCM_KERNEL_VER) kernel.' @@ -30,7 +33,13 @@ all: clean: $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) clean -install modules_install: +signature: all + if test -n "$(MODSIGN_HASHALGO)" -a -n "$(MODSIGN_PRIVFILE)" -a -n "$(MODSIGN_CERTFILE)"; then \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom.ko; \ + $(WCM_KERNEL_DIR)/scripts/sign-file "$(MODSIGN_HASHALGO)" "$(MODSIGN_PRIVFILE)" "$(MODSIGN_CERTFILE)" wacom_w8001.ko; \ + fi + +install modules_install: signature $(MAKE) -C $(WCM_KERNEL_DIR) M=$(PWD) modules_install mkdir -p /etc/depmod.d echo "override wacom * extra" > /etc/depmod.d/input-wacom.conf @@ -70,5 +79,6 @@ distdir: EMPTY_AUTOMAKE_TARGETS = install-data install-exec uninstall install-info EMPTY_AUTOMAKE_TARGETS += installdirs check dvi pdf ps info html tags ctags mostlyclean maintainer-clean +EMPTY_AUTOMAKE_TARGETS += signature .PHONY: $(EMPTY_AUTOMAKE_TARGETS) $(EMPTY_AUTOMAKE_TARGETS): diff --git a/configure.ac b/configure.ac index e4afd11..64413c8 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,7 @@ AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign]) +AM_EXTRA_RECURSIVE_TARGETS([signature]) AM_MAINTAINER_MODE AC_PROG_CC @@ -232,6 +233,98 @@ if test "$RHEL7_RELEASE" -ge "4"; then WCM_KERNEL_VER="3.17" fi +dnl ======================================================= +dnl Module signing + +AC_MSG_CHECKING(kernel sig_enforce parameter) +SIG_KERNEL=$(cat /sys/module/module/parameters/sig_enforce 2>/dev/null || echo "(unknown)") +AC_MSG_RESULT([$SIG_KERNEL]) + +AC_MSG_CHECKING(mokutil sb-state) +SIG_MOK=$(mokutil --sb-state 2>/dev/null || echo "(unknown)") +AC_MSG_RESULT([$SIG_MOK]) + +SIG_REQUIRED=$(( $(echo "$SIG_KERNEL" | grep -q "Y" && echo "1" || echo "0") + \ + $(echo "$SIG_MOK" | grep -q "enabled" && echo "1" || echo "0") \ + )) + +MODSIGN_ENABLE=default +MODSIGN_HASHALGO= +MODSIGN_PRIVFILE= +MODSIGN_CERTFILE= + +AC_ARG_ENABLE(module-signing, + AS_HELP_STRING([--disable-module-signing], [Disable automatic module signing]), + [MODSIGN_ENABLE="$enableval"]) +AC_ARG_WITH(hash-algorithm, + AS_HELP_STRING([--with-hash-algorithm=<alg>], [Specify module signing hash algorithm]), + [MODSIGN_HASHALGO="$withval"]) +AC_ARG_WITH(signing-key, + AS_HELP_STRING([--with-signing-key=<trusted.priv>], [Specify module signing key location]), + [MODSIGN_PRIVFILE="$withval"]) +AC_ARG_WITH(signing-cert, + AS_HELP_STRING([--with-signing-cert=<trusted.der>], [Specify module signing cert location]), + [MODSIGN_CERTFILE="$withval"]) + +if test "$MODSIGN_ENABLE" = "yes" -o "$MODSIGN_ENABLE" = "default"; then + if test "$MODSIGN_HASHALGO" = "yes" -o -z "$MODSIGN_HASHALGO"; then + MODSIGN_HASHALGO="sha512" + fi + + # There is no standard location for storing kernel signing keys + # and certificates. The kernel itself has CONFIG_MODULE_SIG_KEY + # (which contains a key and cert) which likely points to a file + # that doesn't exist unless you built the kernel yourself. Most + # distributions use the "shim" bootloader which allows "machine + # owner keys" (MOK) to be enrolled by the end-user, but only + # Ubuntu provides a tool to automatically generate these keys + # (`update-secureboot-policy --new-key`); other distros rely on + # the user generating the key/cert themselves and keeping it in a + # suitably-safe location. + # + # The kernel should automatically try to sign modules as part of + # the `make modules_install` step, so that covers the first case. + # In the second case the best we can do is try Ubuntu's location. + + if test "$MODSIGN_PRIVFILE" = "yes" -o -z "$MODSIGN_PRIVFILE"; then + MODSIGN_PRIVFILE=$(ls /var/lib/shim-signed/mok/MOK.priv 2>/dev/null || echo "$MODSIGN_PRIVFILE") + fi + if test "$MODSIGN_CERTFILE" = "yes" -o -z "$MODSIGN_CERTFILE"; then + MODSIGN_CERTFILE=$(ls /var/lib/shim-signed/mok/MOK.der 2>/dev/null || echo "$MODSIGN_CERTFILE") + fi + + AC_MSG_CHECKING(for module signing hash algorithm) + AC_MSG_RESULT([$MODSIGN_HASHALGO]) + AC_MSG_CHECKING(for module signing key) + AC_MSG_RESULT([$MODSIGN_PRIVFILE]) + AC_MSG_CHECKING(for module signing certificate) + AC_MSG_RESULT([$MODSIGN_CERTFILE]) + + if test ! -f "$MODSIGN_PRIVFILE" -o ! -f "$MODSIGN_CERTFILE"; then + AC_MSG_WARN([Module signing key and/or certificate missing.]) + + if test "$MODSIGN_ENABLE" = "yes"; then + AC_MSG_ERROR([Unable to honor explicit request for module signing.]) + fi + + if test "$SIG_REQUIRED" -gt 0; then + AC_MSG_ERROR([Kernel is configured to only load dnl +signed modules but we are unable to produce a signed module. Either (1) dnl +re-run configure with the options '--with-signing-key=<key>' and dnl +'--with-signing-cert=<cert>' set, (2) indicate you will sign the modules dnl +yourself by re-running configure with the '--disable-module-signing' dnl +option set, or (3) disable the kernel's signed module requirement (e.g. dnl +disable secure boot).]) + fi + fi +else + # Make sure we don't pass these along via AC_SUBST + MODSIGN_HASHALGO= + MODSIGN_PRIVFILE= + MODSIGN_CERTFILE= +fi + + dnl Separate test output from file-generation output echo @@ -240,6 +333,9 @@ AC_SUBST(WCM_KERNEL_DIR) AC_SUBST(WCM_KERNEL_VER) AC_SUBST(RHEL7_RELEASE) AC_SUBST(MODUTS) +AC_SUBST(MODSIGN_HASHALGO) +AC_SUBST(MODSIGN_PRIVFILE) +AC_SUBST(MODSIGN_CERTFILE) AC_CONFIG_FILES([Makefile 2.6.32/Makefile -- 2.19.2 _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel