From nobody Mon Jun 8 13:56:14 2026 X-Original-To: bugs@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gYtqf56TFz6g6Qw for ; Mon, 08 Jun 2026 13:56:14 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gYtqf4d0Qz49xS for ; Mon, 08 Jun 2026 13:56:14 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780926974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wyMS+pQ4I/mYikFvisy0Y3JgUC8yQ/sVLWol/jifvlY=; b=HCwxi2pqLUdds66QXNi0PAZ1SSUeG8Yz86Z3p6jAdyKcW5fXHA3CxlVMS4dAvpDArs3xiL 4PyaaLzK6pns5nRMZvQJ5zzgzs7LxUl9t3qa+2FZWqSLCarYu3xxCoDOHpKZ6fmN9Z7bFt BjYQI2/QX4n180VebjmXlsnGefDT1VQx7H9uC3oFAnUm5AqvdU20w3TQWtSybbI0ulVdzU CD8+qrULVzcp0h/lsxVK7bkiJQSNBugRPxmStvFkoeUSQwsvgldbfmc37p/09NIRGCZvll Q+PLyXnFTb3nGYuxWHOL22BNaBcGyIrqtSwPr1dxmUMdEJgYXJKw/z+VtotRaw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1780926974; a=rsa-sha256; cv=none; b=uB8H+H43mxG4P2OYG7sIwEutqT07LGTw6sk1HR7VqB2XGHKamSZvtyPXBcyvrxQQv4gY/C K8cnMEbz4dlDwQvEpYJFvQyRenk2e8mTNDwLSkzoH7OY+SrK0QJDG6UYGDXY6BINqSgfw1 LkAmpy8Uw1r0Jaej7srSm6HBu+BPeQ+gJ7BYPkfy7InqRFkhCx/k43xbCoN014DnMMXoG2 3c/YASbjKssilLoof3FqlAhgE29DTBSXCtAv4V6Kn3EgF59/JWc2MckXIhk6HKFEnbw/RT Ws5itYWOeYlhPGpUagCijKD2YJloYiGDSUEgpcvRgajgRZC6v6LPddYS518d8Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780926974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wyMS+pQ4I/mYikFvisy0Y3JgUC8yQ/sVLWol/jifvlY=; b=O7tD7VbRz0ocrlz4auwdH1K1Rr3gcunfFL2esqlbkJNE1bP1jhG9wOrwr0dxZF3wsMwPhS Misl6RUT4YjZV9vKSB03sTQRndy800OHTfvqVx3dJgVQVuxfgh+ghfqNypDp5pSTsJEelN Qb1X0hQ+jFaDeSRKieZQijiBqZ0DfjRYdof0Ro7OYMgXD5rmLTjVeUZ3OP9S9txoI/Oe2d JEl3H3ADczryzUxOc6R3m7BmVeYYJQdP+mHD/3haM3MKXG2e0gXTFwermJpyZYsftk6N97 OcVbCllrXFKCai6IGOgwecv5N42SV/WybjYxXjq7Tp/BljqYWjdnPqY8r2UqXQ== Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2610:1c1:1:606c::50:1d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4gYtqf3vzTzqpG for ; Mon, 08 Jun 2026 13:56:14 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org ([127.0.1.5]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id 658DuET3069636 for ; Mon, 8 Jun 2026 13:56:14 GMT (envelope-from bugzilla-noreply@freebsd.org) Received: (from www@localhost) by kenobi.freebsd.org (8.15.2/8.15.2/Submit) id 658DuEv5069635 for bugs@FreeBSD.org; Mon, 8 Jun 2026 13:56:14 GMT (envelope-from bugzilla-noreply@freebsd.org) X-Authentication-Warning: kenobi.freebsd.org: www set sender to bugzilla-noreply@freebsd.org using -f From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 295935] stand/libsa: fstat() returns an uninitialized struct stat, causing spurious veriexec "no entry" on ZFS root under Secure Boot Date: Mon, 08 Jun 2026 13:56:14 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: bin X-Bugzilla-Version: 16.0-CURRENT X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Only Me X-Bugzilla-Who: etienne.bonnand@defenso.fr X-Bugzilla-Status: New X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: bugs@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter Message-ID: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="UTF-8" X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated List-Id: Bug reports List-Archive: https://lists.freebsd.org/archives/freebsd-bugs List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-bugs@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D295935 Bug ID: 295935 Summary: stand/libsa: fstat() returns an uninitialized struct stat, causing spurious veriexec "no entry" on ZFS root under Secure Boot Product: Base System Version: 16.0-CURRENT Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: bin Assignee: bugs@FreeBSD.org Reporter: etienne.bonnand@defenso.fr Product: Base System Component: bin (boot loader / stand) Version: 16.0-CURRENT --- Summary --- With a verified-boot loader (LOADER_VERIEXEC / LOADER_VERIEXEC_VECTX) and a= ZFS root, the loader fails to verify the kernel against a correct, signed manif= est: Verified /boot/kernel/manifest signed by Unverified /boot/kernel/kernel: no entry The manifest contains a correct, properly formatted entry for the kernel wh= ose SHA-256 matches the on-disk file. The same configuration works on UFS. --- Root cause --- lib/libsecureboot/veopen.c, fingerprint_info_lookup() filters manifest entr= ies by device number: if (fip->fi_dev !=3D 0 && fip->fi_dev !=3D dev) continue; fi_dev is the st_dev of the manifest file (fingerprint_info_add(), veopen.c ~124); dev is the st_dev of the verified file (fstat() in fingerprint_info_lookup(), veopen.c ~206-207). Both come from struct stat objects that are never zero-initialized: - lib/libsecureboot/veopen.c declares "struct stat st;" at lines 198 and = 422 with no initialization. - stand/libsa/fstat.c:35 =E2=80=94 fstat() passes the caller's struct sta= t straight to fo_stat without memset'ing it. - stand/libsa/zfs/zfsimpl.c =E2=80=94 zfs_dnode_stat() only sets st_mode = (3708), st_uid, st_gid and st_size; it never assigns st_dev. On ZFS, st_dev therefore retains stack garbage. fi_dev and dev are read from two different uninitialized stack frames, so they almost always differ. The "fi_dev !=3D 0" guard does not help, because fi_dev is garbage too (rarely exactly 0). The only matching manifest entry is skipped, fingerprint_info_lookup() returns NULL, and verify_fd() emits "no entry" (veopen.c ~430). UFS is unaffected: stand/libsa/ufs.c:869 sets st_dev =3D (dev_t)(fp->f_fs->fs_id[0] ^ fp->f_fs->fs_id[1]), so manifest and target share the same value and the comparison passes. The UNIT_TEST paths in veopen.c force both fi_dev and dev to 0, which indic= ates the device comparison was already known to be unreliable outside a real ker= nel. --- Reproduction --- 1. ZFS-on-root (zroot/ROOT/default over GELI), amd64. 2. Build the EFI loader with WITH_BEARSSL, WITH_LOADER_VERIEXEC, WITH_LOADER_VERIEXEC_VECTX, WITH_LOADER_EFI_SECUREBOOT. 3. Generate and sign a /boot/kernel manifest (kernel + modules), enroll the signing certificate, enable UEFI Secure Boot. 4. At the loader prompt: unload; load /boot/kernel/kernel 5. The manifest signature verifies, but the kernel lookup fails with "no entry". The manifest line is byte-for-byte correct (hexdump: "kernel sha256=3D\n", single 0x20 separator, no CRLF, hash matches sha256 of the kernel). --- Suggested fix --- The underlying defect is that the loader's stat path returns a struct stat = with uninitialized fields. Zero the struct in stand/libsa/fstat.c before it is populated, so filesystems that do not set every field (the standalone ZFS implementation does not set st_dev) leave those fields as 0 rather than sta= ck garbage: int fstat(int fd, struct stat *sb) { ... memset(sb, 0, sizeof(*sb)); /* ensure unset fields are 0, not garbage */ ... } With st_dev =3D=3D 0 on both sides, the existing "fi_dev !=3D 0" guard in v= eopen.c neutralizes the device comparison, and verification proceeds based on path matching and the signed hash (where the actual security guarantee lies). Th= is fixes the symptom without modifying libsecureboot, and is a general robustn= ess improvement: a struct stat should never be returned with uninitialized fiel= ds. An alternative is to have zfs_dnode_stat() set st_dev to a stable per-datas= et value (as UFS does with fs_id), but a correct stable value is less obvious = in the standalone ZFS code, and the memset addresses the broader class of uninitialized-field issues. --- Environment --- FreeBSD 16.0-CURRENT, amd64, Lenovo ThinkPad T14s Gen 6. Root: ZFS (zroot/ROOT/default) over GELI. UEFI Secure Boot enabled, custom signing key enrolled in db. --=20 You are receiving this mail because: You are the assignee for the bug.=