Skip to content

Commit

Permalink
fast-reboot: verify firmware "romem" checksum
Browse files Browse the repository at this point in the history
This takes a checksum of skiboot memory after boot that should be
unchanged during OS operation, and verifies it before allowing a
fast reboot.

This is not read-only memory from skiboot's point of view, beause
it includes things like the opal branch table that gets populated
during boot.

This helps to improve the integrity of firmware against host and
runtime firmware memory scribble bugs.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
npiggin authored and stewartsmith committed Sep 20, 2018
1 parent 5118fc7 commit 2649d66
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
5 changes: 5 additions & 0 deletions core/fast-reboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ static bool fast_reboot_sanity_check(void)
return false;
}

if (!verify_romem()) {
disable_fast_reboot("Inconsistent firmware romem checksum");
return false;
}

return true;
}

Expand Down
47 changes: 47 additions & 0 deletions core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,51 @@ static void pci_nvram_init(void)
}
}

static uint32_t mem_csum(void *_p, void *_e)
{
size_t len = _e - _p;
uint32_t *p = _p;
uint32_t v1 = 0, v2 = 0;
uint32_t csum;
unsigned int i;

for (i = 0; i < len; i += 4) {
uint32_t v = *p++;
v1 += v;
v2 += v1;
}

csum = v1 ^ v2;

return csum;
}

static uint32_t romem_csum;

static void checksum_romem(void)
{
uint32_t csum;

romem_csum = 0;

csum = mem_csum(_start, _romem_end);
romem_csum ^= csum;
csum = mem_csum(__builtin_kernel_start, __builtin_kernel_end);
romem_csum ^= csum;
}

bool verify_romem(void)
{
uint32_t old = romem_csum;
checksum_romem();
if (old != romem_csum) {
romem_csum = old;
prlog(PR_NOTICE, "OPAL checksums did not match\n");
return false;
}
return true;
}

/* Called from head.S, thus no prototype. */
void main_cpu_entry(const void *fdt);

Expand Down Expand Up @@ -1177,6 +1222,8 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
/* On P9, switch to radix mode by default */
cpu_set_radix_mode();

checksum_romem();

load_and_boot_kernel(false);
}

Expand Down
3 changes: 3 additions & 0 deletions include/mem_region.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,7 @@ struct mem_region *find_mem_region(const char *name);

bool mem_range_is_reserved(uint64_t start, uint64_t size);

/* Read-only memory checksum */
bool verify_romem(void);

#endif /* __MEMORY_REGION */

0 comments on commit 2649d66

Please sign in to comment.