Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package tboot for openSUSE:Factory checked in at 2026-06-25 10:57:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/tboot (Old) and /work/SRC/openSUSE:Factory/.tboot.new.2088 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tboot" Thu Jun 25 10:57:00 2026 rev:54 rq:1361572 version:20250417_1.11.12 Changes: -------- --- /work/SRC/openSUSE:Factory/tboot/tboot.changes 2026-01-22 15:15:44.594145714 +0100 +++ /work/SRC/openSUSE:Factory/.tboot.new.2088/tboot.changes 2026-06-25 10:59:07.821341104 +0200 @@ -1,0 +2,42 @@ +Wed Jun 24 10:43:49 UTC 2026 - Matthias Gerstner <[email protected]> + +- add tboot-grub2-fix-version-find-latest.diff: grub2-mkconfig no longer works + with the tboot drop-in configuration files, because they rely on the no + longer available "find_version_latest" (bsc#1266833). This patch provides + drop-in replacements of that function based on the recommended + "version_sort()" helper function. + +------------------------------------------------------------------- +Wed Jun 24 10:17:19 UTC 2026 - Matthias Gerstner <[email protected]> + +- update to version v1.11.12: + Fix lcptools-v2 compilation error, caused by incorrect size of + digest buffer allocation. The size of the digest buffer should be + SHA1_DIGEST_SIZE, not sizeof(tb_hash_t). + + Fix SGX status verification. TBOOT used improper method of the SGX + status verification. Added proper SGX status verification by checking + both CPUID and MSR_IA32_FEATURE_CONTROL[bit 18]. If SGX is not + enabled, TBOOT will print error message and return without doing the + SVN check. + + Secure pointer to the TBOOT Log base from unauthorized DMA access. + Defined new functions in tboot.h to return the base address of the + TBOOT Log and validate its UUID, ensuring proper initialization. + + Provide DMA protection for global variable holding the number of e820 + entries. Defined a secure global pointer in OsMleData structure, + protected from unauthorized DMA access, with verification procedure + called before e820 map copying and TXT heap initialization. + +- update to version v1.11.11: + + Provide new cmdline option - "force_pmrs", which disabled TPR + configuration and support both for TBOOT and SINIT ACM. TBOOT sets + PMRs for SINIT ACM as it's default memory protection mechanism. + Disable Intel CET technology, during TBOOT shutdown execution. + +- drop tboot-fix-alloc-size-warning.patch: now contained upstream. +- drop tboot-cet.patch: now contained upstream. + +------------------------------------------------------------------- Old: ---- tboot-1.11.10.tar.gz tboot-1.11.10.tar.gz.gpg tboot-cet.patch tboot-fix-alloc-size-warning.patch New: ---- tboot-1.11.12.tar.gz tboot-1.11.12.tar.gz.gpg tboot-grub2-fix-version-find-latest.diff ----------(Old B)---------- Old:- drop tboot-fix-alloc-size-warning.patch: now contained upstream. - drop tboot-cet.patch: now contained upstream. Old: - drop tboot-fix-alloc-size-warning.patch: now contained upstream. - drop tboot-cet.patch: now contained upstream. ----------(Old E)---------- ----------(New B)---------- New: - add tboot-grub2-fix-version-find-latest.diff: grub2-mkconfig no longer works with the tboot drop-in configuration files, because they rely on the no ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tboot.spec ++++++ --- /var/tmp/diff_new_pack.CSU7bw/_old 2026-06-25 10:59:08.393360224 +0200 +++ /var/tmp/diff_new_pack.CSU7bw/_new 2026-06-25 10:59:08.393360224 +0200 @@ -1,7 +1,7 @@ # # spec file for package tboot # -# Copyright (c) 2026 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: tboot -%define ver 1.11.10 +%define ver 1.11.12 Version: 20250417_%{ver} Release: 0 Summary: Program for performing a verified launch using Intel TXT @@ -33,8 +33,7 @@ Patch3: tboot-distributor.patch Patch4: tboot-grub2-refuse-secure-boot.patch Patch5: tboot-bsc#1207833-copy-mbi.patch -Patch6: tboot-fix-alloc-size-warning.patch -Patch7: tboot-cet.patch +Patch6: tboot-grub2-fix-version-find-latest.diff Patch8: gcc16-compat.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build ExclusiveArch: %{ix86} x86_64 ++++++ gcc16-compat.patch ++++++ --- /var/tmp/diff_new_pack.CSU7bw/_old 2026-06-25 10:59:08.425361294 +0200 +++ /var/tmp/diff_new_pack.CSU7bw/_new 2026-06-25 10:59:08.429361427 +0200 @@ -1,7 +1,7 @@ -Index: tboot-1.11.10/safestringlib/safeclib/strpbrk_s.c +Index: tboot-1.11.12/safestringlib/safeclib/strpbrk_s.c =================================================================== ---- tboot-1.11.10.orig/safestringlib/safeclib/strpbrk_s.c -+++ tboot-1.11.10/safestringlib/safeclib/strpbrk_s.c +--- tboot-1.11.12.orig/safestringlib/safeclib/strpbrk_s.c ++++ tboot-1.11.12/safestringlib/safeclib/strpbrk_s.c @@ -92,7 +92,6 @@ strpbrk_s (char *dest, rsize_t dmax, char *src, rsize_t slen, char **first) { ++++++ tboot-1.11.10.tar.gz -> tboot-1.11.12.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/.hg_archival.txt new/tboot-1.11.12/.hg_archival.txt --- old/tboot-1.11.10/.hg_archival.txt 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/.hg_archival.txt 2026-03-18 15:37:09.000000000 +0100 @@ -1,4 +1,4 @@ repo: cedd93279188334eb41d248d5eb70a41a2bc70ca -node: 4bf2e38197238a539530eab991244723fb127ba1 +node: 174b80ceb338b17bcb5a3161531acd7562d122f9 branch: default -tag: v1.11.10 +tag: v1.11.12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/.hgtags new/tboot-1.11.12/.hgtags --- old/tboot-1.11.10/.hgtags 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/.hgtags 2026-03-18 15:37:09.000000000 +0100 @@ -51,3 +51,5 @@ 0000000000000000000000000000000000000000 v1.11.9 0000000000000000000000000000000000000000 v1.11.9 93a7c34511548204c2921a5c427085d352e64eb7 v1.11.9 +4bf2e38197238a539530eab991244723fb127ba1 v1.11.10 +94c0de658794f271a9d6a2b5f78d08f69274ecda v1.11.11 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/CHANGELOG new/tboot-1.11.12/CHANGELOG --- old/tboot-1.11.10/CHANGELOG 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/CHANGELOG 2026-03-18 15:37:09.000000000 +0100 @@ -1,3 +1,27 @@ +20260318: v1.11.12 + Fix lcptools-v2 compilation error, caused by incorrect size of + digest buffer allocation. The size of the digest buffer should be + SHA1_DIGEST_SIZE, not sizeof(tb_hash_t). + + Fix SGX status verification. TBOOT used improper method of the SGX + status verification. Added proper SGX status verification by checking + both CPUID and MSR_IA32_FEATURE_CONTROL[bit 18]. If SGX is not + enabled, TBOOT will print error message and return without doing the + SVN check. + + Secure pointer to the TBOOT Log base from unauthorized DMA access. + Defined new functions in tboot.h to return the base address of the + TBOOT Log and validate its UUID, ensuring proper initialization. + + Provide DMA protection for global variable holding the number of e820 + entries. Defined a secure global pointer in OsMleData structure, + protected from unauthorized DMA access, with verification procedure + called before e820 map copying and TXT heap initialization. +20260214: v1.11.11 + Provide new cmdline option - "force_pmrs", which disabled TPR + configuration and support both for TBOOT and SINIT ACM. TBOOT sets + PMRs for SINIT ACM as it's default memory protection mechanism. + Disable Intel CET technology, during TBOOT shutdown execution. 20250417: v1.11.10 Fix the issue causing tboot to hang during waking up processors from txt sleep on DMR simics diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/include/tb_error.h new/tboot-1.11.12/include/tb_error.h --- old/tboot-1.11.10/include/tb_error.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/include/tb_error.h 2026-03-18 15:37:09.000000000 +0100 @@ -40,6 +40,7 @@ TB_ERR_NONE = 0, /* succeed */ TB_ERR_FIXED = 1, /* previous error has been fixed */ TB_ERR_GENERIC, /* non-fatal generic error */ + TB_ERR_DMA_CORRUPTION_DETECTED, /* DMA corruption detected */ TB_ERR_TPM_NOT_READY, /* tpm not ready */ TB_ERR_SMX_NOT_SUPPORTED, /* smx not supported */ TB_ERR_VMX_NOT_SUPPORTED, /* vmx not supported */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/lcptools-v2/pconf_legacy.c new/tboot-1.11.12/lcptools-v2/pconf_legacy.c --- old/tboot-1.11.10/lcptools-v2/pconf_legacy.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/lcptools-v2/pconf_legacy.c 2026-03-18 15:37:09.000000000 +0100 @@ -324,7 +324,7 @@ ERROR("Error: no pcrs were selected.\n"); return NULL; } - digest = malloc(SHA1_DIGEST_SIZE); + digest = malloc(sizeof(tb_hash_t)); if (digest == NULL) { ERROR("Error: failed to allocate memory for digest buffer.\n"); return NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/20_linux_tboot new/tboot-1.11.12/tboot/20_linux_tboot --- old/tboot-1.11.10/tboot/20_linux_tboot 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/20_linux_tboot 2026-03-18 15:37:09.000000000 +0100 @@ -195,7 +195,7 @@ tboot_dirname=`dirname ${current_tboot}` rel_tboot_dirname=`make_system_path_relative_to_its_root $tboot_dirname` # tboot_version=`echo $tboot_basename | sed -e "s,.gz$,,g;s,^tboot-,,g"` - tboot_version="1.11.10" + tboot_version="1.11.12" echo "submenu \"tboot ${tboot_version}\" {" while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/20_linux_xen_tboot new/tboot-1.11.12/tboot/20_linux_xen_tboot --- old/tboot-1.11.10/tboot/20_linux_xen_tboot 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/20_linux_xen_tboot 2026-03-18 15:37:09.000000000 +0100 @@ -230,7 +230,7 @@ tboot_basename=`basename ${current_tboot}` tboot_dirname=`dirname ${current_tboot}` rel_tboot_dirname=`make_system_path_relative_to_its_root $tboot_dirname` - tboot_version="1.11.10" + tboot_version="1.11.12" list="${linux_list}" echo "submenu \"Xen ${xen_version}\" \"Tboot ${tboot_version}\"{" while [ "x$list" != "x" ] ; do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/Config.mk new/tboot-1.11.12/tboot/Config.mk --- old/tboot-1.11.10/tboot/Config.mk 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/Config.mk 2026-03-18 15:37:09.000000000 +0100 @@ -1,4 +1,4 @@ -# Copyright (c) 2006-2010, Intel Corporation +# Copyright (c) 2006-2026, Intel Corporation # All rights reserved. # -*- mode: Makefile; -*- @@ -6,8 +6,8 @@ # # tboot-specific build settings # -RELEASEVER := "1.11.10" -RELEASETIME := "2025-04-17 16:00 +0100" +RELEASEVER := "1.11.12" +RELEASETIME := "2026-03-18 16:00 +0100" ROOTDIR ?= $(CURDIR)/.. # tboot needs too many customized compiler settings to use system CFLAGS, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/cmdline.c new/tboot-1.11.12/tboot/common/cmdline.c --- old/tboot-1.11.10/tboot/common/cmdline.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/cmdline.c 2026-03-18 15:37:09.000000000 +0100 @@ -85,6 +85,7 @@ { "measure_nv", "false" }, /* true|false */ { "extpol", "sha256" }, /*agile|embedded|sha1|sha256|sm3|... */ { "ignore_prev_err", "true"}, /* true|false */ + { "force_pmrs", "false"}, /* true|false */ { "force_tpm2_legacy_log", "false"}, /* true|false */ { "save_vtd", "false"}, /* true|false */ { "dump_memmap", "false"}, /* true|false */ @@ -541,6 +542,19 @@ } } +bool get_tboot_force_pmrs(void) +{ + const char *force_pmrs = get_option_val(g_tboot_cmdline_options, + g_tboot_param_values, + "force_pmrs"); + if (force_pmrs != NULL && (tb_strcmp(force_pmrs, "true") == 0)) + { + return true; + } + + return false; +} + bool get_tboot_force_tpm2_legacy_log(void) { const char *force_legacy_log = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/e820.c new/tboot-1.11.12/tboot/common/e820.c --- old/tboot-1.11.10/tboot/common/e820.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/e820.c 2026-03-18 15:37:09.000000000 +0100 @@ -58,8 +58,9 @@ * this version will replace original in mbi */ #define MAX_E820_ENTRIES (TBOOT_E820_COPY_SIZE / sizeof(memory_map_t)) -static unsigned int g_nr_map; -static memory_map_t *g_copy_e820_map = (memory_map_t *)TBOOT_E820_COPY_ADDR; +static uint32_t g_num_of_e820_entries = 0; +static uint32_t *g_nr_map = &g_num_of_e820_entries; +static memory_map_t *const g_copy_e820_map = (memory_map_t *)TBOOT_E820_COPY_ADDR; static inline void split64b(uint64_t val, uint32_t *val_lo, uint32_t *val_hi) { *val_lo = (uint32_t)(val & 0xffffffff); @@ -110,9 +111,9 @@ * Prints copied e820 map w/o any header (i.e. just entries, indented by a tab) * */ -static void print_map(memory_map_t *e820, int nr_map) +static void print_map(memory_map_t *const e820, uint32_t nr_map) { - for ( int i = 0; i < nr_map; i++ ) { + for ( uint32_t i = 0; i < nr_map; i++ ) { memory_map_t *entry = &e820[i]; uint64_t base_addr, length; @@ -127,7 +128,7 @@ } } -static bool insert_after_region(memory_map_t *e820map, unsigned int *nr_map, +static bool insert_after_region(memory_map_t *const e820map, uint32_t *const nr_map, unsigned int pos, uint64_t addr, uint64_t size, uint32_t type) { @@ -152,7 +153,7 @@ return true; } -static void remove_region(memory_map_t *e820map, unsigned int *nr_map, +static void remove_region(memory_map_t *const e820map, uint32_t *const nr_map, unsigned int pos) { /* shift (copy) everything down one entry */ @@ -162,7 +163,7 @@ (*nr_map)--; } -static bool protect_region(memory_map_t *e820map, unsigned int *nr_map, +static bool protect_region(memory_map_t *const e820map, uint32_t *const nr_map, uint64_t new_addr, uint64_t new_size, uint32_t new_type) { @@ -298,7 +299,7 @@ return g_copy_e820_map; } -unsigned int get_nr_map() +uint32_t *get_nr_map_ptr(void) { return g_nr_map; } @@ -310,11 +311,22 @@ * * return: false = error (no table or table too big for new space) */ -bool copy_e820_map(loader_ctx *lctx) +bool copy_e820_map(loader_ctx *lctx, uint32_t *const nr_map) { get_tboot_min_ram(); - g_nr_map = 0; + /* Verify nr_map pointer */ + if (nr_map == NULL) { + printk(TBOOT_ERR"e820: nr_map pointer is NULL.\n"); + return false; + } + + if (!verify_g_nr_map_ptr(nr_map)) { + printk(TBOOT_ERR"e820: memory map copying failed.\n"); + return false; + } + + *nr_map = 0; if (have_loader_memmap(lctx)){ uint32_t memmap_length = get_loader_memmap_length(lctx); @@ -325,14 +337,14 @@ uint32_t entry_offset = 0; while ( entry_offset < memmap_length && - g_nr_map < MAX_E820_ENTRIES ) { + *nr_map < MAX_E820_ENTRIES ) { memory_map_t *entry = (memory_map_t *) (((uint32_t) memmap) + entry_offset); /* we want to support unordered and/or overlapping entries */ /* so use protect_region() to insert into existing map, since */ /* it handles these cases */ - if ( !protect_region(g_copy_e820_map, &g_nr_map, + if ( !protect_region(g_copy_e820_map, nr_map, e820_base_64(entry), e820_length_64(entry), entry->type) ) return false; @@ -347,7 +359,7 @@ entry_offset += sizeof(memory_map_t); } - if ( g_nr_map == MAX_E820_ENTRIES ) { + if ( *nr_map == MAX_E820_ENTRIES ) { printk(TBOOT_ERR"Too many e820 entries\n"); return false; } @@ -373,7 +385,7 @@ g_copy_e820_map[1].type = E820_RAM; g_copy_e820_map[1].size = sizeof(memory_map_t) - sizeof(uint32_t); - g_nr_map = 2; + *nr_map = 2; } else { printk(TBOOT_ERR"no e820 map nor memory limits provided\n"); @@ -385,7 +397,22 @@ bool e820_protect_region(uint64_t addr, uint64_t size, uint32_t type) { - return protect_region(g_copy_e820_map, &g_nr_map, addr, size, type); + return protect_region(g_copy_e820_map, g_nr_map, addr, size, type); +} + +bool e820_verify_num_of_entries(void) +{ + /* Verify number of the e820 memory map entries */ + if (*g_nr_map >= MAX_E820_ENTRIES) + { + printk(TBOOT_ERR"Too many e820 entries\n"); + printk(TBOOT_ERR"It should be noticed during e820 memmap copying.\n"); + printk(TBOOT_ERR"g_nr_map had to be corrupted prior to the Vt-d setup\n"); + printk(TBOOT_ERR"Number of e820 memmap entries: %u\n", *g_nr_map); + return false; + } + + return true; } /* @@ -409,7 +436,7 @@ e820_base = 0; e820_length = 0; - for ( unsigned int i = 0; i < g_nr_map; i = gap ? i : i+1, gap = !gap ) { + for ( unsigned int i = 0; i < *g_nr_map; i = gap ? i : i+1, gap = !gap ) { e820_entry = &g_copy_e820_map[i]; if ( gap ) { /* deal with the gap in e820 map */ @@ -511,7 +538,7 @@ end = base + length; /* find where our region should cover the ram in e820 */ - for ( unsigned int i = 0; i < g_nr_map; i++ ) { + for ( unsigned int i = 0; i < *g_nr_map; i++ ) { e820_entry = &g_copy_e820_map[i]; e820_base = e820_base_64(e820_entry); e820_length = e820_length_64(e820_entry); @@ -537,7 +564,7 @@ else if ( (e820_base >= base) && (end > e820_base) && (e820_end > end) ) { /* split the current ram map */ - if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i-1, + if ( !insert_after_region(g_copy_e820_map, g_nr_map, i-1, e820_base, (end - e820_base), E820_RESERVED) ) return false; @@ -558,7 +585,7 @@ split64b((base - e820_base), &(g_copy_e820_map[i].length_low), &(g_copy_e820_map[i].length_high)); /* split the current ram map */ - if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i, base, + if ( !insert_after_region(g_copy_e820_map, g_nr_map, i, base, (e820_end - base), E820_RESERVED) ) return false; i++; @@ -570,12 +597,12 @@ split64b((base - e820_base), &(g_copy_e820_map[i].length_low), &(g_copy_e820_map[i].length_high)); /* split the current ram map */ - if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i, base, + if ( !insert_after_region(g_copy_e820_map, g_nr_map, i, base, length, E820_RESERVED) ) return false; i++; /* fixup the rest of the current ram map */ - if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i, end, + if ( !insert_after_region(g_copy_e820_map, g_nr_map, i, end, (e820_end - end), e820_entry->type) ) return false; i++; @@ -593,7 +620,7 @@ void print_e820_map(void) { - print_map(g_copy_e820_map, g_nr_map); + print_map(g_copy_e820_map, *g_nr_map); } bool get_ram_ranges(uint64_t *min_lo_ram, uint64_t *max_lo_ram, @@ -623,7 +650,7 @@ g_min_ram, last_min_ram_base, last_min_ram_size); } - for ( unsigned int i = 0; i < g_nr_map; i++ ) { + for ( unsigned int i = 0; i < *g_nr_map; i++ ) { memory_map_t *entry = &g_copy_e820_map[i]; uint64_t base = e820_base_64(entry); uint64_t limit = base + e820_length_64(entry); @@ -693,7 +720,7 @@ if ( ram_base == NULL || ram_size == NULL ) return false; - for ( unsigned int i = 0; i < g_nr_map; i++ ) { + for ( unsigned int i = 0; i < *g_nr_map; i++ ) { memory_map_t *entry = &g_copy_e820_map[i]; if ( entry->type == E820_RAM ) { @@ -719,6 +746,10 @@ } } +void set_nr_map_ptr(uint32_t *const addr) +{ + g_nr_map = addr; +} /* * Local variables: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/loader.c new/tboot-1.11.12/tboot/common/loader.c --- old/tboot-1.11.10/tboot/common/loader.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/loader.c 2026-03-18 15:37:09.000000000 +0100 @@ -1273,7 +1273,7 @@ /* memory map--we can just use the modified copy for this one */ if (have_loader_memmap(g_ldr_ctx)){ mbi->mmap_addr = (uint32_t)get_e820_copy(); - mbi->mmap_length = (get_nr_map()) * sizeof(memory_map_t); + mbi->mmap_length = (*get_nr_map_ptr()) * sizeof(memory_map_t); mbi->flags |= MBI_MEMMAP; } @@ -1915,7 +1915,7 @@ /* multiboot 1 */ multiboot_info_t *mbi = (multiboot_info_t *) lctx->addr; mbi->mmap_addr = (uint32_t)get_e820_copy(); - mbi->mmap_length = (get_nr_map()) * sizeof(memory_map_t); + mbi->mmap_length = (*get_nr_map_ptr()) * sizeof(memory_map_t); mbi->flags |= MBI_MEMMAP; /* in case only MBI_MEMLIMITS was set */ return; } else { @@ -1925,7 +1925,7 @@ uint32_t old_memmap_size = get_loader_memmap_length(lctx); uint32_t old_memmap_entry_count = old_memmap_size / sizeof(memory_map_t); - if (old_memmap_entry_count < (get_nr_map())){ + if (old_memmap_entry_count < (*get_nr_map_ptr())){ /* we have to grow */ struct mb2_tag *map = (struct mb2_tag *)(lctx->addr + 8); map = find_mb2_tag_type(map, MB2_TAG_TYPE_MMAP); @@ -1936,7 +1936,7 @@ if (false == grow_mb2_tag(lctx, map, sizeof(memory_map_t) * - ((get_nr_map()) - old_memmap_entry_count))){ + ((*get_nr_map_ptr()) - old_memmap_entry_count))){ printk(TBOOT_ERR"MB2 failed to grow e820 map tag\n"); return; } @@ -1952,7 +1952,7 @@ printk(TBOOT_ERR"old memory map not found\n"); return; } - for (i = 0; i < (get_nr_map()); i++){ + for (i = 0; i < (*get_nr_map_ptr()); i++){ *old = *new; old++, new++; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/memlog.c new/tboot-1.11.12/tboot/common/memlog.c --- old/tboot-1.11.10/tboot/common/memlog.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/memlog.c 2026-03-18 15:37:09.000000000 +0100 @@ -43,59 +43,120 @@ #include <memlog.h> -/* memory-based serial log (ensure in .data section so that not cleared) */ -__data tboot_log_t *g_log = NULL; + +/* Memory-mapped tboot log header at the fixed log region base address. */ +#define TBOOT_LOG_HDR ((tboot_log_t *)TBOOT_SERIAL_LOG_ADDR) + +/* UUID for the tboot log */ +static const uuid_t tboot_log_uuid = TBOOT_LOG_UUID; + +/** + * @brief Check if the tboot log UUID is valid. + * + * @return 0 if the UUID is valid; otherwise -1. + */ +static int check_tboot_log_uuid(void) +{ + if ( tb_memcmp(&TBOOT_LOG_HDR->uuid, &tboot_log_uuid, sizeof(uuid_t)) != 0 ) + { + return -1; + } + return 0; +} + +/** + * @brief Get the base physical address of the tboot memory log region. + * + * Validates that the UUID stored in the log header matches the expected + * tboot log UUID. This way we can verify that the TBOOT log was initialized + * properly. + * + * @return uint32_t TBOOT_SERIAL_LOG_ADDR if the header is valid; otherwise 0. + */ +uint32_t memlog_get_base(void) +{ + if ( check_tboot_log_uuid() != 0 ) { + return 0; + } + + return TBOOT_SERIAL_LOG_ADDR; +} void memlog_init(void) { - if ( g_log == NULL ) { - g_log = (tboot_log_t *)TBOOT_SERIAL_LOG_ADDR; - uuid_t uuid = (uuid_t)TBOOT_LOG_UUID; - tb_memcpy((void *) &g_log->uuid, (const void *) &uuid, sizeof(uuid_t)); - g_log->curr_pos = 0; - g_log->zip_count = 0; - for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_pos[i] = 0; - for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_size[i] = 0; - } + if ( check_tboot_log_uuid() != 0 ) + { + uuid_t uuid = (uuid_t)TBOOT_LOG_UUID; + tb_memcpy((void *) &TBOOT_LOG_HDR->uuid, (const void *) &uuid, sizeof(uuid_t)); + TBOOT_LOG_HDR->curr_pos = 0; + TBOOT_LOG_HDR->zip_count = 0; + for (uint8_t i = 0; i < ZIP_COUNT_MAX; i++) { + TBOOT_LOG_HDR->zip_pos[i] = 0; + TBOOT_LOG_HDR->zip_size[i] = 0; + } + } /* initialize these post-launch as well, since bad/malicious values */ /* could compromise environment */ - g_log = (tboot_log_t *)TBOOT_SERIAL_LOG_ADDR; - g_log->max_size = TBOOT_SERIAL_LOG_SIZE - sizeof(*g_log); + TBOOT_LOG_HDR->max_size = TBOOT_SERIAL_LOG_SIZE - sizeof(tboot_log_t); + + if ( TBOOT_LOG_HDR->zip_count >= ZIP_COUNT_MAX ) + { + /* Corrupted zip_count; reset the log to a safe state. */ + TBOOT_LOG_HDR->curr_pos = 0; + /* Mark TBOOT LOG UUID as corrupted so it will be reinitialized. */ + tb_memset((void *)&TBOOT_LOG_HDR->uuid, 0, sizeof(uuid_t)); + for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) + { + TBOOT_LOG_HDR->zip_pos[i] = 0; + TBOOT_LOG_HDR->zip_size[i] = 0; + } + /* Ensure zip_count is within bounds for any subsequent use. */ + TBOOT_LOG_HDR->zip_count = 0; + } /* if we're calling this post-launch, verify that curr_pos is valid */ - if ( g_log->zip_pos[g_log->zip_count] > g_log->max_size && g_log != NULL ){ - g_log->curr_pos = 0; - uint8_t zero = 0; - tb_memcpy((void *) &g_log->uuid, (const void *) &zero, sizeof(uint8_t)); - for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_pos[i] = 0; - for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_size[i] = 0; + if (TBOOT_LOG_HDR->zip_pos[TBOOT_LOG_HDR->zip_count] > + TBOOT_LOG_HDR->max_size) { + TBOOT_LOG_HDR->curr_pos = 0; + + /* Match TBOOT LOG UUID as corrupted, when TBOOT LOG exceeds */ + /* its maximum size */ + tb_memset(((void *) &TBOOT_LOG_HDR->uuid), 0, sizeof(uuid_t)); + for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) { + TBOOT_LOG_HDR->zip_pos[i] = 0; + TBOOT_LOG_HDR->zip_size[i] = 0; + } + } + + if (TBOOT_LOG_HDR->curr_pos > TBOOT_LOG_HDR->max_size) { + TBOOT_LOG_HDR->curr_pos = TBOOT_LOG_HDR->zip_pos[TBOOT_LOG_HDR->zip_count]; } - if ( g_log->curr_pos > g_log->max_size ) - g_log->curr_pos = g_log->zip_pos[g_log->zip_count]; } void memlog_write(const char *str, unsigned int count) { - if ( g_log == NULL || count > g_log->max_size ) { + if (check_tboot_log_uuid() != 0 || count > TBOOT_LOG_HDR->max_size || + count == 0) { return; } /* Check if there is space for the new string and a null terminator */ - if (g_log->curr_pos + count + 1> g_log->max_size) { + if (TBOOT_LOG_HDR->curr_pos + count + 1> TBOOT_LOG_HDR->max_size) { memlog_compress(count); } - tb_memcpy(&g_log->buf[g_log->curr_pos], str, count); - g_log->curr_pos += count; + tb_memcpy(&TBOOT_LOG_HDR->buf[TBOOT_LOG_HDR->curr_pos], str, count); + TBOOT_LOG_HDR->curr_pos += count; /* if the string wasn't NULL-terminated, then NULL-terminate the log */ - if ( str[count-1] != '\0' ) - g_log->buf[g_log->curr_pos] = '\0'; + if (str[count-1] != '\0') { + TBOOT_LOG_HDR->buf[TBOOT_LOG_HDR->curr_pos] = '\0'; + } else { /* so that curr_pos will point to the NULL and be overwritten */ /* on next copy */ - g_log->curr_pos--; + TBOOT_LOG_HDR->curr_pos--; } } @@ -108,7 +169,8 @@ uint32_t zip_pos; bool log_reset_flag; - if (required_space == 0 && g_log->curr_pos < g_log->max_size / 2) { + if (required_space == 0 && TBOOT_LOG_HDR->curr_pos < + TBOOT_LOG_HDR->max_size / 2) { /* Flush was requested, but we have over half buffer free, skip it */ return; } @@ -117,49 +179,58 @@ log_reset_flag = false; /* Check if there is space to add another compressed chunk */ - if(g_log->zip_count >= ZIP_COUNT_MAX) + if (TBOOT_LOG_HDR->zip_count >= ZIP_COUNT_MAX) { log_reset_flag = true; - else{ + } + else { /* Get the start position of the new compressed chunk */ - zip_pos = g_log->zip_pos[g_log->zip_count]; + zip_pos = TBOOT_LOG_HDR->zip_pos[TBOOT_LOG_HDR->zip_count]; /* Compress the last part of the log buffer that is not compressed, and put the compressed output in out (buf) */ - zip_size = LZ_Compress(&g_log->buf[zip_pos], out, (g_log->curr_pos - zip_pos), sizeof(buf) ); + zip_size = LZ_Compress(&TBOOT_LOG_HDR->buf[zip_pos], out, + (TBOOT_LOG_HDR->curr_pos - zip_pos), sizeof(buf)); /* Check if buf was large enough for LZ_compress to succeed */ - if( zip_size < 0 ) + if (zip_size < 0) { log_reset_flag = true; - else{ + } + else { /* Check if there is space to add the compressed string, the new string and a null terminator to the log */ - if( (zip_pos + zip_size + required_space + 1) > g_log->max_size ) + if ((zip_pos + zip_size + required_space + 1) > + TBOOT_LOG_HDR->max_size) { log_reset_flag = true; + } else{ /* Add the new compressed chunk to the log buffer, over-writing the last part of the log that was just compressed */ - tb_memcpy(&g_log->buf[zip_pos], out, zip_size); - g_log->zip_size[g_log->zip_count] = zip_size; - g_log->zip_count++; - g_log->curr_pos = zip_pos + zip_size; + tb_memcpy(&TBOOT_LOG_HDR->buf[zip_pos], out, zip_size); + TBOOT_LOG_HDR->zip_size[TBOOT_LOG_HDR->zip_count] = zip_size; + TBOOT_LOG_HDR->zip_count++; + TBOOT_LOG_HDR->curr_pos = zip_pos + zip_size; /* Set a NULL ending */ - g_log->buf[g_log->curr_pos] ='\0'; + TBOOT_LOG_HDR->buf[TBOOT_LOG_HDR->curr_pos] ='\0'; /* Only if there is space to add another compressed chunk, prepare its start position. */ - if( g_log->zip_count < ZIP_COUNT_MAX ) - g_log->zip_pos[g_log->zip_count] = g_log->curr_pos; + if( TBOOT_LOG_HDR->zip_count < ZIP_COUNT_MAX ) { + TBOOT_LOG_HDR->zip_pos[TBOOT_LOG_HDR->zip_count] = TBOOT_LOG_HDR->curr_pos; + } } } } /* There was some space-shortage problem. Reset the log. */ - if ( log_reset_flag ){ - g_log->curr_pos = 0; - for( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_pos[i] = 0; - for( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_size[i] = 0; - g_log->zip_count = 0; + if (log_reset_flag) { + TBOOT_LOG_HDR->curr_pos = 0; + for (uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) { + TBOOT_LOG_HDR->zip_pos[i] = 0; + TBOOT_LOG_HDR->zip_size[i] = 0; + } + + TBOOT_LOG_HDR->zip_count = 0; } } \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/policy.c new/tboot-1.11.12/tboot/common/policy.c --- old/tboot-1.11.10/tboot/common/policy.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/policy.c 2026-03-18 15:37:09.000000000 +0100 @@ -99,12 +99,13 @@ { TB_POLTYPE_CONT_NON_FATAL, TB_POLACT_CONTINUE, { {TB_ERR_FATAL, TB_POLACT_HALT}, - {TB_ERR_PREV_TXT_ERROR, TB_POLACT_UNMEASURED_LAUNCH}, + {TB_ERR_DMA_CORRUPTION_DETECTED, TB_POLACT_HALT}, + {TB_ERR_PREV_TXT_ERROR, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_TPM_NOT_READY, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_SMX_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_VMX_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_VTD_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH}, - {TB_ERR_TXT_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH}, + {TB_ERR_TXT_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_SINIT_NOT_PRESENT, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_ACMOD_VERIFY_FAILED, TB_POLACT_UNMEASURED_LAUNCH}, {TB_ERR_NONE, TB_POLACT_CONTINUE}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/shutdown.S new/tboot-1.11.12/tboot/common/shutdown.S --- old/tboot-1.11.10/tboot/common/shutdown.S 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/shutdown.S 2026-03-18 15:37:09.000000000 +0100 @@ -116,9 +116,21 @@ */ ENTRY(shutdown_entry) .code64 + endbr64 cli wbinvd + /* Disable CET*/ + movl $0, %eax + movl $0, %edx + movl $MSR_IA32_U_CET, %ecx + wrmsr + + movl $0, %eax + movl $0, %edx + movl $MSR_IA32_S_CET, %ecx + wrmsr + movl $MSR_EFER,%ecx rdmsr bt $_EFER_LME,%eax diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/common/tboot.c new/tboot-1.11.12/tboot/common/tboot.c --- old/tboot-1.11.10/tboot/common/tboot.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/common/tboot.c 2026-03-18 15:37:09.000000000 +0100 @@ -35,6 +35,7 @@ */ #include <config.h> +#include <memlog.h> #include <types.h> #include <stdbool.h> #include <stdarg.h> @@ -154,6 +155,31 @@ s3_wakeup_end - s3_wakeup_16); } +static bool secure_nr_map_ptr(void) +{ + txt_heap_t *heap = NULL; + os_mle_data_t *os_mle_data = NULL; + + heap = get_txt_heap(); + if (heap == NULL) { + printk(TBOOT_ERR"Error: TXT heap is not defined.\n"); + printk(TBOOT_ERR"Failed to secure g_nr_map pointer.\n"); + return false; + } + + os_mle_data = get_os_mle_data_start(heap); + if (os_mle_data == NULL) { + printk(TBOOT_ERR"Error: Failed to get os_mle_data pointer.\n"); + printk(TBOOT_ERR"Failed to secure g_nr_map pointer.\n"); + return false; + } + + /* Set g_nr_map to point at the num_of_e820_entries member of the */ + /* OsMleData struct */ + set_nr_map_ptr(&os_mle_data->num_of_e820_entries); + return true; +} + static inline void print_tboot_shared(const tboot_shared_t *tboot_shared) { printk(TBOOT_DETA"tboot_shared data:\n"); @@ -175,7 +201,6 @@ tb_error_t err; struct tpm_if *tpm = get_tpm(); const struct tpm_if_fp *tpm_fp = get_tpm_fp(); - extern tboot_log_t *g_log; extern void shutdown_entry(void); printk(TBOOT_INFO"measured launch succeeded\n"); @@ -266,7 +291,7 @@ tb_memset(&_tboot_shared, 0, PAGE_SIZE); _tboot_shared.uuid = (uuid_t)TBOOT_SHARED_UUID; _tboot_shared.version = 6; - _tboot_shared.log_addr = (uint32_t)g_log; + _tboot_shared.log_addr = memlog_get_base(); _tboot_shared.shutdown_entry = (uint32_t)shutdown_entry; _tboot_shared.tboot_base = (uint32_t)&_start; _tboot_shared.tboot_size = (uint32_t)&_end - (uint32_t)&_start; @@ -352,8 +377,9 @@ void begin_launch(void *addr, uint32_t magic) { tb_error_t err; + bool is_nr_map_secured = false; - if (g_ldr_ctx->type == 0) + if (g_ldr_ctx->type == 0) determine_loader_type(addr, magic); /* on pre-SENTER boot, copy command line to buffer in tboot image @@ -400,7 +426,7 @@ if (is_launched()) printk(TBOOT_INFO"SINIT ACM successfully returned...\n"); if ( s3_flag ) printk(TBOOT_INFO"Resume from S3...\n"); - + /* RLM scaffolding if (g_ldr_ctx->type == 2) print_loader_ctx(g_ldr_ctx); @@ -430,9 +456,24 @@ } printk(TBOOT_INFO"BSP is cpu %u\n", get_apicid()); + /* secure g_nr_map pointer from DMA unauthorized access */ + if (supports_txt() == TB_ERR_NONE) { + is_nr_map_secured = secure_nr_map_ptr(); + if (!is_nr_map_secured) { + printk(TBOOT_ERR"Error: Failed to secure g_nr_map pointer.\n"); + printk(TBOOT_ERR"E820 map may be corrupted by DMA attack.\n"); + apply_policy(TB_ERR_FATAL); + } + else { + printk(TBOOT_INFO"Global ptr for the num of e820 entries has been" + " secured by TBOOT.\n"); + } + } + + /* make copy of e820 map that we will use and adjust */ if ( !s3_flag ) { - if ( !copy_e820_map(g_ldr_ctx) ) apply_policy(TB_ERR_FATAL); + if ( !copy_e820_map(g_ldr_ctx, get_nr_map_ptr())) apply_policy(TB_ERR_FATAL); if (efi_memmap_copy(g_ldr_ctx)) { printk(TBOOT_INFO"Original EFI memory map:\n"); efi_memmap_dump(); @@ -454,10 +495,17 @@ if (!verify_acmod(g_sinit)) apply_policy(TB_ERR_ACMOD_VERIFY_FAILED); } - + //We need to have g_sinit point to SINIT ACM before we can run is_tpr_supported //This global variable decides whether PMR or TPR is used - g_tpr_support = is_tpr_supported(); + if (get_tboot_force_pmrs()) { + // Disable TPR support, if "force_pmrs" cmdline option was set + g_tpr_support = false; + force_pmrs_usage(); + } + else { + g_tpr_support = is_tpr_supported(); + } /* make TPM ready for measured launch */ if (!tpm_detect()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/cmdline.h new/tboot-1.11.12/tboot/include/cmdline.h --- old/tboot-1.11.10/tboot/include/cmdline.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/cmdline.h 2026-03-18 15:37:09.000000000 +0100 @@ -55,6 +55,7 @@ extern bool get_tboot_ignore_prev_err(void); extern bool get_tboot_measure_nv(void); extern void get_tboot_extpol(void); +extern bool get_tboot_force_pmrs(void); extern bool get_tboot_force_tpm2_legacy_log(void); extern bool get_tboot_save_vtd(void); extern bool get_tboot_dump_memmap(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/e820.h new/tboot-1.11.12/tboot/include/e820.h --- old/tboot-1.11.10/tboot/include/e820.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/e820.h 2026-03-18 15:37:09.000000000 +0100 @@ -81,11 +81,15 @@ uint64_t attribute; } efi_memory_desc_t; +extern uint32_t *get_nr_map_ptr(void); +extern void set_nr_map_ptr(uint32_t *const); +extern bool verify_g_nr_map_ptr(uint32_t *const nr_map); + extern memory_map_t *get_e820_copy(void); -extern unsigned int get_nr_map(void); -extern bool copy_e820_map(loader_ctx *lctx); +extern bool copy_e820_map(loader_ctx *lctx, uint32_t *const); extern bool e820_protect_region(uint64_t addr, uint64_t size, uint32_t type); extern bool e820_reserve_ram(uint64_t base, uint64_t length); +extern bool e820_verify_num_of_entries(void); extern void print_e820_map(void); extern uint32_t e820_check_region(uint64_t base, uint64_t length); extern bool get_ram_ranges(uint64_t *min_lo_ram, uint64_t *max_lo_ram, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/memlog.h new/tboot-1.11.12/tboot/include/memlog.h --- old/tboot-1.11.10/tboot/include/memlog.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/memlog.h 2026-03-18 15:37:09.000000000 +0100 @@ -38,6 +38,7 @@ #include <types.h> +uint32_t memlog_get_base(void); void memlog_init(void); void memlog_write(const char *str, unsigned int count); void memlog_compress(uint32_t required_space); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/msr.h new/tboot-1.11.12/tboot/include/msr.h --- old/tboot-1.11.10/tboot/include/msr.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/msr.h 2026-03-18 15:37:09.000000000 +0100 @@ -95,6 +95,10 @@ /* AMD64 MSR's */ #define MSR_EFER 0xc0000080 /* extended features */ +/* CET MSRs*/ +#define MSR_IA32_U_CET 0x000006a0 /* user mode cet */ +#define MSR_IA32_S_CET 0x000006a2 /* kernel mode cet */ + /* EFER bits */ #define _EFER_LME 8 /* Long mode enable */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/processor.h new/tboot-1.11.12/tboot/include/processor.h --- old/tboot-1.11.10/tboot/include/processor.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/processor.h 2026-03-18 15:37:09.000000000 +0100 @@ -94,6 +94,14 @@ #define CR4_SMXE 0x00004000/* enable SMX */ #define CR4_PCIDE 0x00020000/* enable PCID */ +#define CPUID_X86_FEATURE_XMM3 (1<<0) +#define CPUID_X86_FEATURE_VMX (1<<5) +#define CPUID_X86_FEATURE_SMX (1<<6) +#define CPUID_X86_FEATURE_SGX (1<<18) + +/* Bits in EBX for CPUID leaf 7, sub-leaf 0 */ +#define CPUID_EBX_X86_SGX_SUPPORTED (1<<2) + #ifndef __ASSEMBLY__ static inline void sse_enable(void) @@ -174,9 +182,6 @@ return regs[3]; } -#define CPUID_X86_FEATURE_XMM3 (1<<0) -#define CPUID_X86_FEATURE_VMX (1<<5) -#define CPUID_X86_FEATURE_SMX (1<<6) static inline unsigned long read_cr0(void) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/txt/acmod.h new/tboot-1.11.12/tboot/include/txt/acmod.h --- old/tboot-1.11.10/tboot/include/txt/acmod.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/txt/acmod.h 2026-03-18 15:37:09.000000000 +0100 @@ -202,6 +202,8 @@ extern txt_caps_t get_sinit_capabilities(const acm_hdr_t* hdr); extern tpm_info_list_t *get_tpm_info_list(const acm_hdr_t* hdr); extern void verify_IA32_se_svn_status(const acm_hdr_t *acm_hdr); +extern acm_info_table_t *get_acmod_info_table(const acm_hdr_t* hdr); + #endif /* __TXT_ACMOD_H__ */ /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/txt/heap.h new/tboot-1.11.12/tboot/include/txt/heap.h --- old/tboot-1.11.10/tboot/include/txt/heap.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/txt/heap.h 2026-03-18 15:37:09.000000000 +0100 @@ -296,6 +296,8 @@ uint32_t version; /* currently 3 */ mtrr_state_t saved_mtrr_state; /* saved prior to changes for SINIT */ void *lctx_addr; /* needs to be restored to ebx */ + uint32_t num_of_e820_entries; /* number of entries in the copy of */ + /* e820 map */ uint32_t saved_misc_enable_msr; /* saved prior to SENTER */ /* PO policy data */ uint8_t lcp_po_data[MAX_LCP_PO_DATA_SIZE]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/include/txt/txt.h new/tboot-1.11.12/tboot/include/txt/txt.h --- old/tboot-1.11.10/tboot/include/txt/txt.h 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/include/txt/txt.h 2026-03-18 15:37:09.000000000 +0100 @@ -60,6 +60,7 @@ extern void txt_shutdown(void); extern bool txt_is_powercycle_required(void); extern void ap_wait(unsigned int cpuid); +extern void force_pmrs_usage(void); extern int get_evtlog_type(void); extern bool is_tpr_supported(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/txt/acmod.c new/tboot-1.11.12/tboot/txt/acmod.c --- old/tboot-1.11.10/tboot/txt/acmod.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/txt/acmod.c 2026-03-18 15:37:09.000000000 +0100 @@ -56,7 +56,7 @@ #include <tpm.h> #endif /* IS_INCLUDED */ -static acm_info_table_t *get_acmod_info_table(const acm_hdr_t* hdr) +acm_info_table_t *get_acmod_info_table(const acm_hdr_t* hdr) { uint32_t user_area_off; @@ -1061,17 +1061,30 @@ #ifndef IS_INCLUDED /* defined in utils/acminfo.c */ void verify_IA32_se_svn_status(const acm_hdr_t *acm_hdr) { - struct tpm_if *tpm = get_tpm(); + uint32_t ebx = 0; + struct tpm_if *tpm = get_tpm(); const struct tpm_if_fp *tpm_fp = get_tpm_fp(); printk(TBOOT_INFO"SGX:verify_IA32_se_svn_status is called\n"); - - //check if SGX is enabled by cpuid with ax=7, cx=0 - if ((cpuid_ebx1(7,0) & 0x00000004) == 0){ - printk(TBOOT_ERR"SGX is not enabled, cpuid.ebx: 0x%x\n", cpuid_ebx1(7,0)); + + /* check if SGX is supported by cpuid with ax=7, cx=0 */ + ebx = cpuid_ebx1(7,0); + if ((ebx & CPUID_EBX_X86_SGX_SUPPORTED) == 0){ + printk(TBOOT_ERR"SGX is not supported, cpuid.ebx: 0x%x\n", ebx); return; } - printk(TBOOT_INFO"SGX is enabled, cpuid.ebx:0x%x\n", cpuid_ebx1(7,0)); + + printk(TBOOT_INFO"SGX is supported, cpuid.ebx:0x%x\n", ebx); + + /* check if SGX is enabled */ + if ((rdmsr(MSR_IA32_FEATURE_CONTROL) & CPUID_X86_FEATURE_SGX) != + CPUID_X86_FEATURE_SGX){ + printk(TBOOT_ERR"SGX is not enabled, IA32_FEATURE_CONTROL: 0x%Lx\n", + rdmsr(MSR_IA32_FEATURE_CONTROL)); + return; + } + + printk(TBOOT_INFO"SGX is enabled.\n"); printk(TBOOT_INFO"Comparing se_svn with ACM Header se_svn\n"); if (((rdmsr(MSR_IA32_SE_SVN_STATUS)>>16) & 0xff) != acm_hdr->se_svn) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/txt/heap.c new/tboot-1.11.12/tboot/txt/heap.c --- old/tboot-1.11.10/tboot/txt/heap.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/txt/heap.c 2026-03-18 15:37:09.000000000 +0100 @@ -667,6 +667,8 @@ printk(TBOOT_DETA"\t version: %u\n", os_mle_data->version); /* TBD: perhaps eventually print saved_mtrr_state field */ printk(TBOOT_DETA"\t loader context addr: %p\n", os_mle_data->lctx_addr); + printk(TBOOT_DETA"\t number of e820 map entries: %u\n", + os_mle_data->num_of_e820_entries); } static bool verify_os_mle_data(const txt_heap_t *txt_heap) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tboot-1.11.10/tboot/txt/txt.c new/tboot-1.11.12/tboot/txt/txt.c --- old/tboot-1.11.10/tboot/txt/txt.c 2025-04-17 14:33:11.000000000 +0200 +++ new/tboot-1.11.12/tboot/txt/txt.c 2026-03-18 15:37:09.000000000 +0100 @@ -97,7 +97,7 @@ * this is the structure whose addr we'll put in TXT heap * it needs to be within the MLE pages, so force it to the .text section */ -static __text const mle_hdr_t g_mle_hdr = { +static __text mle_hdr_t g_mle_hdr = { uuid : MLE_HDR_UUID, length : sizeof(mle_hdr_t), version : MLE_HDR_VER, @@ -111,12 +111,15 @@ TBOOT_BASE_ADDR, }; +static bool g_force_pmrs = false; + /* * counts of APs going into wait-for-sipi */ /* count of APs in WAIT-FOR-SIPI */ atomic_t ap_wfs_count; + static void print_file_info(void) { printk(TBOOT_DETA"file addresses:\n"); @@ -570,10 +573,14 @@ /* * sets up TXT heap */ -static txt_heap_t *init_txt_heap(void *ptab_base, acm_hdr_t *sinit, loader_ctx *lctx) +static txt_heap_t *init_txt_heap(void *ptab_base, acm_hdr_t *sinit, + loader_ctx *lctx) { - txt_heap_t *txt_heap; - uint64_t *size; + uint32_t tmp_num_of_e820_entries = 0; + + txt_heap_t *txt_heap = NULL; + uint64_t *size = NULL; + struct tpm_if *tpm = get_tpm(); txt_heap = get_txt_heap(); @@ -588,12 +595,28 @@ * OS/loader to MLE data */ os_mle_data_t *os_mle_data = get_os_mle_data_start(txt_heap); + + if (!verify_g_nr_map_ptr(get_nr_map_ptr())) { + apply_policy(TB_ERR_DMA_CORRUPTION_DETECTED); + } + + if (!e820_verify_num_of_entries()) { + apply_policy(TB_ERR_DMA_CORRUPTION_DETECTED); + } + size = (uint64_t *)((uint32_t)os_mle_data - sizeof(uint64_t)); *size = sizeof(*os_mle_data) + sizeof(uint64_t); + + /* Save num of e820 entries from OsMleData in temporary structure */ + tmp_num_of_e820_entries = os_mle_data->num_of_e820_entries; + tb_memset(os_mle_data, 0, sizeof(*os_mle_data)); + + /* Set OsMleData */ os_mle_data->version = 3; os_mle_data->lctx_addr = lctx->addr; os_mle_data->saved_misc_enable_msr = rdmsr(MSR_IA32_MISC_ENABLE); + os_mle_data->num_of_e820_entries = tmp_num_of_e820_entries; /* * OS/loader to SINIT data @@ -666,6 +689,14 @@ printk(TBOOT_ERR"SINIT capabilities are incompatible (0x%x)\n", sinit_caps._raw); return NULL; } + + if (g_tpr_support == false && g_force_pmrs == true) + { + os_sinit_data->capabilities.tpr_support = 0; + printk(TBOOT_INFO"TPR Support disabled in the ACM capabilities " + "(OsSinitData).\n"); + } + if ( get_evtlog_type() == EVTLOG_TPM2_TCG ) { printk(TBOOT_INFO"SINIT ACM supports TCG compliant TPM 2.0 event log format, tcg_event_log_format = %d \n", sinit_caps.tcg_event_log_format); @@ -839,11 +870,30 @@ return sinit_caps.tpr_support; } +void force_pmrs_usage(void) +{ + acm_info_table_t *info_table = get_acmod_info_table(g_sinit); + if (info_table == NULL) { + return; + } + + if (info_table->min_mle_hdr_ver >= 0x00020003) { + printk(TBOOT_WARN"SINIT ACM has no support for PMR DMA Protection by default.\n"); + printk(TBOOT_WARN"MinMleHeader version is downgraded to 2.2.\n"); + info_table->min_mle_hdr_ver = 0x00020002; + } + + g_force_pmrs = true; + g_mle_hdr.capabilities.tpr_support = 0; + printk(TBOOT_INFO"TPR support disabled in the MLE capabilities.\n"); + return; +} + tb_error_t txt_launch_environment(loader_ctx *lctx) { - void *mle_ptab_base; - os_mle_data_t *os_mle_data; - txt_heap_t *txt_heap; + void *mle_ptab_base = NULL; + os_mle_data_t *os_mle_data = NULL; + txt_heap_t *txt_heap = NULL; /* * find correct SINIT AC module in modules list @@ -873,8 +923,9 @@ /* initialize TXT heap */ txt_heap = init_txt_heap(mle_ptab_base, g_sinit, lctx); - if ( txt_heap == NULL ) + if ( txt_heap == NULL ) { return TB_ERR_TXT_NOT_SUPPORTED; + } /* save MTRRs before we alter them for SINIT launch */ os_mle_data = get_os_mle_data_start(txt_heap); @@ -1444,6 +1495,40 @@ return true; } +bool verify_g_nr_map_ptr(uint32_t *const nr_map) +{ + txt_heap_t *heap = NULL; + os_mle_data_t *os_mle_data = NULL; + + if (supports_txt() != TB_ERR_NONE) { + printk(TBOOT_WARN"TXT is not supported on this platform, skipping " + "g_nr_map pointer TXT protection check.\n"); + return true; + } + + /* Get TXT heap and OsMleData base addresses*/ + heap = get_txt_heap(); + if (heap == NULL) { + printk(TBOOT_ERR"Error: TXT heap is not initialized.\n"); + return false; + } + + os_mle_data = get_os_mle_data_start(heap); + if (os_mle_data == NULL) { + printk(TBOOT_ERR"Error: Failed to get os_mle_data pointer.\n"); + return false; + } + + if (nr_map != &os_mle_data->num_of_e820_entries) { + printk(TBOOT_ERR"Error: Registered g_nr_map corruption.\n"); + printk(TBOOT_ERR"g_nr_map should point at the num_of_e820_entries member\n"); + printk(TBOOT_ERR"in the OsMleData structure\n"); + printk(TBOOT_ERR"g_nr_map: 0x%p\n", get_nr_map_ptr()); + return false; + } + + return true; +} /* * Local variables: ++++++ tboot-bsc#1207833-copy-mbi.patch ++++++ --- /var/tmp/diff_new_pack.CSU7bw/_old 2026-06-25 10:59:08.865376002 +0200 +++ /var/tmp/diff_new_pack.CSU7bw/_new 2026-06-25 10:59:08.869376136 +0200 @@ -1,7 +1,7 @@ -Index: tboot-1.11.9/tboot/common/loader.c +Index: tboot-1.11.12/tboot/common/loader.c =================================================================== ---- tboot-1.11.9.orig/tboot/common/loader.c -+++ tboot-1.11.9/tboot/common/loader.c +--- tboot-1.11.12.orig/tboot/common/loader.c ++++ tboot-1.11.12/tboot/common/loader.c @@ -1100,15 +1100,21 @@ void move_modules(loader_ctx *lctx) if ( below_tboot(lowest) ) ++++++ tboot-grub2-fix-version-find-latest.diff ++++++ --- tboot-1.11.12.orig/tboot/20_linux_tboot 2026-06-24 12:39:41.510323209 +0200 +++ tboot-1.11.12/20_linux_tboot 2026-06-24 12:39:12.747557424 +0200 @@ -210,6 +210,20 @@ fi prepare_boot_cache= +# version_find_latest was dropped from the grub shell utility functions, we +# now have to use version_sort(). It expects newline-separated basenames. +version_find_latest() +{ + local list="$1" + # translate space separated list into newline separated list + list=`echo $list | tr ' ' '\n'` + # drop the /boot prefix + list=`echo $list | grep -o "[^/]\+$"` + list=`echo $list | version_sort` + latest=`echo $list | tail -n 1` + echo "/boot/${latest}" +} + while [ "x${tboot_list}" != "x" ] && [ "x$linux_list" != "x" ] ; do list="${linux_list}" current_tboot=`version_find_latest $tboot_list` --- tboot-1.11.12.orig/tboot/20_linux_xen_tboot 2026-06-24 12:39:41.510551291 +0200 +++ tboot-1.11.12/tboot/20_linux_xen_tboot 2026-06-24 12:39:12.747708992 +0200 @@ -254,6 +254,20 @@ fi prepare_boot_cache= +# version_find_latest was dropped from the grub shell utility functions, we +# now have to use version_sort(). It expects newline-separated basenames. +version_find_latest() +{ + local list="$1" + # translate space separated list into newline separated list + list=`echo $list | tr ' ' '\n'` + # drop the /boot prefix + list=`echo $list | grep -o "[^/]\+$"` + list=`echo $list | version_sort` + latest=`echo $list | tail -n 1` + echo "/boot/${latest}" +} + while [ "x${xen_list}" != "x" ] ; do current_xen=`version_find_latest $xen_list` xen_basename=`basename ${current_xen}` ++++++ tboot-grub2-fix-xen-submenu-name.patch ++++++ --- /var/tmp/diff_new_pack.CSU7bw/_old 2026-06-25 10:59:08.909377473 +0200 +++ /var/tmp/diff_new_pack.CSU7bw/_new 2026-06-25 10:59:08.917377741 +0200 @@ -4,13 +4,13 @@ References: bnc#865815 Patch-Mainline: no -Index: tboot-1.11.10/tboot/20_linux_xen_tboot +Index: tboot-1.11.12/tboot/20_linux_xen_tboot =================================================================== ---- tboot-1.11.10.orig/tboot/20_linux_xen_tboot -+++ tboot-1.11.10/tboot/20_linux_xen_tboot +--- tboot-1.11.12.orig/tboot/20_linux_xen_tboot ++++ tboot-1.11.12/tboot/20_linux_xen_tboot @@ -246,7 +246,7 @@ while [ "x${xen_list}" != "x" ] ; do rel_tboot_dirname=`make_system_path_relative_to_its_root $tboot_dirname` - tboot_version="1.11.10" + tboot_version="1.11.12" list="${linux_list}" - echo "submenu \"Xen ${xen_version}\" \"Tboot ${tboot_version}\"{" + echo "submenu \"Xen ${xen_version} with Tboot ${tboot_version}\"{"
