Package: libefivar1 Version: 30-1 Severity: important Tags: upstream patch Part of the code in linux.c uses "st_rdev >> 8" and "st_rdev & 0xFF" to find the major and minor device number for the disk to install. It was correct a long time ago but it has been quite some time that both major and minor can exceed 8 bits. The libc provides macros to extract the major and minor; another part of the same file uses these macros. Furthermore, the field containing the minor is declared as unsigned char, making it 8 bits.
The result is a failure to prepare boot variables, making grub-install fail for example, for a device with a minor >= 256. The device I needed to use was 179:256. Running with strace showed an attempt to access /sys/dev/block/4275:0 instead of /sys/dev/block/179:256 that would have been correct considering the previous system call was fstat() showing "st_rdev=makedev(179, 256)". You can notice that 179+256*16 = 4275. The attached patch fixes things. Regards, -- Nicolas George -- System Information: Debian Release: stretch/sid APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'testing'), (500, 'stable'), (50, 'unstable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.6.0-1-amd64 (SMP w/8 CPU cores) Locale: LANG=, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages libefivar1:amd64 depends on: ii libc6 2.24-5 libefivar1:amd64 recommends no packages. libefivar1:amd64 suggests no packages. -- no debconf information
diff -ru orig/efivar-30/src/linux.c efivar-30/src/linux.c --- orig/efivar-30/src/linux.c 2016-10-03 18:29:32.000000000 +0200 +++ efivar-30/src/linux.c 2016-11-13 16:55:17.001150388 +0100 @@ -55,7 +55,7 @@ char *linkbuf; ssize_t rc; - rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%hhu", + rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%"PRIu32, info->major, info->minor); if (rc < 0) return -1; @@ -913,11 +913,11 @@ return 1; } if (S_ISBLK(buf.st_mode)) { - info->major = buf.st_rdev >> 8; - info->minor = buf.st_rdev & 0xFF; + info->major = major(buf.st_rdev); + info->minor = minor(buf.st_rdev); } else if (S_ISREG(buf.st_mode)) { - info->major = buf.st_dev >> 8; - info->minor = buf.st_dev & 0xFF; + info->major = major(buf.st_dev); + info->minor = minor(buf.st_dev); } else { printf("Cannot stat non-block or non-regular file\n"); return 1; diff -ru orig/efivar-30/src/linux.h efivar-30/src/linux.h --- orig/efivar-30/src/linux.h 2016-10-03 18:29:32.000000000 +0200 +++ efivar-30/src/linux.h 2016-11-13 16:47:30.773353757 +0100 @@ -75,7 +75,7 @@ unsigned int disknum; unsigned char part; uint64_t major; - unsigned char minor; + uint32_t minor; uint32_t edd10_devicenum; struct pci_root_info pci_root;
signature.asc
Description: Digital signature