So that when we apply the patch again the .bss is cleared. Otherwise we may find some variables containing old values.
The payloads may contain various .bss - especially if -fdata-sections is used which can create .bss.<name> sections. Signed-off-by: Konrad Rzeszutek Wilk <konrad.w...@oracle.com> --- Cc: Ross Lagerwall <ross.lagerw...@citrix.com> Cc: Jan Beulich <jbeul...@suse.com> v3: Initial submission v4: s/EINVAL/EOPNOTSUPP/ Do memset in a single place Support multiple BSS sections. --- xen/common/livepatch.c | 60 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index 5da28a3..b5aef57 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -70,6 +70,9 @@ struct payload { unsigned int nsyms; /* Nr of entries in .strtab and symbols. */ struct livepatch_build_id id; /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */ struct livepatch_build_id dep; /* ELFNOTE_DESC(.livepatch.depends). */ + void **bss; /* .bss's of the payload. */ + size_t *bss_size; /* and their sizes. */ + size_t n_bss; /* Size of the array. */ char name[XEN_LIVEPATCH_NAME_SIZE]; /* Name of it. */ }; @@ -255,12 +258,18 @@ static struct payload *find_payload(const char *name) static void free_payload_data(struct payload *payload) { /* Set to zero until "move_payload". */ - if ( !payload->pages ) - return; - - vfree((void *)payload->text_addr); + if ( payload->pages ) + { + vfree((void *)payload->text_addr); + payload->pages = 0; + } - payload->pages = 0; + if ( payload->n_bss ) + { + xfree(payload->bss); + xfree(payload->bss_size); + payload->n_bss = 0; + } } /* @@ -287,6 +296,7 @@ static int move_payload(struct payload *payload, struct livepatch_elf *elf) unsigned int i; size_t size = 0; unsigned int *offset; + unsigned int n_bss = 0; int rc = 0; offset = xmalloc_array(unsigned int, elf->hdr->e_shnum); @@ -309,7 +319,11 @@ static int move_payload(struct payload *payload, struct livepatch_elf *elf) calc_section(&elf->sec[i], &payload->text_size, &offset[i]); else if ( !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) && (elf->sec[i].sec->sh_flags & SHF_WRITE) ) + { calc_section(&elf->sec[i], &payload->rw_size, &offset[i]); + if ( elf->sec[i].sec->sh_type == SHT_NOBITS ) + n_bss++; + } else if ( !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) && !(elf->sec[i].sec->sh_flags & SHF_WRITE) ) calc_section(&elf->sec[i], &payload->ro_size, &offset[i]); @@ -334,12 +348,8 @@ static int move_payload(struct payload *payload, struct livepatch_elf *elf) size = PFN_UP(size); /* Nr of pages. */ text_buf = vmalloc_xen(size * PAGE_SIZE); if ( !text_buf ) - { - dprintk(XENLOG_ERR, LIVEPATCH "%s: Could not allocate memory for payload!\n", - elf->name); - rc = -ENOMEM; - goto out; - } + goto out_mem; + rw_buf = text_buf + PAGE_ALIGN(payload->text_size); ro_buf = rw_buf + PAGE_ALIGN(payload->rw_size); @@ -348,6 +358,14 @@ static int move_payload(struct payload *payload, struct livepatch_elf *elf) payload->rw_addr = rw_buf; payload->ro_addr = ro_buf; + payload->bss = xmalloc_array(void *, n_bss); + payload->bss_size = xmalloc_array(size_t, n_bss); + if ( !payload->bss || !payload->bss_size ) + goto out_mem; + + payload->n_bss = n_bss; + n_bss = 0; /* Reusing as counter. */ + for ( i = 1; i < elf->hdr->e_shnum; i++ ) { if ( elf->sec[i].sec->sh_flags & SHF_ALLOC ) @@ -374,14 +392,24 @@ static int move_payload(struct payload *payload, struct livepatch_elf *elf) elf->name, elf->sec[i].name, elf->sec[i].load_addr); } else - memset(elf->sec[i].load_addr, 0, elf->sec[i].sec->sh_size); + { + payload->bss[n_bss] = elf->sec[i].load_addr; + payload->bss_size[n_bss++] = elf->sec[i].sec->sh_size; + } } } + ASSERT(n_bss == payload->n_bss); out: xfree(offset); return rc; + + out_mem: + dprintk(XENLOG_ERR, LIVEPATCH "%s: Could not allocate memory for payload!\n", + elf->name); + rc = -ENOMEM; + goto out; } static int secure_payload(struct payload *payload, struct livepatch_elf *elf) @@ -997,6 +1025,10 @@ static int apply_payload(struct payload *data) printk(XENLOG_INFO LIVEPATCH "%s: Applying %u functions\n", data->name, data->nfuncs); + /* And clear the BSS for subsequent operation. */ + for ( i = 0; i < data->n_bss; i++ ) + memset(data->bss[i], 0, data->bss_size[i]); + arch_livepatch_quiesce(); for ( i = 0; i < data->nfuncs; i++ ) @@ -1513,9 +1545,9 @@ static void livepatch_printall(unsigned char key) list_for_each_entry ( data, &payload_list, list ) { - printk(" name=%s state=%s(%d) %p (.data=%p, .rodata=%p) using %u pages.\n", + printk(" name=%s state=%s(%d) %p (.data=%p, .rodata=%p) using %u pages (%zu .bss).\n", data->name, state2str(data->state), data->state, data->text_addr, - data->rw_addr, data->ro_addr, data->pages); + data->rw_addr, data->ro_addr, data->pages, data->n_bss); for ( i = 0; i < data->nfuncs; i++ ) { -- 2.4.11 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org https://lists.xen.org/xen-devel