Bug#799443: initramfs-tools: avoid executing firmware and maintain symlinks
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 <apw@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 <apw@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 <apw@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 <apw@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 to: