summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbat.h11
-rw-r--r--pe.c6
-rw-r--r--sbat.c175
3 files changed, 88 insertions, 104 deletions
diff --git a/include/sbat.h b/include/sbat.h
index ffde202d..7aec3b78 100644
--- a/include/sbat.h
+++ b/include/sbat.h
@@ -18,7 +18,7 @@ extern list_t sbat_var;
EFI_STATUS parse_sbat_var(list_t *entries);
void cleanup_sbat_var(list_t *entries);
-struct sbat_entry {
+struct sbat_section_entry {
const CHAR8 *component_name;
const CHAR8 *component_generation;
const CHAR8 *vendor_name;
@@ -26,11 +26,14 @@ struct sbat_entry {
const CHAR8 *vendor_version;
const CHAR8 *vendor_url;
};
+#define SBAT_SECTION_COLUMNS (sizeof (struct sbat_section_entry) / sizeof(CHAR8 *))
-EFI_STATUS parse_sbat(char *sbat_base, size_t sbat_size, size_t *sbats, struct sbat_entry ***sbat);
-void cleanup_sbat_entries(size_t n, struct sbat_entry **entries);
+EFI_STATUS
+parse_sbat_section(char *section_base, size_t section_size, size_t *n,
+ struct sbat_section_entry ***entriesp);
+void cleanup_sbat_section_entries(size_t n, struct sbat_section_entry **entries);
-EFI_STATUS verify_sbat(size_t n, struct sbat_entry **entries);
+EFI_STATUS verify_sbat(size_t n, struct sbat_section_entry **entries);
#endif /* !SBAT_H_ */
// vim:fenc=utf-8:tw=75:noet
diff --git a/pe.c b/pe.c
index e4e7133d..9da87530 100644
--- a/pe.c
+++ b/pe.c
@@ -829,7 +829,7 @@ handle_sbat(char *SBATBase, size_t SBATSize)
unsigned int i;
EFI_STATUS efi_status;
size_t n;
- struct sbat_entry **entries = NULL;
+ struct sbat_section_entry **entries = NULL;
char *sbat_data;
size_t sbat_size;
@@ -850,7 +850,7 @@ handle_sbat(char *SBATBase, size_t SBATSize)
CopyMem(sbat_data, SBATBase, SBATSize);
sbat_data[SBATSize] = '\0';
- efi_status = parse_sbat(sbat_data, sbat_size, &n, &entries);
+ efi_status = parse_sbat_section(sbat_data, sbat_size, &n, &entries);
if (EFI_ERROR(efi_status)) {
perror(L"Could not parse .sbat section data: %r\n", efi_status);
goto err;
@@ -869,7 +869,7 @@ handle_sbat(char *SBATBase, size_t SBATSize)
efi_status = verify_sbat(n, entries);
- cleanup_sbat_entries(n, entries);
+ cleanup_sbat_section_entries(n, entries);
err:
FreePool(sbat_data);
diff --git a/sbat.c b/sbat.c
index bf1d1167..9a61007d 100644
--- a/sbat.c
+++ b/sbat.c
@@ -25,51 +25,96 @@ get_sbat_field(CHAR8 *current, CHAR8 *end, const CHAR8 **field, char delim)
}
EFI_STATUS
-parse_sbat_entry(CHAR8 **current, CHAR8 *end, struct sbat_entry **sbat_entry)
+parse_sbat_section(char *section_base, size_t section_size,
+ size_t *n_entries,
+ struct sbat_section_entry ***entriesp)
{
- struct sbat_entry *entry = NULL;
+ struct sbat_section_entry *entry = NULL, **entries;
+ EFI_STATUS efi_status = EFI_SUCCESS;
+ list_t csv, *pos = NULL;
+ char * end = section_base + section_size - 1;
+ size_t allocsz = 0;
+ size_t n;
+ char *strtab;
- entry = AllocateZeroPool(sizeof(*entry));
- if (!entry)
- return EFI_OUT_OF_RESOURCES;
+ if (!section_base || !section_size || !n_entries || !entriesp)
+ return EFI_INVALID_PARAMETER;
- *current = get_sbat_field(*current, end, &entry->component_name, ',');
- if (!entry->component_name)
- goto error;
+ INIT_LIST_HEAD(&csv);
- *current = get_sbat_field(*current, end, &entry->component_generation,
- ',');
- if (!entry->component_generation)
- goto error;
+ efi_status =
+ parse_csv_data(section_base, end, SBAT_SECTION_COLUMNS, &csv);
+ if (EFI_ERROR(efi_status)) {
+ return efi_status;
+ }
- *current = get_sbat_field(*current, end, &entry->vendor_name, ',');
- if (!entry->vendor_name)
- goto error;
+ n = 0;
+ list_for_each(pos, &csv) {
+ struct csv_row * row;
+ size_t i;
- *current =
- get_sbat_field(*current, end, &entry->vendor_package_name, ',');
- if (!entry->vendor_package_name)
- goto error;
+ row = list_entry(pos, struct csv_row, list);
- *current = get_sbat_field(*current, end, &entry->vendor_version, ',');
- if (!entry->vendor_version)
- goto error;
+ if (row->n_columns < SBAT_SECTION_COLUMNS) {
+ efi_status = EFI_INVALID_PARAMETER;
+ goto err;
+ }
- *current = get_sbat_field(*current, end, &entry->vendor_url, '\n');
- if (!entry->vendor_url)
- goto error;
+ allocsz += sizeof(struct sbat_section_entry *);
+ allocsz += sizeof(struct sbat_section_entry);
+ for (i = 0; i < row->n_columns; i++) {
+ if (row->columns[i][0] == '\000') {
+ efi_status = EFI_INVALID_PARAMETER;
+ goto err;
+ }
+ allocsz += strlena(row->columns[i]) + 1;
+ }
+ n++;
+ }
- *sbat_entry = entry;
+ strtab = AllocateZeroPool(allocsz);
+ if (!strtab) {
+ efi_status = EFI_OUT_OF_RESOURCES;
+ goto err;
+ }
- return EFI_SUCCESS;
+ entries = (struct sbat_section_entry **)strtab;
+ strtab += sizeof(struct sbat_section_entry *) * n;
+ entry = (struct sbat_section_entry *)strtab;
+ strtab += sizeof(struct sbat_section_entry) * n;
+ n = 0;
+
+ list_for_each(pos, &csv) {
+ struct csv_row * row;
+ size_t i;
+ const char **ptrs[] = {
+ &entry->component_name,
+ &entry->component_generation,
+ &entry->vendor_name,
+ &entry->vendor_package_name,
+ &entry->vendor_version,
+ &entry->vendor_url,
+ };
-error:
- FreePool(entry);
- return EFI_INVALID_PARAMETER;
+
+ row = list_entry(pos, struct csv_row, list);
+ for (i = 0; i < row->n_columns; i++) {
+ *(ptrs[i]) = strtab;
+ strtab = stpcpy(strtab, row->columns[i]) + 1;
+ }
+ entries[n] = entry;
+ entry++;
+ n++;
+ }
+ *entriesp = entries;
+ *n_entries = n;
+err:
+ free_csv_list(&csv);
+ return efi_status;
}
void
-cleanup_sbat_entries(size_t n, struct sbat_entry **entries)
+cleanup_sbat_section_entries(size_t n, struct sbat_section_entry **entries)
{
size_t i;
@@ -86,71 +131,7 @@ cleanup_sbat_entries(size_t n, struct sbat_entry **entries)
}
EFI_STATUS
-parse_sbat(char *sbat_base, size_t sbat_size, size_t *sbats, struct sbat_entry ***sbat)
-{
- CHAR8 *current = (CHAR8 *)sbat_base;
- CHAR8 *end = (CHAR8 *)sbat_base + sbat_size;
- EFI_STATUS efi_status = EFI_SUCCESS;
- struct sbat_entry *entry = NULL;
- struct sbat_entry **entries;
- size_t i = 0;
- size_t pages = 1;
- size_t n = PAGE_SIZE / sizeof(*entry);
-
- if (!sbat_base || sbat_size == 0 || !sbats || !sbat)
- return EFI_INVALID_PARAMETER;
-
- if (current == end)
- return EFI_INVALID_PARAMETER;
-
- *sbats = 0;
- *sbat = 0;
-
- entries = AllocateZeroPool(pages * PAGE_SIZE);
- if (!entries)
- return EFI_OUT_OF_RESOURCES;
-
- do {
- entry = NULL;
- efi_status = parse_sbat_entry(&current, end, &entry);
- if (EFI_ERROR(efi_status))
- goto error;
-
- if (end < current) {
- efi_status = EFI_INVALID_PARAMETER;
- goto error;
- }
-
- if (i >= n) {
- struct sbat_entry **new_entries;
- unsigned int osize = PAGE_SIZE * pages;
- unsigned int nsize = osize + PAGE_SIZE;
-
- new_entries = ReallocatePool(entries, osize, nsize);
- if (!new_entries) {
- efi_status = EFI_OUT_OF_RESOURCES;
- goto error;
- }
- entries = new_entries;
- ZeroMem(&entries[i], PAGE_SIZE);
- pages += 1;
- n = nsize / sizeof(entry);
- }
- entries[i++] = entry;
- } while (entry && current && *current != '\0');
-
- *sbats = i;
- *sbat = entries;
-
- return efi_status;
-error:
- perror(L"Failed to parse SBAT data: %r\n", efi_status);
- cleanup_sbat_entries(i, entries);
- return efi_status;
-}
-
-EFI_STATUS
-verify_single_entry(struct sbat_entry *entry, struct sbat_var *sbat_var_entry)
+verify_single_entry(struct sbat_section_entry *entry, struct sbat_var *sbat_var_entry)
{
UINT16 sbat_gen, sbat_var_gen;
@@ -194,7 +175,7 @@ cleanup_sbat_var(list_t *entries)
}
EFI_STATUS
-verify_sbat(size_t n, struct sbat_entry **entries)
+verify_sbat(size_t n, struct sbat_section_entry **entries)
{
unsigned int i;
list_t *pos = NULL;