Package: initramfs-tools
Version: 0.120ubuntu5~rc2
Severity: normal

When adding firmware to the initramfs we currently use copy_exec() this
leads to us running ldd on the firmware, and effectivly attempting to
executing the firmware.  As we have no control over the actual contents
of this firmware this can lead to us actually executing it; in Ubuntu we
have seen this with glibc.x32 installed and cirtain firmware leading to
crashes in ldd and initramfs build failures.

Additionally using copy_exec() uses cp -aL which squashes any symlinks,
while this ensures the firmware is available upstream firmware is starting
to use the below idiom to represent preferred versions of firmware, and
we will end up with multiple versions of the actual firmware in the
initramfs:

    -rw-rw-r-- 1 apw apw   5872 Sep 19 08:51 bxt_dmc_ver1_04.bin
    lrwxrwxrwx 1 apw apw     19 Sep 19 08:51 bxt_dmc_ver1.bin -> 
bxt_dmc_ver1_04.bin
    -rw-rw-r-- 1 apw apw   8380 Sep 19 08:51 skl_dmc_ver1_19.bin
    -rw-rw-r-- 1 apw apw   8380 Sep 19 08:51 skl_dmc_ver1_20.bin
    -rw-rw-r-- 1 apw apw   8824 Sep 19 08:51 skl_dmc_ver1_21.bin
    lrwxrwxrwx 1 apw apw     19 Sep 19 08:51 skl_dmc_ver1.bin -> 
skl_dmc_ver1_21.bin
    -rw-rw-r-- 1 apw apw 109636 Sep 19 08:51 skl_guc_ver1_1059.bin
    lrwxrwxrwx 1 apw apw     21 Sep 19 08:51 skl_guc_ver1.bin -> 
skl_guc_ver1_1059.bin

In Ubuntu we are using the combination of the two attached patches to
solve these issues.

-apw
>From f7d9025b736edbd771fc5befc256d556a2f4204b Mon Sep 17 00:00:00 2001
From: Andy Whitcroft <a...@canonical.com>
Date: Mon, 17 Feb 2014 11:51:59 +0000
Subject: [PATCH 1/2] hook-functions: when copying firmware, don't use
 copy_exec

When copying firmware, don't use copy_exec; running ldd on random firmware files is annoying and, if libc-x32 is installed, may cause crashes due to lack of kernel support.

LP: #1115875
Signed-off-by: Andy Whitcroft <a...@canonical.com>
---
 hook-functions | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/hook-functions b/hook-functions
index ee1c205..0239d8a 100644
--- a/hook-functions
+++ b/hook-functions
@@ -101,10 +101,16 @@ manual_add_modules()
 			fi
 
 			if [ -e "/lib/firmware/${version}/${firmware}" ]; then
-				copy_exec "/lib/firmware/${version}/${firmware}"
+				firmware="/lib/firmware/$version/$firmware"
 			else
-				copy_exec "/lib/firmware/${firmware}"
+				firmware="/lib/firmware/$firmware"
 			fi
+
+			target_dir="$DESTDIR/$(dirname "$firmware")"
+			if ! [ -d "$target_dir" ]; then
+				mkdir -p "$target_dir"
+			fi
+			cp -a "$firmware" "$target_dir"
 			if [ "${verbose}" = "y" ]; then
 				echo "Adding firmware ${firmware}"
 			fi
-- 
2.5.0

>From 18816c491ca53a13e66e1c1e2de13efcd05c23c3 Mon Sep 17 00:00:00 2001
From: Andy Whitcroft <a...@ubuntu.com>
Date: Fri, 18 Sep 2015 15:08:29 +0100
Subject: [PATCH 2/2] hook-functions: firmware -- copy symlink components into
 initramfs

It is becoming increasingly common to use symbolic links to map preferred
versions of firmware where more than one is available:

    -rw-rw-r-- 1 apw apw   5872 Sep 19 08:51 bxt_dmc_ver1_04.bin
    lrwxrwxrwx 1 apw apw     19 Sep 19 08:51 bxt_dmc_ver1.bin -> bxt_dmc_ver1_04.bin
    -rw-rw-r-- 1 apw apw   8380 Sep 19 08:51 skl_dmc_ver1_19.bin
    -rw-rw-r-- 1 apw apw   8380 Sep 19 08:51 skl_dmc_ver1_20.bin
    -rw-rw-r-- 1 apw apw   8824 Sep 19 08:51 skl_dmc_ver1_21.bin
    lrwxrwxrwx 1 apw apw     19 Sep 19 08:51 skl_dmc_ver1.bin -> skl_dmc_ver1_21.bin
    -rw-rw-r-- 1 apw apw 109636 Sep 19 08:51 skl_guc_ver1_1059.bin
    lrwxrwxrwx 1 apw apw     21 Sep 19 08:51 skl_guc_ver1.bin -> skl_guc_ver1_1059.bin

Detect, follow and copy symlink chains.

LP: #1496163
Signed-off-by: Andy Whitcroft <a...@ubuntu.com>
---
 hook-functions | 37 ++++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/hook-functions b/hook-functions
index 0239d8a..1ee246c 100644
--- a/hook-functions
+++ b/hook-functions
@@ -54,6 +54,7 @@ add_modules_from_file()
 manual_add_modules()
 {
 	local prefix kmod options firmware
+	local target_dir depth firmware_link
 
 	if [ $# -eq 0 ]; then
 		return
@@ -106,13 +107,35 @@ manual_add_modules()
 				firmware="/lib/firmware/$firmware"
 			fi
 
-			target_dir="$DESTDIR/$(dirname "$firmware")"
-			if ! [ -d "$target_dir" ]; then
-				mkdir -p "$target_dir"
-			fi
-			cp -a "$firmware" "$target_dir"
-			if [ "${verbose}" = "y" ]; then
-				echo "Adding firmware ${firmware}"
+			depth=10
+			while [ "$firmware" != '' -a "$depth" -gt 0 ]
+			do
+				target_dir="$DESTDIR/$(dirname "$firmware")"
+				if ! [ -d "$target_dir" ]; then
+					mkdir -p "$target_dir"
+				fi
+				cp -a "$firmware" "$target_dir"
+
+				if [ -L "$firmware" ]; then
+					if [ "${verbose}" = "y" ]; then
+						echo "Adding symlink ${firmware}"
+					fi
+
+					depth=$(($depth-1))
+					firmware_link=$(readlink "$firmware")
+					case "$firmware_link" in
+					/*)	firmware="$firmware_link" ;;
+					*)	firmware="$(dirname "$firmware")/$firmware_link" ;;
+					esac
+				else
+					if [ "${verbose}" = "y" ]; then
+						echo "Adding firmware ${firmware}"
+					fi
+					break
+				fi
+			done
+			if [ -L "$firmware" -a "${verbose}" = "y" ]; then
+				echo "Adding firmware ${firmware} -- hanging symlink"
 			fi
 		done
 	done
-- 
2.5.0

Reply via email to