Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pcr-oracle for openSUSE:Factory checked in at 2025-02-27 14:49:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pcr-oracle (Old) and /work/SRC/openSUSE:Factory/.pcr-oracle.new.25152 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pcr-oracle" Thu Feb 27 14:49:49 2025 rev:17 rq:1248601 version:0.5.4 Changes: -------- --- /work/SRC/openSUSE:Factory/pcr-oracle/pcr-oracle.changes 2025-02-21 21:35:34.654264789 +0100 +++ /work/SRC/openSUSE:Factory/.pcr-oracle.new.25152/pcr-oracle.changes 2025-02-27 14:51:04.520830854 +0100 @@ -1,0 +2,6 @@ +Wed Feb 26 07:31:47 UTC 2025 - Gary Ching-Pang Lin <g...@suse.com> + +- Add fix-bsc1230316-predict-sbatlevelrt.patch to predict + SbatLevelRT for the next boot (bsc#1230316) + +------------------------------------------------------------------- New: ---- fix-bsc1230316-predict-sbatlevelrt.patch BETA DEBUG BEGIN: New: - Add fix-bsc1230316-predict-sbatlevelrt.patch to predict SbatLevelRT for the next boot (bsc#1230316) BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pcr-oracle.spec ++++++ --- /var/tmp/diff_new_pack.pzmtVZ/_old 2025-02-27 14:51:05.236860730 +0100 +++ /var/tmp/diff_new_pack.pzmtVZ/_new 2025-02-27 14:51:05.236860730 +0100 @@ -40,6 +40,8 @@ Patch5: fix-testcase-empty-efi-variables.patch # PATCH-FIX-UPSTREAM fix-event-reshash-for-cryptouuid.patch gh#okirch/pcr-oracle!60 Patch6: fix-event-reshash-for-cryptouuid.patch +# PATCH-FIX-UPSTREAM fix-bsc1230316-predict-sbatlevelrt.patch gh#okirch/pcr-oracle!61 +Patch7: fix-bsc1230316-predict-sbatlevelrt.patch BuildRequires: libopenssl-devel >= 0.9.8 BuildRequires: tpm2-0-tss-devel >= 2.4.0 Requires: libtss2-tcti-device0 ++++++ fix-bsc1230316-predict-sbatlevelrt.patch ++++++ >From 5f73c8d655465470498c91f238788d2ffa48de81 Mon Sep 17 00:00:00 2001 From: Gary Lin <g...@suse.com> Date: Tue, 25 Feb 2025 16:13:28 +0800 Subject: [PATCH 1/2] Locate .sbatlevel section in shim.efi The .sbatlevel section in shim.efi will be used to set SbatLevelRT and we need the section to predict SbatLevelRT. Per PE format SPEC(*), the section name is "An 8-byte, null-padded UTF-8 encoded string. If the string is exactly 8 8 characters long, there is no terminating null. For longer names, this field contains a slash (/) that is followed by an ASCII representation of a decimal number that is an offset into the string table." Before looking for the .sbatlevel section, we have to get the string table, To get the offset to the string table: string_table_offset = symbol_table_offset + (number_of_symbols * symbol_size) With the offset, we can go further to look for the longer section names and get the .sbatlevel section. (*) https://learn.microsoft.com/en-us/windows/win32/debug/pe-format Signed-off-by: Gary Lin <g...@suse.com> --- src/authenticode.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++ src/authenticode.h | 2 ++ 2 files changed, 77 insertions(+) Index: pcr-oracle-0.5.4/src/authenticode.c =================================================================== --- pcr-oracle-0.5.4.orig/src/authenticode.c +++ pcr-oracle-0.5.4/src/authenticode.c @@ -91,10 +91,14 @@ struct pecoff_image_info { uint16_t machine_id; uint16_t num_sections; uint32_t symtab_offset; + uint32_t num_symbols; uint16_t optional_hdr_size; uint32_t optional_hdr_offset; uint32_t section_table_offset; + + uint32_t strtab_offset; + uint32_t strtab_size; } pe_hdr; struct { @@ -111,6 +115,9 @@ struct pecoff_image_info { pecoff_section_t * section; authenticode_image_info_t auth_info; + + /* The contents of .sbatlevel */ + buffer_t * sbatlevel; }; #define MSDOS_STUB_PE_OFFSET 0x3c @@ -147,6 +154,7 @@ void pecoff_image_info_free(pecoff_image_info_t *img) { buffer_free(img->data); + buffer_free(img->sbatlevel); free(img->display_name); free(img->data_dirs); free(img->section); @@ -351,6 +359,8 @@ __pecoff_process_header(buffer_t *in, pe if (!__pecoff_get_u32(in, img, PECOFF_HEADER_SYMTAB_POS_OFFSET, &img->pe_hdr.symtab_offset)) return false; + if (!__pecoff_get_u32(in, img, PECOFF_HEADER_SYMTAB_CNT_OFFSET, &img->pe_hdr.num_symbols)) + return false; img->pe_hdr.optional_hdr_offset = img->pe_hdr.offset + PECOFF_HEADER_LENGTH; if (!__pecoff_get_u16(in, img, PECOFF_HEADER_OPTIONAL_HDR_SIZE_OFFSET, &img->pe_hdr.optional_hdr_size)) @@ -358,6 +368,19 @@ __pecoff_process_header(buffer_t *in, pe img->pe_hdr.section_table_offset = img->pe_hdr.optional_hdr_offset + img->pe_hdr.optional_hdr_size; + /* String table follows symbol table immediately. + * One symbol is 18 bytes, so the offset to string table is + * symtab_offset + num_symbols * 18 + * + * ref: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-string-table + * https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table + */ + if (img->pe_hdr.symtab_offset != 0) { + img->pe_hdr.strtab_offset = img->pe_hdr.symtab_offset + (img->pe_hdr.num_symbols * 18); + if (!__pecoff_get_u32(in, img, img->pe_hdr.strtab_offset, &img->pe_hdr.strtab_size)) + return false; + } + return true; } @@ -451,6 +474,27 @@ __pecoff_process_optional_header(buffer_ } static bool +__pecoff_name_to_offset(char *sec_name, uint32_t *offset) +{ + uint32_t result = 0; + int i; + + if (sec_name[0] != '/') + return false; + + for (i = 1; i < 8 && sec_name[i] != '\0'; i++) { + if (sec_name[i] < '0' || sec_name[i] > '9') + return false; + + result = result * 10 + sec_name[i] - '0'; + } + + *offset = result; + + return true; +} + +static bool __pecoff_process_sections(buffer_t *in, pecoff_image_info_t *info) { unsigned int tbl_offset = info->pe_hdr.section_table_offset; @@ -458,6 +502,9 @@ __pecoff_process_sections(buffer_t *in, buffer_t hdr; unsigned int i; pecoff_section_t *sec; + uint32_t str_offset; + char *long_name; + buffer_t *sec_buf; pe_debug(" Processing %u sections (table at offset %u)\n", num_sections, tbl_offset); @@ -483,6 +530,27 @@ __pecoff_process_sections(buffer_t *in, pe_debug(" Section %-8s raw %7u at 0x%08x-0x%08x\n", sec->name, sec->raw.size, sec->raw.addr, sec->raw.addr + sec->raw.size); + /* Process the section names longer than 8 bytes */ + long_name = NULL; + if (__pecoff_name_to_offset(sec->name, &str_offset) && + str_offset < info->pe_hdr.strtab_size) { + long_name = (char *)(in->data + info->pe_hdr.strtab_offset + str_offset); + pe_debug(" Long Name: %s\n", long_name); + } + + /* Get sbatlevel from .sbatlevel section */ + if (long_name != NULL && strcmp(long_name, ".sbatlevel") == 0) { + if (!(sec_buf = buffer_alloc_write(sec->raw.size))) + return false; + + if (!buffer_seek_read(in, sec->raw.addr)) + return false; + + if (!buffer_copy(in, sec->raw.size, sec_buf)) + return false; + + info->sbatlevel = sec_buf; + } } /* We are supposed to sort the sections in ascending order, but we're not doing it here, we @@ -506,6 +574,7 @@ __pecoff_show_header(pecoff_image_info_t pe_debug(" Architecture: %s\n", __pecoff_get_machine(img)); pe_debug(" Number of sections: %d\n", img->pe_hdr.num_sections); pe_debug(" Symbol table position: 0x%08x\n", img->pe_hdr.symtab_offset); + pe_debug(" String table position: 0x%08x\n", img->pe_hdr.strtab_offset); pe_debug(" Optional header size: %d\n", img->pe_hdr.optional_hdr_size); } @@ -751,3 +820,9 @@ authenticode_get_signer(const pecoff_ima cert_table_free(cert_tbl); return signer; } + +buffer_t * +pecoff_image_get_sbatlevel(pecoff_image_info_t *img) +{ + return img->sbatlevel; +} Index: pcr-oracle-0.5.4/src/authenticode.h =================================================================== --- pcr-oracle-0.5.4.orig/src/authenticode.h +++ pcr-oracle-0.5.4/src/authenticode.h @@ -29,5 +29,7 @@ extern tpm_evdigest_t * authenticode_get extern cert_table_t * authenticode_get_certificate_table(const pecoff_image_info_t *img); extern parsed_cert_t * authenticode_get_signer(const pecoff_image_info_t *); +extern buffer_t * pecoff_image_get_sbatlevel(pecoff_image_info_t *); + #endif /* AUTHENTICODE_H */ Index: pcr-oracle-0.5.4/src/efi-application.c =================================================================== --- pcr-oracle-0.5.4.orig/src/efi-application.c +++ pcr-oracle-0.5.4/src/efi-application.c @@ -315,6 +315,7 @@ __tpm_event_efi_bsa_rehash(const tpm_eve const struct efi_bsa_event *evspec = &parsed->efi_bsa_event; const char *new_application; struct efi_bsa_event evspec_clone; + buffer_t *sbatlevel; /* Some BSA events do not refer to files, but to some data blobs residing somewhere on a device. * We're not yet prepared to handle these, so we hope the user doesn't mess with them, and @@ -348,6 +349,14 @@ __tpm_event_efi_bsa_rehash(const tpm_eve } } + /* Set the sbatlevel section from shim.efi */ + if (ctx->sbatlevel == NULL + && (sbatlevel = pecoff_image_get_sbatlevel(evspec->img_info)) != NULL) { + if ((ctx->sbatlevel = buffer_alloc_write(sbatlevel->size)) == NULL + || !buffer_copy(sbatlevel, sbatlevel->size, ctx->sbatlevel)) + return NULL; + } + if (ctx->use_pesign) return __efi_application_rehash_pesign(ctx, evspec->efi_partition, evspec->efi_application); Index: pcr-oracle-0.5.4/src/efi-variable.c =================================================================== --- pcr-oracle-0.5.4.orig/src/efi-variable.c +++ pcr-oracle-0.5.4/src/efi-variable.c @@ -93,6 +93,159 @@ __tpm_event_efi_variable_build_event(con return bp; } +#define SBATLEVELRT_VARNAME "SbatLevelRT-605dab50-e046-4300-abb6-3dd810dd8b23" +#define SBATPOLICY_VARNAME "SbatPolicy-605dab50-e046-4300-abb6-3dd810dd8b23" +#define SECUREBOOT_VARNAME "SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c" + +#define POLICY_LATEST 1 +#define POLICY_AUTOMATIC 2 +#define POLICY_RESET 3 + +#define SBAT_ORIGINAL "sbat,1,2021030218\n" + +static bool +parse_sbatlevel_section(buffer_t *sec, char **sbat_automatic, char **sbat_latest) +{ + uint32_t fmt_ver; + uint32_t offset_auto; + uint32_t offset_latest; + + if (!buffer_get_u32le(sec, &fmt_ver) + || !buffer_get_u32le(sec, &offset_auto) + || !buffer_get_u32le(sec, &offset_latest)) + return false; + + if (offset_auto >= offset_latest) + return false; + + if (!buffer_seek_read(sec, offset_auto + 4)) + return false; + *sbat_automatic = (char *)buffer_read_pointer(sec); + + if (!buffer_seek_read(sec, offset_latest + 4)) + return false; + *sbat_latest = (char *)(buffer_read_pointer(sec)); + + return true; +} + +static bool +fetch_sbat_datestamp(const char *sbat, size_t size, uint32_t *datestamp) +{ + uint32_t date = 0; + size_t i; + + /* Expected string: "sbat,X,YYYYYYYYYY\n" */ + if (size < 17) + return false; + + if (strncmp(sbat, "sbat,", 5) != 0) + return false; + + for (i = 5; i < size && sbat[i] != ','; i++); + i++; + if (i >= size) + return false; + + for (; i < size && sbat[i] != '\n'; i++) { + if (sbat[i] < '0' || sbat[i] > '9') + return false; + date = date * 10 + sbat[i] - '0'; + } + + *datestamp = date; + return true; +} + +static buffer_t * +efi_sbatlevel_get_record(buffer_t *sbatlevel) +{ + char *sbat_automatic; + char *sbat_latest; + const char *sbat_candidate; + const char *sbat_current; + buffer_t *buffer = NULL; + buffer_t *sbatlvlrt = NULL; + buffer_t *result = NULL; + uint8_t secureboot; + uint8_t sbatpolicy; + uint32_t current_date; + uint32_t candidate_date; + bool sbat_reset = false; + + if (!parse_sbatlevel_section(sbatlevel, &sbat_automatic, &sbat_latest)) { + error("Unable to process SbatLevel\n"); + return NULL; + } + + buffer = runtime_read_efi_variable(SECUREBOOT_VARNAME); + if (buffer == NULL || !buffer_get_u8(buffer, &secureboot)) + secureboot = 0; + buffer_free(buffer); + + buffer = runtime_read_efi_variable(SBATPOLICY_VARNAME); + if (buffer == NULL || !buffer_get_u8(buffer, &sbatpolicy)) + sbatpolicy = POLICY_AUTOMATIC; + buffer_free(buffer); + + switch (sbatpolicy) { + case POLICY_LATEST: + sbat_candidate = sbat_latest; + break; + case POLICY_AUTOMATIC: + sbat_candidate = sbat_automatic; + break; + case POLICY_RESET: + if (secureboot == 1) { + infomsg("SBAT cannot be reset when Secure Boot is enabled.\n"); + sbat_candidate = sbat_automatic; + } else { + sbat_candidate = SBAT_ORIGINAL; + } + break; + default: + error("Invalid SBAT policy\n"); + return NULL; + } + + if ((sbatlvlrt = runtime_read_efi_variable(SBATLEVELRT_VARNAME)) == NULL) { + error("Unable to read SbatLevelRT\n"); + return NULL; + } + + sbat_current = (const char *)buffer_read_pointer(sbatlvlrt); + + if (!fetch_sbat_datestamp(sbat_current, sbatlvlrt->size, ¤t_date) + || !fetch_sbat_datestamp(sbat_candidate, strlen(sbat_candidate), &candidate_date)) { + error("Unable to get SBAT timestamp\n"); + goto fail; + } + + debug("Current SBAT datestampe: %u\n", current_date); + debug("Candidate SBAT datestampe: %u\n", candidate_date); + + if (current_date >= candidate_date && sbat_reset == false) { + debug("Use current SbatLevel\n"); + result = sbatlvlrt; + } else { + debug("Use candidate SbatLevel\n"); + buffer_free(sbatlvlrt); + + /* Copy the candidate SbatLevel string without the terminating null */ + if ((result = buffer_alloc_write(strlen(sbat_candidate))) == NULL + || !buffer_put(result, sbat_candidate, strlen(sbat_candidate))) + goto fail; + } + + return result; + +fail: + buffer_free(sbatlvlrt); + buffer_free(result); + + return NULL; +} + enum { HASH_STRATEGY_EVENT, HASH_STRATEGY_DATA, @@ -114,6 +267,11 @@ efi_variable_authority_get_record(const } else if (!strcmp(var_short_name, "MokListRT")) { db_name = "MokList"; + } else + if (!strcmp(var_short_name, "SbatLevel")) { + if (ctx->sbatlevel != NULL) + return efi_sbatlevel_get_record(ctx->sbatlevel); + return runtime_read_efi_variable(var_name); } else { /* Read as-is (this could be SbatLevel, or some other variable that's not * a signature db). */ Index: pcr-oracle-0.5.4/src/eventlog.c =================================================================== --- pcr-oracle-0.5.4.orig/src/eventlog.c +++ pcr-oracle-0.5.4/src/eventlog.c @@ -1148,6 +1148,7 @@ tpm_event_log_rehash_ctx_init(tpm_event_ void tpm_event_log_rehash_ctx_destroy(tpm_event_log_rehash_ctx_t *ctx) { + buffer_free(ctx->sbatlevel); } void Index: pcr-oracle-0.5.4/src/eventlog.h =================================================================== --- pcr-oracle-0.5.4.orig/src/eventlog.h +++ pcr-oracle-0.5.4/src/eventlog.h @@ -209,6 +209,8 @@ typedef struct tpm_event_log_rehash_ctx /* This get set when the user specifies --next-kernel */ char * boot_entry_path; uapi_boot_entry_t * boot_entry; + + buffer_t * sbatlevel; } tpm_event_log_rehash_ctx_t; #define GRUB_COMMAND_ARGV_MAX 32