[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] libelf: fix stack memory leak when loading 32 bit symbol tables
commit fb08f7d009a64b96efa4462c9d19ed6881936859 Author: Roger Pau Monné <roger.pau@xxxxxxxxxx> AuthorDate: Tue Nov 22 13:48:30 2016 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Nov 22 13:48:30 2016 +0100 libelf: fix stack memory leak when loading 32 bit symbol tables The 32 bit Elf structs are smaller than the 64 bit ones, which means that when loading them there's some padding left uninitialized at the end of each struct (because the size indicated in e_ehsize and e_shentsize is smaller than the size of elf_ehdr and elf_shdr). Fix this by introducing a new helper that is used to set [caller_]xdest_{base/size} and that takes care of performing the appropriate memset of the region. This newly introduced helper is then used to set and unset xdest_{base/size} in elf_load_bsdsyms. Now that the full struct is zeroed, there's no need to specifically zero the undefined section. This is CVE-2016-9384 / XSA-164. Suggested-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Also remove the open coded (and redundant with the earlier elf_memset_unchecked()) use of caller_xdest_* from elf_init(). Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> --- xen/common/libelf/libelf-loader.c | 14 +++----------- xen/common/libelf/libelf-tools.c | 11 +++++++++-- xen/include/xen/libelf.h | 15 +++++++++------ 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c index 2626a40..d67e0a7 100644 --- a/xen/common/libelf/libelf-loader.c +++ b/xen/common/libelf/libelf-loader.c @@ -43,8 +43,6 @@ elf_errorstatus elf_init(struct elf_binary *elf, const char *image_input, size_t elf->ehdr = ELF_MAKE_HANDLE(elf_ehdr, (elf_ptrval)image_input); elf->class = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_CLASS]); elf->data = elf_uval_3264(elf, elf->ehdr, e32.e_ident[EI_DATA]); - elf->caller_xdest_base = NULL; - elf->caller_xdest_size = 0; /* Sanity check phdr. */ offset = elf_uval(elf, elf->ehdr, e_phoff) + @@ -284,9 +282,8 @@ do { \ #define SYMTAB_INDEX 1 #define STRTAB_INDEX 2 - /* Allow elf_memcpy_safe to write to symbol_header. */ - elf->caller_xdest_base = &header; - elf->caller_xdest_size = sizeof(header); + /* Allow elf_memcpy_safe to write to header. */ + elf_set_xdest(elf, &header, sizeof(header)); /* * Calculate the position of the various elements in GUEST MEMORY SPACE. @@ -319,11 +316,7 @@ do { \ elf_store_field_bitness(elf, header_handle, e_phentsize, 0); elf_store_field_bitness(elf, header_handle, e_phnum, 0); - /* Zero the undefined section. */ - section_handle = ELF_MAKE_HANDLE(elf_shdr, - ELF_REALPTR2PTRVAL(&header.elf_header.section[SHN_UNDEF])); shdr_size = elf_uval(elf, elf->ehdr, e_shentsize); - elf_memset_safe(elf, ELF_HANDLE_PTRVAL(section_handle), 0, shdr_size); /* * The symtab section header is going to reside in section[SYMTAB_INDEX], @@ -404,8 +397,7 @@ do { \ } /* Remove permissions from elf_memcpy_safe. */ - elf->caller_xdest_base = NULL; - elf->caller_xdest_size = 0; + elf_set_xdest(elf, NULL, 0); #undef SYMTAB_INDEX #undef STRTAB_INDEX diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c index 5a4757b..e73e729 100644 --- a/xen/common/libelf/libelf-tools.c +++ b/xen/common/libelf/libelf-tools.c @@ -59,8 +59,7 @@ bool elf_access_ok(struct elf_binary * elf, return 1; if ( elf_ptrval_in_range(ptrval, size, elf->dest_base, elf->dest_size) ) return 1; - if ( elf_ptrval_in_range(ptrval, size, - elf->caller_xdest_base, elf->caller_xdest_size) ) + if ( elf_ptrval_in_range(ptrval, size, elf->xdest_base, elf->xdest_size) ) return 1; elf_mark_broken(elf, "out of range access"); return 0; @@ -373,6 +372,14 @@ bool elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr return ((p_type == PT_LOAD) && (p_flags & (PF_R | PF_W | PF_X)) != 0); } +void elf_set_xdest(struct elf_binary *elf, void *addr, uint64_t size) +{ + elf->xdest_base = addr; + elf->xdest_size = size; + if ( addr != NULL ) + elf_memset_safe(elf, ELF_REALPTR2PTRVAL(addr), 0, size); +} + /* * Local variables: * mode: C diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h index 90bd8cb..1b763f3 100644 --- a/xen/include/xen/libelf.h +++ b/xen/include/xen/libelf.h @@ -202,13 +202,11 @@ struct elf_binary { uint64_t bsd_symtab_pend; /* - * caller's other acceptable destination - * - * Again, these are trusted and must be valid (or 0) so long - * as the struct elf_binary is in use. + * caller's other acceptable destination. + * Set by elf_set_xdest. Do not set these directly. */ - void *caller_xdest_base; - uint64_t caller_xdest_size; + void *xdest_base; + uint64_t xdest_size; #ifndef __XEN__ /* misc */ @@ -485,5 +483,10 @@ static inline void ELF_ADVANCE_DEST(struct elf_binary *elf, uint64_t amount) } } +/* Specify a (single) additional destination, to which the image may + * cause writes. As with dest_base and dest_size, the values provided + * are trusted and must be valid so long as the struct elf_binary + * is in use or until elf_set_xdest(,0,0) is called. */ +void elf_set_xdest(struct elf_binary *elf, void *addr, uint64_t size); #endif /* __XEN_LIBELF_H__ */ -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |