Bug#975425: buster-pu: package efivar/32-2+deb10u1
Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org@packages.debian.org
Usertags: pu
Hi folks,
I'd like to upload a stable update for efivar, with two (sets of)
fixes backported from upstream.
* Firstly, there's a simple initialisation fix to fix some possible
crashes.
* Secondly, there's support for newer systems that need extra NVME
support doing device lookups. (#975417). This is an important
update for supporting installation and boot on those new
systems. The reporter of the bug has tested with test packages and
all looks good.
Debdiff attached.
-- System Information:
Debian Release: 10.6
APT prefers stable-debug
APT policy: (500, 'stable-debug'), (500, 'stable'), (500, 'oldstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 4.19.0-12-amd64 (SMP w/4 CPU cores)
Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE=en_GB:en (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff -Nru efivar-37/debian/changelog efivar-37/debian/changelog
--- efivar-37/debian/changelog 2019-03-01 17:55:07.000000000 +0000
+++ efivar-37/debian/changelog 2020-11-22 00:03:59.000000000 +0000
@@ -1,3 +1,13 @@
+efivar (37-2+deb10u1) buster; urgency=medium
+
+ * Backport important fixes from unstable:
+ + fix uninitialized variable in parse_acpi_root, saving possible
+ segfault.
+ + Add support for nvme-fabrics and nvme-subsystem devices. Closes:
+ #975417
+
+ -- Steve McIntyre <93sam@debian.org> Sun, 22 Nov 2020 00:03:59 +0000
+
efivar (37-2) unstable; urgency=medium
* Cherry-pick fix from upstream:
diff -Nru efivar-37/debian/patches/0001-Fix-the-error-path-in-set_disk_and_part_name.patch efivar-37/debian/patches/0001-Fix-the-error-path-in-set_disk_and_part_name.patch
--- efivar-37/debian/patches/0001-Fix-the-error-path-in-set_disk_and_part_name.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/0001-Fix-the-error-path-in-set_disk_and_part_name.patch 2020-11-21 23:57:27.000000000 +0000
@@ -0,0 +1,74 @@
+From 22bc0866e941cbfe57de6522db51e9cf2c6b3ff1 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 2 Oct 2019 17:01:00 -0400
+Subject: [PATCH] Fix the error path in set_disk_and_part_name()
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+[ dannf: Context adjustments due to upstream whitespace cleanup;
+ Included to simplify the application of
+ 0003-Try-even-harder-to-find-disk-device-symlinks-in-sysf.patch ]
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1891718
+Bug: https://github.com/rhboot/efivar/issues/157
+Origin: upstream, https://github.com/rhboot/efivar/commit/22bc0866e941cbfe57de6522db51e9cf2c6b3ff1
+Last-Updated: 2020-09-30
+
+Index: efivar-37/src/linux.c
+===================================================================
+--- efivar-37.orig/src/linux.c
++++ efivar-37/src/linux.c
+@@ -1,6 +1,6 @@
+ /*
+ * libefiboot - library for the manipulation of EFI boot variables
+- * Copyright 2012-2015 Red Hat, Inc.
++ * Copyright 2012-2019 Red Hat, Inc.
+ * Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ *
+ * This library is free software; you can redistribute it and/or
+@@ -169,6 +169,8 @@ set_disk_name(struct device *dev, const
+ int HIDDEN
+ set_disk_and_part_name(struct device *dev)
+ {
++ int rc = -1;
++
+ /*
+ * results are like such:
+ * maj:min -> ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
+@@ -200,6 +202,7 @@ set_disk_and_part_name(struct device *de
+ set_disk_name(dev, "%s", penultimate);
+ set_part_name(dev, "%s", ultimate);
+ debug("disk:%s part:%s", penultimate, ultimate);
++ rc = 0;
+ } else if (ultimate && approximate && !strcmp(approximate, "nvme")) {
+ /*
+ * 259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
+@@ -207,6 +210,7 @@ set_disk_and_part_name(struct device *de
+ set_disk_name(dev, "%s", ultimate);
+ set_part_name(dev, "%sp%d", ultimate, dev->part);
+ debug("disk:%s part:%sp%d", ultimate, ultimate, dev->part);
++ rc = 0;
+ } else if (ultimate && penultimate && !strcmp(penultimate, "block")) {
+ /*
+ * 253:0 -> ../../devices/virtual/block/dm-0 (... I guess)
+@@ -220,15 +224,19 @@ set_disk_and_part_name(struct device *de
+ set_disk_name(dev, "%s", ultimate);
+ set_part_name(dev, "%s%d", ultimate, dev->part);
+ debug("disk:%s part:%s%d", ultimate, ultimate, dev->part);
++ rc = 0;
+ } else if (ultimate && approximate && !strcmp(approximate, "mtd")) {
+ /*
+ * 31:0 -> ../../devices/platform/1e000000.palmbus/1e000b00.spi/spi_master/spi32766/spi32766.0/mtd/mtd0/mtdblock0
+ */
+ set_disk_name(dev, "%s", ultimate);
+ debug("disk:%s", ultimate);
++ rc = 0;
+ }
+
+- return 0;
++ if (rc < 0)
++ efi_error("Could not parse disk name:\"%s\"", dev->link);
++ return rc;
+ }
+
+ static struct dev_probe *dev_probes[] = {
diff -Nru efivar-37/debian/patches/0002-sysfs-parsers-make-all-the-sys-block-link-parsers-wo.patch efivar-37/debian/patches/0002-sysfs-parsers-make-all-the-sys-block-link-parsers-wo.patch
--- efivar-37/debian/patches/0002-sysfs-parsers-make-all-the-sys-block-link-parsers-wo.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/0002-sysfs-parsers-make-all-the-sys-block-link-parsers-wo.patch 2020-11-21 23:57:27.000000000 +0000
@@ -0,0 +1,92 @@
+From 4718694094647b981b74453445d000b0296b6544 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 15 Oct 2019 16:53:27 -0400
+Subject: [PATCH] sysfs parsers: make all the /sys/block link parsers work the
+ same way
+
+Apparently I wrote some of these one way and some the other, and the one
+special case where everything was "current+sz" instead of some form of
+"current += pos; sz += pos; ...; return sz;" or the subtraction version.
+
+Make them all the same, where possible.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+[ dannf: Restrict to just linux-nvme.c;
+ Context adjustments due to upstream whitespace cleanup;
+ drop call to dbgmk() call - it didn't exist in v37;
+ included to simplify application of later patches in series ]
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1891718
+Bug: https://github.com/rhboot/efivar/issues/157
+Origin: upstream, https://github.com/rhboot/efivar/commit/4718694094647b981b74453445d000b0296b6544
+Last-Updated: 2020-09-30
+
+Index: efivar-37/src/linux-nvme.c
+===================================================================
+--- efivar-37.orig/src/linux-nvme.c
++++ efivar-37/src/linux-nvme.c
+@@ -24,6 +24,7 @@
+ #include <fcntl.h>
+ #include <inttypes.h>
+ #include <stdint.h>
++#include <sys/param.h>
+ #include <unistd.h>
+
+ #include "efiboot.h"
+@@ -48,25 +49,28 @@
+ */
+
+ static ssize_t
+-parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
++parse_nvme(struct device *dev, const char *path, const char *root UNUSED)
+ {
++ const char *current = path;
+ int rc;
+ int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
+ uint8_t *filebuf = NULL;
+- int pos0 = 0, pos1 = 0;
++ int pos0 = -1, pos1 = -1, pos2 = -1;
+
+ debug("entry");
+
+ debug("searching for nvme/nvme0/nvme0n1 or nvme/nvme0/nvme0n1/nvme0n1p1");
+- rc = sscanf(current, "nvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
+- &tosser0, &ctrl_id, &ns_id, &pos0,
+- &tosser1, &tosser2, &partition, &pos1);
+- debug("current:\"%s\" rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
++ rc = sscanf(current, "%nnvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
++ &pos0, &tosser0, &ctrl_id, &ns_id,
++ &pos1, &tosser1, &tosser2, &partition, &pos2);
++ debug("current:\"%s\" rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
+ /*
+ * If it isn't of that form, it's not one of our nvme devices.
+ */
+ if (rc != 3 && rc != 6)
+ return 0;
++ if (rc == 3)
++ pos2 = pos1;
+
+ dev->nvme_info.ctrl_id = ctrl_id;
+ dev->nvme_info.ns_id = ns_id;
+@@ -77,8 +81,9 @@ parse_nvme(struct device *dev, const cha
+ if (dev->part == -1)
+ dev->part = partition;
+
+- pos0 = pos1;
++ pos1 = pos2;
+ }
++ current += pos1;
+
+ /*
+ * now fish the eui out of sysfs is there is one...
+@@ -110,7 +115,8 @@ parse_nvme(struct device *dev, const cha
+ memcpy(dev->nvme_info.eui, eui, sizeof(eui));
+ }
+
+- return pos0;
++ debug("current:'%s' sz:%zd", current, current - path);
++ return current - path;
+ }
+
+ static ssize_t
diff -Nru efivar-37/debian/patches/0003-Try-even-harder-to-find-disk-device-symlinks-in-sysf.patch efivar-37/debian/patches/0003-Try-even-harder-to-find-disk-device-symlinks-in-sysf.patch
--- efivar-37/debian/patches/0003-Try-even-harder-to-find-disk-device-symlinks-in-sysf.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/0003-Try-even-harder-to-find-disk-device-symlinks-in-sysf.patch 2020-11-21 23:57:27.000000000 +0000
@@ -0,0 +1,209 @@
+From c9c1424d0e09bf33b747d37c43177c63367b1290 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Fri, 11 Oct 2019 14:20:54 -0400
+Subject: [PATCH] Try even harder to find disk device symlinks in sysfs.
+
+Today's realization is that the thing encoded into the structure of
+sysfs is, in the best case, the dependency graph of the makefile targets
+to build a device driver.
+
+In the case of nvme-fabric, or really wherever the kernel has
+class_create() and device_create() in the same function, there's an
+extra level of indirection.
+
+Anyway, in this patch we stop pretending sysfs isn't completely absurd,
+and just try adding "/device" in the middle of the driver symlink path,
+until we actually either get ENOENT on the device symlink or find a
+device symlink that actually has a driver symlink under it.
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+[ dannf: Context adjustments due to upstream whitespace cleanup;
+ Adjust to omit efi_error_pop() call that didn't exist in v37;
+ included to simplify application of later patches in series ]
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1891718
+Bug: https://github.com/rhboot/efivar/issues/157
+Origin: upstream, https://github.com/rhboot/efivar/commit/c9c1424d0e09bf33b747d37c43177c63367b1290
+Last-Updated: 2020-09-30
+
+Index: efivar-37/src/linux-nvme.c
+===================================================================
+--- efivar-37.orig/src/linux-nvme.c
++++ efivar-37/src/linux-nvme.c
+@@ -88,13 +88,12 @@ parse_nvme(struct device *dev, const cha
+ /*
+ * now fish the eui out of sysfs is there is one...
+ */
+- rc = read_sysfs_file(&filebuf,
+- "class/block/nvme%dn%d/eui",
+- ctrl_id, ns_id);
+- if ((rc < 0 && errno == ENOENT) || filebuf == NULL) {
+- rc = read_sysfs_file(&filebuf,
+- "class/block/nvme%dn%d/device/eui",
+- ctrl_id, ns_id);
++ char *euipath = NULL;
++ rc = read_sysfs_file(&filebuf, "class/block/nvme%dn%d/eui", ctrl_id, ns_id);
++ if (rc < 0 && (errno == ENOENT || errno == ENOTDIR)) {
++ rc = find_device_file(&euipath, "eui", "class/block/nvme%dn%d", ctrl_id, ns_id);
++ if (rc >= 0 && euipath != NULL)
++ rc = read_sysfs_file(&filebuf, "%s", euipath);
+ }
+ if (rc >= 0 && filebuf != NULL) {
+ uint8_t eui[8];
+Index: efivar-37/src/linux.c
+===================================================================
+--- efivar-37.orig/src/linux.c
++++ efivar-37/src/linux.c
+@@ -410,24 +410,32 @@ struct device HIDDEN
+ goto err;
+ }
+
+- if (dev->device[0] != 0) {
+- rc = sysfs_readlink(&tmpbuf, "block/%s/device/driver", dev->disk_name);
++ /*
++ * So, on a normal disk, you get something like:
++ * /sys/block/sda/device -> ../../0:0:0:0
++ * /sys/block/sda/device/driver -> ../../../../../../../bus/scsi/drivers/sd
++ *
++ * On a directly attached nvme device you get:
++ * /sys/block/nvme0n1/device -> ../../nvme0
++ * /sys/block/nvme0n1/device/device -> ../../../0000:6e:00.0
++ * /sys/block/nvme0n1/device/device/driver -> ../../../../bus/pci/drivers/nvme
++ *
++ * On a fabric-attached nvme device, you get something like:
++ * /sys/block/nvme0n1/device -> ../../nvme0
++ * /sys/block/nvme0n1/device/device -> ../../ctl
++ * /sys/block/nvme0n1/device/device/device -> ../../../../../0000:6e:00.0
++ * /sys/block/nvme0n1/device/device/device/driver -> ../../../../../../bus/pci/drivers/nvme-fabrics
++ *
++ * ... I think? I don't have one in front of me.
++ */
++
++ char *filepath = NULL;
++ rc = find_device_file(&filepath, "driver", "block/%s", dev->disk_name);
++ if (rc >= 0) {
++ rc = sysfs_readlink(&tmpbuf, "%s", filepath);
+ if (rc < 0 || !tmpbuf) {
+- if (errno == ENOENT) {
+- /*
+- * nvme, for example, will have nvme0n1/device point
+- * at nvme0, and we need to look for device/driver
+- * there.
+- */
+- rc = sysfs_readlink(&tmpbuf,
+- "block/%s/device/device/driver",
+- dev->disk_name);
+- }
+- if (rc < 0 || !tmpbuf) {
+- efi_error("readlink of /sys/block/%s/device/driver failed",
+- dev->disk_name);
+- goto err;
+- }
++ efi_error("readlink of /sys/%s failed", filepath);
++ goto err;
+ }
+
+ linkbuf = pathseg(tmpbuf, -1);
+@@ -438,7 +446,7 @@ struct device HIDDEN
+
+ dev->driver = strdup(linkbuf);
+ } else {
+- dev->driver = strdup("");
++ dev->driver = strdup("");
+ }
+
+ if (!dev->driver) {
+Index: efivar-37/src/linux.h
+===================================================================
+--- efivar-37.orig/src/linux.h
++++ efivar-37/src/linux.h
+@@ -1,6 +1,6 @@
+ /*
+ * libefiboot - library for the manipulation of EFI boot variables
+- * Copyright 2012-2015 Red Hat, Inc.
++ * Copyright 2012-2019 Red Hat, Inc.
+ * Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ *
+ * This library is free software; you can redistribute it and/or
+@@ -196,6 +196,22 @@ extern ssize_t HIDDEN make_mac_path(uint
+ bufsize_; \
+ })
+
++#define sysfs_access(mode, fmt, args...) \
++ ({ \
++ int rc_; \
++ char *pn_; \
++ \
++ rc_ = asprintfa(&pn_, "/sys/" fmt, ## args); \
++ if (rc_ >= 0) { \
++ rc_ = access(pn_, mode); \
++ if (rc_ < 0) \
++ efi_error("could not access %s", pn_); \
++ } else { \
++ efi_error("could not allocate memory"); \
++ } \
++ rc_; \
++ })
++
+ #define sysfs_readlink(linkbuf, fmt, args...) \
+ ({ \
+ char *_lb = alloca(PATH_MAX+1); \
+@@ -251,6 +267,57 @@ extern ssize_t HIDDEN make_mac_path(uint
+ dir_; \
+ })
+
++/*
++ * Iterate a /sys/block directory looking for device/foo, device/device/foo,
++ * etc. I'm not proud of this method.
++ */
++#define find_device_file(result, name, fmt, args...) \
++ ({ \
++ int rc_ = 0; \
++ debug("searching for %s from in %s", name, dev->disk_name); \
++ for (unsigned int try_ = 0; true; try_++) { \
++ char slashdev_[sizeof("device") \
++ + try_ * strlen("/device")]; \
++ \
++ char *nul_ = stpcpy(slashdev_, "device"); \
++ for (unsigned int i_ = 0; i_ < try_; i_++) \
++ nul_ = stpcpy(nul_, "/device"); \
++ \
++ debug("trying /sys/" fmt "/%s/%s", \
++ ## args, slashdev_, name); \
++ \
++ rc_ = sysfs_access(F_OK, fmt "/%s", ## args, slashdev_);\
++ if (rc_ < 0) { \
++ if (errno == ENOENT) { \
++ break; \
++ } \
++ efi_error("cannot access /sys/"fmt"/%s: %m", \
++ ## args, slashdev_); \
++ goto find_device_link_err_; \
++ } \
++ \
++ rc_ = sysfs_access(F_OK, fmt "/%s/%s", \
++ ## args, slashdev_, name); \
++ if (rc_ < 0) { \
++ if (errno == ENOENT) { \
++ break; \
++ } \
++ efi_error("cannot access /sys/"fmt"/%s/%s: %m", \
++ ## args, slashdev_, name); \
++ goto find_device_link_err_; \
++ } \
++ \
++ rc_ = asprintfa(result, fmt "/%s/%s", \
++ ## args, slashdev_, name); \
++ if (rc_ < 0) { \
++ efi_error("cannot allocate memory: %m"); \
++ goto find_device_link_err_; \
++ } \
++ } \
++find_device_link_err_: \
++ rc_; \
++ })
++
+ #define DEV_PROVIDES_ROOT 1
+ #define DEV_PROVIDES_HD 2
+ #define DEV_ABBREV_ONLY 4
diff -Nru efivar-37/debian/patches/0004-Handle-sys-devices-virtual-nvme-fabrics-nvme-subsyst.patch efivar-37/debian/patches/0004-Handle-sys-devices-virtual-nvme-fabrics-nvme-subsyst.patch
--- efivar-37/debian/patches/0004-Handle-sys-devices-virtual-nvme-fabrics-nvme-subsyst.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/0004-Handle-sys-devices-virtual-nvme-fabrics-nvme-subsyst.patch 2020-11-21 23:57:27.000000000 +0000
@@ -0,0 +1,309 @@
+From c41da0bdce04ab0f99b992d51ff6fd0ab55d040a Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Wed, 2 Oct 2019 17:04:12 -0400
+Subject: [PATCH] Handle /sys/devices/virtual/{nvme-fabrics,nvme-subsystem}
+ devices
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+[ dannf: Context adjustments due to upstream whitespace cleanup and
+ dbgmk() calls;
+ drop new calls to dbgmk() - it didn't exist in v37 ]
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1891718
+Bug: https://github.com/rhboot/efivar/issues/157
+Origin: upstream, https://github.com/rhboot/efivar/commit/c41da0bdce04ab0f99b992d51ff6fd0ab55d040a
+Last-Updated: 2020-09-30
+
+Index: efivar-37/src/linux-nvme.c
+===================================================================
+--- efivar-37.orig/src/linux-nvme.c
++++ efivar-37/src/linux-nvme.c
+@@ -15,7 +15,6 @@
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+- *
+ */
+
+ #include "fix_coverity.h"
+@@ -35,6 +34,12 @@
+ * /sys/dev/block/$major:$minor looks like:
+ * 259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
+ * 259:1 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p1
++ * or:
++ * 259:0 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1
++ * 259:1 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1/nvme0n1p1
++ * or:
++ * 259:5 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
++ * 259:6 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
+ *
+ * /sys/dev/block/259:0/device looks like:
+ * device -> ../../nvme0
+@@ -56,14 +61,41 @@ parse_nvme(struct device *dev, const cha
+ int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
+ uint8_t *filebuf = NULL;
+ int pos0 = -1, pos1 = -1, pos2 = -1;
++ ssize_t sz = 0;
++ struct subdir {
++ const char * const name;
++ const char * const fmt;
++ int *pos0, *pos1;
++ } subdirs[] = {
++ {"nvme-subsysN/", "%nnvme-subsys%d/%n", &pos0, &pos2},
++ {"ctl/", "%nctl/%n%n", &pos0, &pos1},
++ {"nvme/", "%nnvme/%n%n", &pos0, &pos1},
++ {NULL, }
++ };
+
+ debug("entry");
+
+- debug("searching for nvme/nvme0/nvme0n1 or nvme/nvme0/nvme0n1/nvme0n1p1");
+- rc = sscanf(current, "%nnvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
+- &pos0, &tosser0, &ctrl_id, &ns_id,
+- &pos1, &tosser1, &tosser2, &partition, &pos2);
+- debug("current:\"%s\" rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
++ /*
++ * in this case, *any* of these is okay.
++ */
++ for (int i = 0; subdirs[i].name; i++) {
++ debug("searching for %s", subdirs[i].name);
++ pos0 = tosser0 = pos1 = -1;
++ rc = sscanf(current, subdirs[i].fmt, &pos0, &pos1, &pos2);
++ debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc,
++ *subdirs[i].pos0, *subdirs[i].pos1);
++ if (*subdirs[i].pos0 >= 0 && *subdirs[i].pos1 >= *subdirs[i].pos0) {
++ sz += *subdirs[i].pos1;
++ current += *subdirs[i].pos1;
++ break;
++ }
++ }
++
++ debug("searching for nvme0/nvme0n1 or nvme0/nvme0n1/nvme0n1p1");
++ rc = sscanf(current, "%nnvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
++ &pos0, &tosser0, &ctrl_id, &ns_id, &pos1,
++ &tosser1, &tosser2, &partition, &pos2);
++ debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
+ /*
+ * If it isn't of that form, it's not one of our nvme devices.
+ */
+@@ -81,13 +113,15 @@ parse_nvme(struct device *dev, const cha
+ if (dev->part == -1)
+ dev->part = partition;
+
+- pos1 = pos2;
++ pos1 = pos2;
+ }
++
+ current += pos1;
+
+ /*
+ * now fish the eui out of sysfs is there is one...
+ */
++ debug("looking for the eui");
+ char *euipath = NULL;
+ rc = read_sysfs_file(&filebuf, "class/block/nvme%dn%d/eui", ctrl_id, ns_id);
+ if (rc < 0 && (errno == ENOENT || errno == ENOTDIR)) {
+@@ -110,6 +144,9 @@ parse_nvme(struct device *dev, const cha
+ errno = EINVAL;
+ return -1;
+ }
++ debug("eui is %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
++ eui[0], eui[1], eui[2], eui[3],
++ eui[4], eui[5], eui[6], eui[7]);
+ dev->nvme_info.has_eui = 1;
+ memcpy(dev->nvme_info.eui, eui, sizeof(eui));
+ }
+Index: efivar-37/src/linux-virtual-root.c
+===================================================================
+--- /dev/null
++++ efivar-37/src/linux-virtual-root.c
+@@ -0,0 +1,87 @@
++/*
++ * libefiboot - library for the manipulation of EFI boot variables
++ * Copyright 2012-2019 Red Hat, Inc.
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of the
++ * License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#include "fix_coverity.h"
++
++#include <errno.h>
++#include <fcntl.h>
++#include <inttypes.h>
++#include <stdint.h>
++#include <unistd.h>
++
++#include "efiboot.h"
++
++/*
++ * Support virtually rooted devices (fibre+nvme, etc.)
++ *
++ * /sys/dev/block/$major:$minor looks like:
++ * 259:0 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1
++ * 259:1 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1/nvme0n1p1
++ * or:
++ * 259:5 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
++ * 259:6 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
++ */
++
++static ssize_t
++parse_virtual_root(struct device *dev UNUSED, const char *current, const char *root UNUSED)
++{
++ int rc;
++ ssize_t sz;
++ int pos0 = 0, pos1 = 0;
++ struct subdir {
++ const char * const name;
++ const char * const fmt;
++ } subdirs[] = {
++ {"../../devices/virtual", "%n../../devices/virtual/%n"},
++ {"nvme-subsystem/", "%nnvme-subsystem/%n"},
++ {"nvme-fabrics/ctl/", "%nnvme-fabrics/ctl/%n"},
++ {NULL, NULL}
++ };
++
++ debug("entry");
++
++ for (int i = 0; subdirs[i].name; i++) {
++ debug("searching for %s", subdirs[i].name);
++ pos0 = pos1 = -1;
++ rc = sscanf(current, subdirs[i].fmt, &pos0, &pos1);
++ debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
++ if (rc == 1) {
++ sz += pos1;
++ current += pos1;
++ if (i > 0)
++ goto found;
++ }
++ }
++
++ sz = 0;
++found:
++ debug("current:'%s' sz:%zd\n", current, sz);
++ return sz;
++}
++
++static enum interface_type virtual_root_iftypes[] = { virtual_root, unknown };
++
++struct dev_probe HIDDEN virtual_root_parser = {
++ .name = "virtual_root",
++ .iftypes = virtual_root_iftypes,
++ .flags = DEV_ABBREV_ONLY|DEV_PROVIDES_ROOT,
++ .parse = parse_virtual_root,
++};
++
++// vim:fenc=utf-8:tw=75:noet
+Index: efivar-37/src/linux.h
+===================================================================
+--- efivar-37.orig/src/linux.h
++++ efivar-37/src/linux.h
+@@ -99,7 +99,8 @@ struct emmc_info {
+
+ enum interface_type {
+ unknown,
+- isa, acpi_root, pci_root, soc_root, pci, network,
++ isa, acpi_root, pci_root, soc_root, virtual_root,
++ pci, network,
+ ata, atapi, scsi, sata, sas,
+ usb, i1394, fibre, i2o,
+ md, virtblk,
+@@ -344,6 +345,7 @@ extern struct dev_probe pmem_parser;
+ extern struct dev_probe pci_root_parser;
+ extern struct dev_probe acpi_root_parser;
+ extern struct dev_probe soc_root_parser;
++extern struct dev_probe virtual_root_parser;
+ extern struct dev_probe pci_parser;
+ extern struct dev_probe sas_parser;
+ extern struct dev_probe sata_parser;
+Index: efivar-37/src/linux.c
+===================================================================
+--- efivar-37.orig/src/linux.c
++++ efivar-37/src/linux.c
+@@ -170,16 +170,17 @@ int HIDDEN
+ set_disk_and_part_name(struct device *dev)
+ {
+ int rc = -1;
+-
+- /*
+- * results are like such:
+- * maj:min -> ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
+- */
+-
+ char *ultimate = pathseg(dev->link, -1);
+ char *penultimate = pathseg(dev->link, -2);
+ char *approximate = pathseg(dev->link, -3);
+ char *proximate = pathseg(dev->link, -4);
++ char *psl5 = pathseg(dev->link, -5);
++
++
++ /*
++ * devlinks look something like:
++ * maj:min -> ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
++ */
+
+ errno = 0;
+ debug("dev->disk_name:%p dev->part_name:%p", dev->disk_name, dev->part_name);
+@@ -188,6 +189,7 @@ set_disk_and_part_name(struct device *de
+ debug("penultimate:\"%s\"", penultimate ? : "");
+ debug("approximate:\"%s\"", approximate ? : "");
+ debug("proximate:\"%s\"", proximate ? : "");
++ debug("psl5:'%s'", psl5 ? : "");
+
+ if (ultimate && penultimate &&
+ ((proximate && !strcmp(proximate, "nvme")) ||
+@@ -232,6 +234,34 @@ set_disk_and_part_name(struct device *de
+ set_disk_name(dev, "%s", ultimate);
+ debug("disk:%s", ultimate);
+ rc = 0;
++ } else if ((proximate && ultimate && !strcmp(proximate, "nvme-fabrics")) ||
++ (approximate && ultimate && !strcmp(approximate, "nvme-subsystem"))) {
++ /*
++ * 259:0 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1
++ * ^ proximate ^ ultimate
++ * or
++ * 259:5 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
++ * ^ approximate ^ penultimate
++ * ultimate ^
++ */
++ set_disk_name(dev, "%s", ultimate);
++ debug("disk:%s", ultimate);
++ rc = 0;
++ } else if ((psl5 && penultimate && ultimate && !strcmp(psl5, "nvme-fabrics")) ||
++ (proximate && penultimate && ultimate && !strcmp(proximate, "nvme-subsystem"))) {
++ /*
++ * 259:1 -> ../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1/nvme0n1p1
++ * ^psl5 ^ penultimate
++ * ultimate ^
++ * or
++ * 259:6 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
++ * ^ proximate ^ penultimate
++ * ultimate ^
++ */
++ set_disk_name(dev, "%s", penultimate);
++ set_part_name(dev, "%s", ultimate);
++ debug("disk:%s part:%s", penultimate, ultimate);
++ rc = 0;
+ }
+
+ if (rc < 0)
+@@ -248,6 +278,7 @@ static struct dev_probe *dev_probes[] =
+ &acpi_root_parser,
+ &pci_root_parser,
+ &soc_root_parser,
++ &virtual_root_parser,
+ &pci_parser,
+ &virtblk_parser,
+ &sas_parser,
diff -Nru efivar-37/debian/patches/0005-Fix-variable-sz-uninitialized-error.patch efivar-37/debian/patches/0005-Fix-variable-sz-uninitialized-error.patch
--- efivar-37/debian/patches/0005-Fix-variable-sz-uninitialized-error.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/0005-Fix-variable-sz-uninitialized-error.patch 2020-11-21 23:57:27.000000000 +0000
@@ -0,0 +1,38 @@
+From 9dc04c2fd88b6e0e0fe411885041925d52f71af3 Mon Sep 17 00:00:00 2001
+From: Chih-Wei Huang <cwhuang@linux.org.tw>
+Date: Wed, 22 Jan 2020 12:16:12 +0800
+Subject: [PATCH 2/2] Fix variable 'sz' uninitialized error
+
+To fix the error:
+
+external/efivar/src/linux-virtual-root.c:66:4: error: variable 'sz' is uninitialized when used here [-Werror,-Wuninitialized]
+ sz += pos1;
+ ^~
+external/efivar/src/linux-virtual-root.c:45:12: note: initialize the variable 'sz' to silence this warning
+ ssize_t sz;
+ ^
+ = 0
+1 error generated.
+
+Fixes: c41da0bd ("Handle /sys/devices/virtual/{nvme-fabrics,nvme-subsystem} devices")
+
+Signed-off-by: Chih-Wei Huang <cwhuang@linux.org.tw>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1891718
+Bug: https://github.com/rhboot/efivar/issues/157
+Origin: upstream, https://github.com/rhboot/efivar/commit/9dc04c2fd88b6e0e0fe411885041925d52f71af3
+Last-Updated: 2020-09-30
+
+Index: efivar-37/src/linux-virtual-root.c
+===================================================================
+--- efivar-37.orig/src/linux-virtual-root.c
++++ efivar-37/src/linux-virtual-root.c
+@@ -42,7 +42,7 @@ static ssize_t
+ parse_virtual_root(struct device *dev UNUSED, const char *current, const char *root UNUSED)
+ {
+ int rc;
+- ssize_t sz;
++ ssize_t sz = 0;
+ int pos0 = 0, pos1 = 0;
+ struct subdir {
+ const char * const name;
diff -Nru efivar-37/debian/patches/0006-Fix-parsing-for-nvme-subsystem-devices.patch efivar-37/debian/patches/0006-Fix-parsing-for-nvme-subsystem-devices.patch
--- efivar-37/debian/patches/0006-Fix-parsing-for-nvme-subsystem-devices.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/0006-Fix-parsing-for-nvme-subsystem-devices.patch 2020-11-21 23:57:27.000000000 +0000
@@ -0,0 +1,91 @@
+From 4e12f997f8b6af76ef65e7045c232b7d642a1af4 Mon Sep 17 00:00:00 2001
+From: dann frazier <dann.frazier@canonical.com>
+Date: Mon, 17 Aug 2020 13:11:15 -0600
+Subject: [PATCH] Fix parsing for nvme-subsystem devices
+
+nvme-subsystem devices have a link that looks like:
+ ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
+
+However, the current code expects an additional /nvme0/ component, i.e.:
+ ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0/nvme0n1
+
+Fix this by adding a separate branch for parsing nvme-subsystem devices.
+
+Resolves github issue #157.
+
+Signed-off-by: dann frazier <dann.frazier@canonical.com>
+
+[ dannf: Context adjustments due to upstream whitespace cleanup and
+ dbgmk() calls ]
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1891718
+Bug: https://github.com/rhboot/efivar/issues/157
+Origin: upstream, https://github.com/rhboot/efivar/commit/4e12f997f8b6af76ef65e7045c232b7d642a1af4
+Last-Updated: 2020-10-08
+
+Index: efivar/src/linux-nvme.c
+===================================================================
+--- efivar.orig/src/linux-nvme.c
++++ efivar/src/linux-nvme.c
+@@ -57,7 +57,7 @@ static ssize_t
+ parse_nvme(struct device *dev, const char *path, const char *root UNUSED)
+ {
+ const char *current = path;
+- int rc;
++ int i, rc;
+ int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
+ uint8_t *filebuf = NULL;
+ int pos0 = -1, pos1 = -1, pos2 = -1;
+@@ -78,7 +78,7 @@ parse_nvme(struct device *dev, const cha
+ /*
+ * in this case, *any* of these is okay.
+ */
+- for (int i = 0; subdirs[i].name; i++) {
++ for (i = 0; subdirs[i].name; i++) {
+ debug("searching for %s", subdirs[i].name);
+ pos0 = tosser0 = pos1 = -1;
+ rc = sscanf(current, subdirs[i].fmt, &pos0, &pos1, &pos2);
+@@ -91,18 +91,31 @@ parse_nvme(struct device *dev, const cha
+ }
+ }
+
+- debug("searching for nvme0/nvme0n1 or nvme0/nvme0n1/nvme0n1p1");
+- rc = sscanf(current, "%nnvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
+- &pos0, &tosser0, &ctrl_id, &ns_id, &pos1,
+- &tosser1, &tosser2, &partition, &pos2);
+- debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
+- /*
+- * If it isn't of that form, it's not one of our nvme devices.
+- */
+- if (rc != 3 && rc != 6)
+- return 0;
+- if (rc == 3)
+- pos2 = pos1;
++ if (!subdirs[i].name)
++ return 0;
++
++ debug("searching for nvme-subsysN/");
++ if (!strncmp("nvme-subsysN/", subdirs[i].name, 13)) {
++ debug("searching for nvme0n1");
++ rc = sscanf(current, "%nnvme%dn%d%n",
++ &pos0, &ctrl_id, &ns_id, &pos1);
++ debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
++ if (rc != 2)
++ return 0;
++ } else {
++ debug("searching for nvme0/nvme0n1 or nvme0/nvme0n1/nvme0n1p1");
++ rc = sscanf(current, "%nnvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
++ &pos0, &tosser0, &ctrl_id, &ns_id, &pos1,
++ &tosser1, &tosser2, &partition, &pos2);
++ debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
++ /*
++ * If it isn't of that form, it's not one of our nvme devices.
++ */
++ if (rc != 3 && rc != 6)
++ return 0;
++ if (rc == 3)
++ pos2 = pos1;
++ }
+
+ dev->nvme_info.ctrl_id = ctrl_id;
+ dev->nvme_info.ns_id = ns_id;
diff -Nru efivar-37/debian/patches/Always-initialize-any-variable-we-use-with-sscanf-s-.patch efivar-37/debian/patches/Always-initialize-any-variable-we-use-with-sscanf-s-.patch
--- efivar-37/debian/patches/Always-initialize-any-variable-we-use-with-sscanf-s-.patch 1970-01-01 01:00:00.000000000 +0100
+++ efivar-37/debian/patches/Always-initialize-any-variable-we-use-with-sscanf-s-.patch 2020-11-21 23:53:27.000000000 +0000
@@ -0,0 +1,76 @@
+From 5dc12cc56c79d293cf68d12a0b84373a785745e7 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
+Date: Tue, 28 May 2019 16:27:31 -0400
+Subject: [PATCH] Always initialize any variable we use with sscanf's %n
+
+Signed-off-by: Peter Jones <pjones@redhat.com>
+
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1892792
+Origin: upstream,https://github.com/rhboot/efivar/commit/5dc12cc56c79d293cf68d12a0b84373a785745e7
+Last-Updated: 2020-08-24
+
+Index: efivar/src/linux-acpi-root.c
+===================================================================
+--- efivar.orig/src/linux-acpi-root.c
++++ efivar/src/linux-acpi-root.c
+@@ -44,7 +44,7 @@ static ssize_t
+ parse_acpi_root(struct device *dev, const char *current, const char *root UNUSED)
+ {
+ int rc;
+- int pos;
++ int pos = 0;
+ uint16_t pad0;
+ uint8_t pad1;
+ char *acpi_header = NULL;
+Index: efivar/src/linux-pci-root.c
+===================================================================
+--- efivar.orig/src/linux-pci-root.c
++++ efivar/src/linux-pci-root.c
+@@ -44,7 +44,7 @@ static ssize_t
+ parse_pci_root(struct device *dev, const char *current, const char *root UNUSED)
+ {
+ int rc;
+- int pos;
++ int pos = 0;
+ uint16_t root_domain;
+ uint8_t root_bus;
+ const char *devpart = current;
+Index: efivar/src/linux-pci.c
+===================================================================
+--- efivar.orig/src/linux-pci.c
++++ efivar/src/linux-pci.c
+@@ -46,7 +46,7 @@ static ssize_t
+ parse_pci(struct device *dev, const char *current, const char *root)
+ {
+ int rc;
+- int pos;
++ int pos = 0;
+ const char *devpart = current;
+
+ debug("entry");
+Index: efivar/src/linux-soc-root.c
+===================================================================
+--- efivar.orig/src/linux-soc-root.c
++++ efivar/src/linux-soc-root.c
+@@ -41,7 +41,7 @@ static ssize_t
+ parse_soc_root(struct device *dev UNUSED, const char *current, const char *root UNUSED)
+ {
+ int rc;
+- int pos;
++ int pos = 0;
+ const char *devpart = current;
+
+ debug("entry");
+Index: efivar/src/linux-virtblk.c
+===================================================================
+--- efivar.orig/src/linux-virtblk.c
++++ efivar/src/linux-virtblk.c
+@@ -48,7 +48,7 @@ static ssize_t
+ parse_virtblk(struct device *dev, const char *current, const char *root UNUSED)
+ {
+ uint32_t tosser;
+- int pos;
++ int pos = 0;
+ int rc;
+
+ debug("entry");
diff -Nru efivar-37/debian/patches/series efivar-37/debian/patches/series
--- efivar-37/debian/patches/series 2019-03-01 17:55:07.000000000 +0000
+++ efivar-37/debian/patches/series 2020-11-21 23:57:27.000000000 +0000
@@ -1 +1,8 @@
remove-arrows.patch
+Always-initialize-any-variable-we-use-with-sscanf-s-.patch
+0001-Fix-the-error-path-in-set_disk_and_part_name.patch
+0002-sysfs-parsers-make-all-the-sys-block-link-parsers-wo.patch
+0003-Try-even-harder-to-find-disk-device-symlinks-in-sysf.patch
+0004-Handle-sys-devices-virtual-nvme-fabrics-nvme-subsyst.patch
+0005-Fix-variable-sz-uninitialized-error.patch
+0006-Fix-parsing-for-nvme-subsystem-devices.patch
Reply to: