[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#826578: hw-detect: check-missing-firmware ignores symlinked firmware packages



Package: hw-detect
Severity: important
Tags: d-i patch

Dear Maintainer,

we are distributing our system with a custom Debian installer that has
been created with simple-cdd and contains non-free firmware packages.
One of our customers has reported back to us that he encountered an
error message during the installation that the following firmware file
couldn't be found:

rtl_nic/rtl8168e-3.fw

I checked our installer source and determined that we do supply a
firmware-realtek package that contains this firmware file:

server /root/install-jessie-new/add/firmware # dpkg-deb -c firmware-realtek_0.43_all.deb | grep rtl8168e-3
-rw-r--r-- root/root      3872 2014-06-16 01:51 ./lib/firmware/rtl_nic/rtl8168e-3.fw

Then I booted the installer in a VM and looked in /cdrom/firmware. Most of the
firmware packages there were files, but some were symlinks, including
the firmware-realtek package:

root@unassigned:/cdrom/firmware# find . -type l -exec ls -l {} \;
lr-xr-xr-x 1 root root 62 May 19  2016 ./firmware-bnx2_0.43_all.deb -> ../pool/non-free/f/firmware-nonfree/firmware-bnx2_0.43_all.deb
lr-xr-xr-x 1 root root 60 May 19  2016 ./firmware-linux-free_3.3_all.deb -> ../pool/main/f/firmware-free/firmware-linux-free_3.3_all.deb
lr-xr-xr-x 1 root root 71 May 19  2016 ./firmware-linux-nonfree_0.43_all.deb -> ../pool/non-free/f/firmware-nonfree/firmware-linux-nonfree_0.43_all.deb
lr-xr-xr-x 1 root root 65 May 19  2016 ./firmware-realtek_0.43_all.deb -> ../pool/non-free/f/firmware-nonfree/firmware-realtek_0.43_all.deb

I believe that the Debian installer build process automatically replaces
firmware files with symlinks to the pool if it determines those files to be
identical. To ensure that this not a problem caused by simple-cdd, I booted the
current Debian netinst that I downloaded here:

http://cdimage.debian.org/debian-cd/8.5.0/amd64/iso-cd/debian-8.5.0-amd64-netinst.iso

There was only a single file located in /cdrom/firmware, but it was also a
symlink:

/cdrom/firmware/firmware-linux-free-3.3_all.deb -> ../pool/main/f/firmware-free/firmware-linux-free-3.3_all.deb

So apparently it's not caused by simple-cdd.

I then figured out that the installer uses a script called
check-missing-firmware to load firmware; apparently it determines
missing firmware files and looks amongst others in /cdrom/firmware for
firmware packages which might provide these files. Unfortunately, the
code only accepts packages that are real files, not symlinks; notice the
[ -f ... ] in line 238 in the function check_for_firmware:

check_for_firmware() {
  echo "$files" | sed -e 's/ /\n/g' >/tmp/grepfor
  for filename in $@; do
    if [ -f "$filename" ]; then
      if check_deb_arch "$filename" && list_deb_firmware "$filename" | grep -qf /tmp/grepfor; then
        log "installing firmware package $filename"
        install_firmware_pkg "$filename" || true
      fi
    fi
  done
  rm -f /tmp/grepfor
}

I think that this is a bug and it is responsible for the firmware our
customer reported. I've marked this bug as important because I believe
it has a major impact on the correct operation of this script. Attached
is a simple patch that replaces the `-f` with `-e`, which should fix
this problem.

-- System Information:
Debian Release: 8.5
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: i386 (x86_64)
Foreign Architectures: amd64

Kernel: Linux 3.16.0-4-amd64 (SMP w/8 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
--- check-missing-firmware.sh.orig	2012-06-15 07:56:09.000000000 +0200
+++ check-missing-firmware.sh	2016-06-06 16:41:44.985996412 +0200
@@ -235,7 +235,7 @@
 check_for_firmware() {
 	echo "$files" | sed -e 's/ /\n/g' >/tmp/grepfor
 	for filename in $@; do
-		if [ -f "$filename" ]; then
+		if [ -e "$filename" ]; then
 			if check_deb_arch "$filename" && list_deb_firmware "$filename" | grep -qf /tmp/grepfor; then
 				log "installing firmware package $filename"
 				install_firmware_pkg "$filename" || true

Reply to: