Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fde-tools for openSUSE:Factory 
checked in at 2026-10-28 17:44:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fde-tools (Old)
 and      /work/SRC/openSUSE:Factory/.fde-tools.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fde-tools"

Wed Oct 28 17:44:07 2026 rev:40 rq:1392974 version:0.7.11

Changes:
--------
--- /work/SRC/openSUSE:Factory/fde-tools/fde-tools.changes      2026-10-20 
12:36:36.094202940 +0200
+++ /work/SRC/openSUSE:Factory/.fde-tools.new.2252680/fde-tools.changes 
2026-10-28 17:44:22.417614937 +0100
@@ -1,0 +2,9 @@
+Tue Oct 27 07:12:33 UTC 2026 - Gary Ching-Pang Lin <[email protected]>
+
+- Update to 0.7.11
+  + Add fde-boot-loader helper to detect loader path without
+    efibootmgr/efibootdump (bsc#1286645)
+- Add the new utility: fde-boot-loader
+  + Also add the new BuildRequires: efivar
+
+-------------------------------------------------------------------

Old:
----
  fde-tools-0.7.10.tar.bz2

New:
----
  fde-tools-0.7.11.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ fde-tools.spec ++++++
--- /var/tmp/diff_new_pack.BsVF30/_old  2026-10-28 17:44:23.711669022 +0100
+++ /var/tmp/diff_new_pack.BsVF30/_new  2026-10-28 17:44:23.712669064 +0100
@@ -21,7 +21,7 @@
 %endif
 
 Name:           fde-tools
-Version:        0.7.10
+Version:        0.7.11
 Release:        0
 Summary:        Tools required for Full Disk Encryption
 License:        GPL-2.0-only
@@ -32,6 +32,7 @@
 Source2:        fde-tools.conf
 Patch0:         fde-tools-firstboot-alp-snapshot.patch
 BuildRequires:  help2man
+BuildRequires:  pkgconfig(efivar)
 BuildRequires:  pkgconfig(json-c)
 BuildRequires:  pkgconfig(libcryptsetup)
 BuildRequires:  pkgconfig(libfido2)
@@ -133,6 +134,7 @@
 
 %files
 %{_sbindir}/fdectl
+%{_sbindir}/fde-boot-loader
 %{_sbindir}/fde-token
 %{_sbindir}/fdectl-grub-tpm2
 %dir %{_sysconfdir}/fde

++++++ fde-tools-0.7.10.tar.bz2 -> fde-tools-0.7.11.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fde-tools-0.7.10/Makefile 
new/fde-tools-0.7.11/Makefile
--- old/fde-tools-0.7.10/Makefile       2025-07-29 05:00:40.718993772 +0200
+++ new/fde-tools-0.7.11/Makefile       2026-10-27 08:08:40.693477003 +0100
@@ -17,7 +17,8 @@
 RPM_MACRO_DIR  ?= /etc/rpm
 FIDO_LINK      = -lfido2 -lcrypto
 CRPYT_LINK     = -lcryptsetup -ljson-c
-TOOLS          = fde-token fdectl-grub-tpm2
+EFIVAR_LINK    = -lefivar
+TOOLS          = fde-token fdectl-grub-tpm2 fde-boot-loader
 TOKEN_LINK     = -lcryptsetup
 TOKEN_ABI_PATH = cryptsetup/libcryptsetup-token.sym
 TOKEN_PLUGINS  = libcryptsetup-token-grub-tpm2.so
@@ -98,6 +99,9 @@
 fdectl-grub-tpm2: build/fdectl-grub-tpm2.o
        $(CC) -o $@ $< $(CRPYT_LINK)
 
+fde-boot-loader: build/fde-boot-loader.o
+       $(CC) -o $@ $< $(EFIVAR_LINK)
+
 libcryptsetup-token-grub-tpm2.so: build/cryptsetup/cryptsetup-token-grub-tpm2.o
        $(CC) -o $@ $< $(TOKEN_LINK) -shared 
-Wl,--version-script=$(TOKEN_ABI_PATH)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fde-tools-0.7.10/fde.sh new/fde-tools-0.7.11/fde.sh
--- old/fde-tools-0.7.10/fde.sh 2026-10-16 08:54:10.331932389 +0200
+++ new/fde-tools-0.7.11/fde.sh 2026-10-27 08:08:49.812424249 +0100
@@ -22,7 +22,7 @@
 
 : ${SHAREDIR:=/usr/share/fde}
 
-version=0.7.10
+version=0.7.11
 
 opt_bootloader=grub2
 opt_uefi_bootdir=""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fde-tools-0.7.10/share/uefi 
new/fde-tools-0.7.11/share/uefi
--- old/fde-tools-0.7.10/share/uefi     2026-09-14 05:08:22.068883552 +0200
+++ new/fde-tools-0.7.11/share/uefi     2026-10-27 08:08:40.693477003 +0100
@@ -48,14 +48,11 @@
 
 function uefi_get_current_loader {
 
-    entry=$(LC_ALL=C efibootmgr | grep BootCurrent|awk '{print $2;}')
-    if [ -z "$entry" ]; then
-       fde_trace "Cannot determine current UEFI boot entry"
+    if ! file=$(fde-boot-loader); then
+       fde_trace "fde-boot-loader failed"
        return 1
     fi
 
-    file=$(LC_ALL=C efibootdump "Boot$entry" | sed 
's/.*File(\([^)]*\)).*/\1/;t;d' | tr '\\' /)
-
     # Some boot setups do not use an EFI path with a file component.
     #
     # As a fallback, check the default EFI boot path: \EFI\BOOT\boot*.efi
@@ -74,7 +71,7 @@
     fi
 
     if [ -z "$file" ]; then
-       fde_trace "Cannot determine loader path for UEFI boot entry $entry"
+       fde_trace "Cannot determine loader path for current UEFI boot entry"
        return 1
     fi
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fde-tools-0.7.10/src/fde-boot-loader.c 
new/fde-tools-0.7.11/src/fde-boot-loader.c
--- old/fde-tools-0.7.10/src/fde-boot-loader.c  1970-01-01 01:00:00.000000000 
+0100
+++ new/fde-tools-0.7.11/src/fde-boot-loader.c  2026-10-27 08:08:40.693477003 
+0100
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2026 Gary Lin <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
USA.
+ */
+
+/*
+ * fde-boot-loader: Print the EFI bootloader file path from UEFI load options.
+ *
+ * This helper utility determines the bootloader path by reading BootCurrent
+ * (or a specified Boot#### entry) directly via libefivar and parsing the 
binary
+ * EFI load option structure with explicit bounds checking.
+ *
+ * Parsing the binary device path directly avoids text-formatting ambiguities
+ * present in efibootdump/efibootmgr CLI output, where optional data can be
+ * printed immediately adjacent to the device path without a delimiter.
+ * Explicit bounds checks on node lengths and offsets ensure resilience against
+ * corrupted or malformed firmware entries.
+ *
+ * Consecutive file nodes are joined into a single path, and the extracted
+ * UCS-2 path is converted to an ASCII POSIX path (forward slashes with a
+ * leading '/') and printed to stdout. Control characters, non-ASCII 
characters,
+ * and '.' or '..' path traversal components are strictly rejected. If the boot
+ * entry has no file device path node (e.g. direct disk or network boot), the
+ * utility prints nothing and exits with status 0, allowing callers to fall
+ * back to the default boot path.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <efivar/efivar.h>
+
+#define MAX_PATH_SIZE 4096
+
+/* Read a little-endian 16-bit value from a byte buffer */
+static inline uint16_t
+le16(const uint8_t *p)
+{
+       return (uint16_t)p[0] | ((uint16_t)p[1] << 8);
+}
+
+static bool
+has_dot_component(const char *s)
+{
+       const char *p;
+
+       for (p = s; *p; p++) {
+               if ((p == s || p[-1] == '/') && p[0] == '.') {
+                       if (p[1] == '/' || p[1] == '\0')
+                               return true;
+                       if (p[1] == '.' && (p[2] == '/' || p[2] == '\0'))
+                               return true;
+               }
+       }
+       return false;
+}
+
+/* Append one character, keeping room for the terminating NUL */
+static int
+append_char(char *path, size_t *path_len, size_t max_size, char c)
+{
+       if (*path_len + 1 >= max_size) {
+               fprintf(stderr, "Path buffer exceeded\n");
+               return -1;
+       }
+       path[(*path_len)++] = c;
+       return 0;
+}
+
+/* Append a file node; the node start and each '\' begin a new component */
+static int
+append_file_node(char *path, size_t *path_len, size_t max_size,
+                const uint8_t *payload, size_t payload_len)
+{
+       bool new_comp = true;
+       size_t i;
+       uint16_t c;
+
+       for (i = 0; i + 1 < payload_len; i += 2) {
+               c = le16(payload + i);
+               if (c == 0)
+                       break;
+               if (c == '\\' || c == '/') {
+                       new_comp = true;
+                       continue;
+               }
+               if (c < 0x20 || c >= 0x7f) {
+                       fprintf(stderr, "Invalid character in boot loader path: 
0x%04x\n", c);
+                       return -1;
+               }
+               if (new_comp && append_char(path, path_len, max_size, '/') < 0)
+                       return -1;
+               new_comp = false;
+               if (append_char(path, path_len, max_size, (char)c) < 0)
+                       return -1;
+       }
+       path[*path_len] = '\0';
+       return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+       char var_name[32];
+       uint8_t *data = NULL;
+       size_t size = 0;
+       uint32_t attr = 0;
+       uint16_t id;
+       uint16_t dp_len;
+       size_t desc_offset;
+       size_t dp_offset;
+       const uint8_t *cur;
+       size_t rem;
+       uint8_t type;
+       uint8_t subtype;
+       uint16_t node_len;
+       char path[MAX_PATH_SIZE];
+       size_t path_len = 0;
+       bool in_file_path = false;
+       const char *hex_str;
+       int ret = 1;
+       int i;
+
+       path[0] = '\0';
+
+       if (argc > 1) {
+               if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 
0) {
+                       fprintf(stderr, "Usage: %s [Boot####]\n", argv[0]);
+                       return 0;
+               }
+
+               if (strncasecmp(argv[1], "Boot", 4) == 0)
+                       hex_str = argv[1] + 4;
+               else
+                       hex_str = argv[1];
+
+               if (strlen(hex_str) != 4) {
+                       fprintf(stderr, "Invalid boot entry id: %s\n", argv[1]);
+                       return 1;
+               }
+
+               for (i = 0; i < 4; i++) {
+                       if (!isxdigit((unsigned char)hex_str[i])) {
+                               fprintf(stderr, "Invalid hex digit in boot 
entry id: %s\n", argv[1]);
+                               return 1;
+                       }
+               }
+
+               id = (uint16_t)strtoul(hex_str, NULL, 16);
+       } else {
+               if (efi_get_variable(EFI_GLOBAL_GUID, "BootCurrent",
+                                    &data, &size, &attr) < 0 ||
+                   size < sizeof(uint16_t)) {
+                       fprintf(stderr, "Failed to read BootCurrent\n");
+                       goto out;
+               }
+               id = le16(data);
+               free(data);
+               data = NULL;
+       }
+
+       snprintf(var_name, sizeof(var_name), "Boot%04X", id);
+
+       if (efi_get_variable(EFI_GLOBAL_GUID, var_name, &data, &size, &attr) < 
0) {
+               fprintf(stderr, "Failed to read %s\n", var_name);
+               goto out;
+       }
+
+       if (size < 8) {
+               fprintf(stderr, "Load option in %s is too short (%zu bytes)\n", 
var_name, size);
+               goto out;
+       }
+
+       dp_len = le16(data + 4);
+
+       /* Find end of UCS-2 Description starting at offset 6 */
+       desc_offset = 6;
+       while (desc_offset + 1 < size) {
+               if (data[desc_offset] == 0 && data[desc_offset + 1] == 0)
+                       break;
+               desc_offset += 2;
+       }
+
+       if (desc_offset + 1 >= size) {
+               fprintf(stderr, "Unterminated description in %s\n", var_name);
+               goto out;
+       }
+
+       dp_offset = desc_offset + 2;
+       if (dp_offset + dp_len > size) {
+               fprintf(stderr, "Device path length %u exceeds variable size in 
%s\n", dp_len, var_name);
+               goto out;
+       }
+
+       /* Walk device path nodes within [dp_offset, dp_offset + dp_len) */
+       cur = data + dp_offset;
+       rem = dp_len;
+
+       while (rem > 0) {
+               if (rem < 4) {
+                       fprintf(stderr, "Truncated device path node header in 
%s\n", var_name);
+                       goto out;
+               }
+
+               type = cur[0];
+               subtype = cur[1];
+               node_len = le16(cur + 2);
+
+               if (node_len < 4 || node_len > rem) {
+                       fprintf(stderr, "Invalid device path node length %u 
(remaining: %zu) in %s\n",
+                               node_len, rem, var_name);
+                       goto out;
+               }
+
+               if (type == EFIDP_END_TYPE)
+                       break;
+
+               if (type == EFIDP_MEDIA_TYPE && subtype == EFIDP_MEDIA_FILE) {
+                       in_file_path = true;
+                       if ((node_len - 4) % sizeof(uint16_t) != 0) {
+                               fprintf(stderr, "Invalid file node length %u in 
%s\n", node_len, var_name);
+                               goto out;
+                       }
+                       if (append_file_node(path, &path_len, sizeof(path), cur 
+ 4, node_len - 4) < 0)
+                               goto out;
+               } else if (in_file_path) {
+                       break;
+               }
+
+               cur += node_len;
+               rem -= node_len;
+       }
+
+       if (has_dot_component(path)) {
+               fprintf(stderr, "Path traversal component in boot loader 
path\n");
+               goto out;
+       }
+
+       /* Non-file boot entries (direct disk or network boot) print nothing */
+       if (path[0] != '\0')
+               printf("%s\n", path);
+       ret = 0;
+
+out:
+       free(data);
+       return ret;
+}

Reply via email to