@@ -457,6 +457,24 @@ static int secure_payload(struct payload *payload, struct livepatch_elf *elf)
return rc;
}
+static int check_section(const struct livepatch_elf *elf,
+ const struct livepatch_elf_sec *sec,
+ const size_t sz, bool zero_ok)
+{
+ if ( !elf || !sec )
+ return -EINVAL;
+
+ if ( (!sec->sec->sh_size && !zero_ok) ||
+ (sec->sec->sh_size % sz) )
+ {
+ dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong size %"PRIuElfWord" of %s (must be multiple of %zu)\n",
+ elf->name, sec->sec->sh_size, sec->name, sz);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int check_special_sections(const struct livepatch_elf *elf)
{
unsigned int i;
@@ -506,12 +524,8 @@ static int prepare_payload(struct payload *payload,
sec = livepatch_elf_sec_by_name(elf, ELF_LIVEPATCH_FUNC);
ASSERT(sec);
- if ( sec->sec->sh_size % sizeof(*payload->funcs) )
- {
- dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong size of "ELF_LIVEPATCH_FUNC"!\n",
- elf->name);
+ if ( check_section(elf, sec, sizeof(*payload->funcs), true) )
return -EINVAL;
- }
payload->funcs = sec->load_addr;
payload->nfuncs = sec->sec->sh_size / sizeof(*payload->funcs);
@@ -553,7 +567,7 @@ static int prepare_payload(struct payload *payload,
sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.load");
if ( sec )
{
- if ( sec->sec->sh_size % sizeof(*payload->load_funcs) )
+ if ( check_section(elf, sec, sizeof(*payload->load_funcs), true) )
return -EINVAL;
payload->load_funcs = sec->load_addr;
@@ -563,7 +577,7 @@ static int prepare_payload(struct payload *payload,
sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.unload");
if ( sec )
{
- if ( sec->sec->sh_size % sizeof(*payload->unload_funcs) )
+ if ( check_section(elf, sec, sizeof(*payload->unload_funcs), true) )
return -EINVAL;
payload->unload_funcs = sec->load_addr;
@@ -634,12 +648,8 @@ static int prepare_payload(struct payload *payload,
if ( !sec )
continue;
- if ( sec->sec->sh_size % sizeof(*region->frame[i].bugs) )
- {
- dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong size of .bug_frames.%u!\n",
- elf->name, i);
+ if ( check_section(elf, sec, sizeof(*region->frame[i].bugs), true) )
return -EINVAL;
- }
region->frame[i].bugs = sec->load_addr;
region->frame[i].n_bugs = sec->sec->sh_size /
@@ -652,12 +662,8 @@ static int prepare_payload(struct payload *payload,
#ifdef CONFIG_HAS_ALTERNATIVE
struct alt_instr *a, *start, *end;
- if ( sec->sec->sh_size % sizeof(*a) )
- {
- dprintk(XENLOG_ERR, LIVEPATCH "%s: Size of .alt_instr is not multiple of %zu!\n",
- elf->name, sizeof(*a));
+ if ( check_section(elf, sec, sizeof(*a), true) )
return -EINVAL;
- }
start = sec->load_addr;
end = sec->load_addr + sec->sec->sh_size;
@@ -689,14 +695,8 @@ static int prepare_payload(struct payload *payload,
#ifdef CONFIG_HAS_EX_TABLE
struct exception_table_entry *s, *e;
- if ( !sec->sec->sh_size ||
- (sec->sec->sh_size % sizeof(*region->ex)) )
- {
- dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong size of .ex_table (exp:%lu vs %lu)!\n",
- elf->name, sizeof(*region->ex),
- sec->sec->sh_size);
+ if ( check_section(elf, sec, sizeof(*region->ex), false) )
return -EINVAL;
- }
s = sec->load_addr;
e = sec->load_addr + sec->sec->sh_size;
@@ -555,6 +555,7 @@ typedef struct {
#if defined(ELFSIZE) && (ELFSIZE == 32)
#define PRIxElfAddr "08x"
+#define PRIuElfWord "8u"
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
@@ -582,6 +583,7 @@ typedef struct {
#define AuxInfo Aux32Info
#elif defined(ELFSIZE) && (ELFSIZE == 64)
#define PRIxElfAddr PRIx64
+#define PRIuElfWord PRIu64
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Phdr Elf64_Phdr