Source: freehsm-c
Followup-For: Bug #1149536
X-Debbugs-Cc: [email protected], [email protected]
User: [email protected]
Usertags: amd64
Control: tags -1 ftbfs

Hi,

The attached debdiff against 2.0.0-1 makes freehsm-c build on the 64-bit
non-x86 architectures and stops trying on 32-bit ones:

 * fcf-protection-only-where-supported.patch: -fcf-protection=full is
   x86-only; the Makefile now probes the compiler and only adds it when
   it is accepted. This is #1144631.

 * elf-headers-unaligned-read.patch: find_section_offset() cast the file
   buffer to Elf64_Ehdr/Elf64_Shdr pointers, which -Werror=cast-align
   rejects on riscv64. It now copies the headers with memcpy.

 * debian/control: restrict Architecture to 64-bit architectures. Upstream
   does not support 32-bit at all, the integrity check only parses ELF64
   (https://github.com/afchine1337/freehsm/issues/2).

Both patches are also proposed upstream:
https://github.com/afchine1337/freehsm/pull/18

Testing: 2.0.0-2 with the debdiff builds on amd64 in a forky container,
with -fcf-protection=full still used there, and upstream's
test-integrity passes with the ELF change. The same changes applied to
1.6.0 in Ubuntu (1.6.0-1ubuntu1) built in the Ubuntu archive on amd64,
arm64, ppc64el, riscv64 and s390x.

Regards,
Sebastien


-- System Information:
Debian Release: forky/sid
  APT prefers resolute-updates
  APT policy: (500, 'resolute-updates'), (500, 'resolute-security'), (500, 
'resolute'), (100, 'resolute-backports')
Architecture: amd64 (x86_64)

Kernel: Linux 7.0.0-38-generic (SMP w/16 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_WARN, TAINT_OOT_MODULE
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff -Nru freehsm-c-2.0.0/debian/changelog freehsm-c-2.0.0/debian/changelog
--- freehsm-c-2.0.0/debian/changelog    2026-09-03 22:05:46.000000000 +0200
+++ freehsm-c-2.0.0/debian/changelog    2026-10-09 16:15:39.000000000 +0200
@@ -1,3 +1,16 @@
+freehsm-c (2.0.0-2) UNRELEASED; urgency=medium
+
+  * d/p/fcf-protection-only-where-supported.patch: only use -fcf-
+    protection=full when the compiler supports it, fixing the build on
+    non-x86 architectures (Closes: #1144631).
+  * d/p/elf-headers-unaligned-read.patch: read ELF headers with memcpy
+    instead of casting the buffer, fixing -Werror=cast-align on riscv64.
+  * d/control: restrict to 64-bit architectures; upstream does not
+    support 32-bit (https://github.com/afchine1337/freehsm/issues/2)
+    (Closes: #1149536).
+
+ -- Sebastien Bacher <[email protected]>  Fri, 09 Oct 2026 16:15:39 +0200
+
 freehsm-c (2.0.0-1) unstable; urgency=medium
 
   * Refresh d/patches
diff -Nru freehsm-c-2.0.0/debian/control freehsm-c-2.0.0/debian/control
--- freehsm-c-2.0.0/debian/control      2026-09-03 22:05:46.000000000 +0200
+++ freehsm-c-2.0.0/debian/control      2026-10-09 16:15:39.000000000 +0200
@@ -13,7 +13,7 @@
 Vcs-Git: https://salsa.debian.org/debian/freehsm-c.git
 
 Package: freehsm-c
-Architecture: any
+Architecture: amd64 arm64 ppc64el riscv64 s390x loong64 mips64el sparc64 alpha 
ia64
 Section: libs
 Multi-Arch: no
 Description: PKCS#11 module re-implementing FreeHSM Soft HSM
diff -Nru freehsm-c-2.0.0/debian/patches/elf-headers-unaligned-read.patch 
freehsm-c-2.0.0/debian/patches/elf-headers-unaligned-read.patch
--- freehsm-c-2.0.0/debian/patches/elf-headers-unaligned-read.patch     
1970-01-01 01:00:00.000000000 +0100
+++ freehsm-c-2.0.0/debian/patches/elf-headers-unaligned-read.patch     
2026-10-09 16:15:39.000000000 +0200
@@ -0,0 +1,74 @@
+Description: integrity: read ELF headers with memcpy instead of casting the 
buffer
+ find_section_offset() cast the file buffer to Elf64_Ehdr / Elf64_Shdr
+ pointers. The section header table offset comes from the file, so those
+ pointers are not guaranteed to be aligned, and on strict-alignment
+ targets such as riscv64 -Wcast-align (an error with -Werror) rejects
+ the casts:
+ .
+   src/fhsm_integrity.c: error: cast increases required alignment of
+   target type [-Werror=cast-align]
+ .
+ Copy the ELF header and each section header into local structs with
+ memcpy, which is valid whatever the alignment. While there, reject an
+ unexpected e_shentsize and sh_name values pointing outside the section
+ name string table.
+ .
+ The result is unchanged for valid files: test-integrity passes
+ (unsigned, signed and tampered cases).
+Author: Sebastien Bacher <[email protected]>
+Bug-Debian: https://bugs.debian.org/1149536
+Forwarded: https://github.com/afchine1337/freehsm/pull/18
+Last-Update: 2026-10-09
+---
+Index: freehsm-c-2.0.0/src/fhsm_integrity.c
+===================================================================
+--- freehsm-c-2.0.0.orig/src/fhsm_integrity.c
++++ freehsm-c-2.0.0/src/fhsm_integrity.c
+@@ -174,24 +174,33 @@ static int find_section_offset(const uin
+                                  const char *name,
+                                  size_t *out_off, size_t *out_len)
+ {
++    /* Copy the headers out with memcpy instead of casting into the
++     * buffer: casting a uint8_t pointer to Elf64_Ehdr / Elf64_Shdr is
++     * rejected by -Wcast-align on strict-alignment targets (riscv64),
++     * and the section table offset comes from the file. */
++    Elf64_Ehdr eh;
++    Elf64_Shdr shstr, sh;
+     if (map_len < sizeof(Elf64_Ehdr)) return -1;
+-    const Elf64_Ehdr *eh = (const Elf64_Ehdr *)map;
+-    if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0) return -1;
+-    if (eh->e_ident[EI_CLASS] != ELFCLASS64) return -1;
+-    if (eh->e_shoff == 0 || eh->e_shnum == 0)  return -1;
+-    if (eh->e_shoff + (size_t)eh->e_shnum * eh->e_shentsize > map_len) return 
-1;
++    memcpy(&eh, map, sizeof eh);
++    if (memcmp(eh.e_ident, ELFMAG, SELFMAG) != 0) return -1;
++    if (eh.e_ident[EI_CLASS] != ELFCLASS64) return -1;
++    if (eh.e_shoff == 0 || eh.e_shnum == 0)  return -1;
++    if (eh.e_shentsize != sizeof(Elf64_Shdr)) return -1;
++    if (eh.e_shoff + (size_t)eh.e_shnum * eh.e_shentsize > map_len) return -1;
+ 
+-    const Elf64_Shdr *sh = (const Elf64_Shdr *)(map + eh->e_shoff);
+-    if (eh->e_shstrndx >= eh->e_shnum) return -1;
+-    const Elf64_Shdr *shstr = &sh[eh->e_shstrndx];
+-    if (shstr->sh_offset + shstr->sh_size > map_len) return -1;
+-    const char *strtab = (const char *)(map + shstr->sh_offset);
++    const uint8_t *shtab = map + eh.e_shoff;
++    if (eh.e_shstrndx >= eh.e_shnum) return -1;
++    memcpy(&shstr, shtab + (size_t)eh.e_shstrndx * sizeof(Elf64_Shdr), sizeof 
shstr);
++    if (shstr.sh_offset + shstr.sh_size > map_len) return -1;
++    const char *strtab = (const char *)(map + shstr.sh_offset);
+ 
+-    for (uint16_t i = 0; i < eh->e_shnum; ++i) {
+-        const char *n = strtab + sh[i].sh_name;
++    for (uint16_t i = 0; i < eh.e_shnum; ++i) {
++        memcpy(&sh, shtab + (size_t)i * sizeof(Elf64_Shdr), sizeof sh);
++        if (sh.sh_name >= shstr.sh_size) return -1;
++        const char *n = strtab + sh.sh_name;
+         if (strcmp(n, name) == 0) {
+-            *out_off = sh[i].sh_offset;
+-            *out_len = sh[i].sh_size;
++            *out_off = sh.sh_offset;
++            *out_len = sh.sh_size;
+             return 0;
+         }
+     }
diff -Nru 
freehsm-c-2.0.0/debian/patches/fcf-protection-only-where-supported.patch 
freehsm-c-2.0.0/debian/patches/fcf-protection-only-where-supported.patch
--- freehsm-c-2.0.0/debian/patches/fcf-protection-only-where-supported.patch    
1970-01-01 01:00:00.000000000 +0100
+++ freehsm-c-2.0.0/debian/patches/fcf-protection-only-where-supported.patch    
2026-10-09 16:15:39.000000000 +0200
@@ -0,0 +1,36 @@
+Description: build: only use -fcf-protection=full where the compiler supports 
it
+ -fcf-protection=full enables Intel CET and only exists on x86. On every
+ other architecture GCC fails with:
+ .
+   cc1: error: '-fcf-protection=full' is not supported for this target
+ .
+ so the module does not build on arm64, ppc64el, riscv64 or s390x.
+ .
+ Probe the compiler once and only add the flag when it is accepted. On
+ x86 the flags are unchanged.
+ .
+Author: Sebastien Bacher <[email protected]>
+Bug-Debian: https://bugs.debian.org/1144631
+Forwarded: https://github.com/afchine1337/freehsm/pull/18
+Last-Update: 2026-10-09
+---
+Index: freehsm-c-2.0.0/Makefile
+===================================================================
+--- freehsm-c-2.0.0.orig/Makefile
++++ freehsm-c-2.0.0/Makefile
+@@ -43,9 +43,14 @@ WARN_FLAGS = \
+     -Wnull-dereference -Wdouble-promotion -Wconversion \
+     -Wno-sign-conversion -Wno-unused-parameter
+ 
++# -fcf-protection=full (Intel CET) only exists on x86; GCC rejects it as
++# "not supported for this target" everywhere else. Only use it when the
++# compiler accepts it.
++CF_PROTECTION_FLAG := $(shell $(CC) -Werror -fcf-protection=full -x c -c 
/dev/null -o /dev/null >/dev/null 2>&1 && echo -fcf-protection=full)
++
+ HARDEN_FLAGS = \
+     -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIC \
+-    -fstack-clash-protection -fcf-protection=full \
++    -fstack-clash-protection $(CF_PROTECTION_FLAG) \
+     -fvisibility=hidden -fno-strict-aliasing \
+     -fno-omit-frame-pointer \
+     -DOPENSSL_API_COMPAT=0x30000000L
diff -Nru freehsm-c-2.0.0/debian/patches/series 
freehsm-c-2.0.0/debian/patches/series
--- freehsm-c-2.0.0/debian/patches/series       2026-09-03 22:05:46.000000000 
+0200
+++ freehsm-c-2.0.0/debian/patches/series       2026-10-09 16:15:30.000000000 
+0200
@@ -1 +1,3 @@
 inject-compiler-linker-flags.patch
+fcf-protection-only-where-supported.patch
+elf-headers-unaligned-read.patch

Reply via email to