From: Andrew Cooper Date: Tue, 13 Jun 2017 20:36:58 +0000 (+0100) Subject: xen/livepatch: Don't crash on encountering STN_UNDEF relocations X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~1927 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2ff229643b739e2fd0cd0536ee9fca506cfa92f8;p=xen.git xen/livepatch: Don't crash on encountering STN_UNDEF relocations A symndx of STN_UNDEF is special, and means a symbol value of 0. While legitimate in the ELF standard, its existance in a livepatch is questionable at best. Until a plausible usecase presents itself, reject such a relocation with -EOPNOTSUPP. Additionally, fix an off-by-one error while range checking symndx, and perform a safety check on elf->sym[symndx].sym before derefencing it, to avoid tripping over a NULL pointer when calculating val. Signed-off-by: Andrew Cooper Reviewed-by: Stefano Stabellini Reviewed-by: Konrad Rzeszutek Wilk Tested-by: Konrad Rzeszutek Wilk [x86 and arm32] Reviewed-by: Jan Beulich Reviewed-by: Ross Lagerwall --- diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c index a328179b43..41378a54ae 100644 --- a/xen/arch/arm/arm32/livepatch.c +++ b/xen/arch/arm/arm32/livepatch.c @@ -254,12 +254,24 @@ int arch_livepatch_perform(struct livepatch_elf *elf, addend = get_addend(type, dest); } - if ( symndx > elf->nsym ) + if ( symndx == STN_UNDEF ) + { + dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n", + elf->name); + return -EOPNOTSUPP; + } + else if ( symndx >= elf->nsym ) { dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative symbol wants symbol@%u which is past end!\n", elf->name, symndx); return -EINVAL; } + else if ( !elf->sym[symndx].sym ) + { + dprintk(XENLOG_ERR, LIVEPATCH "%s: No relative symbol@%u\n", + elf->name, symndx); + return -EINVAL; + } val = elf->sym[symndx].sym->st_value; /* S */ diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c index 63929b1751..2247b925a0 100644 --- a/xen/arch/arm/arm64/livepatch.c +++ b/xen/arch/arm/arm64/livepatch.c @@ -252,12 +252,24 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf, int ovf = 0; uint64_t val; - if ( symndx > elf->nsym ) + if ( symndx == STN_UNDEF ) + { + dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n", + elf->name); + return -EOPNOTSUPP; + } + else if ( symndx >= elf->nsym ) { dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n", elf->name, symndx); return -EINVAL; } + else if ( !elf->sym[symndx].sym ) + { + dprintk(XENLOG_ERR, LIVEPATCH "%s: No relative symbol@%u\n", + elf->name, symndx); + return -EINVAL; + } val = elf->sym[symndx].sym->st_value + r->r_addend; /* S+A */ diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c index 7917610f1d..406eb910cc 100644 --- a/xen/arch/x86/livepatch.c +++ b/xen/arch/x86/livepatch.c @@ -170,12 +170,24 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf, uint8_t *dest = base->load_addr + r->r_offset; uint64_t val; - if ( symndx > elf->nsym ) + if ( symndx == STN_UNDEF ) + { + dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n", + elf->name); + return -EOPNOTSUPP; + } + else if ( symndx >= elf->nsym ) { dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n", elf->name, symndx); return -EINVAL; } + else if ( !elf->sym[symndx].sym ) + { + dprintk(XENLOG_ERR, LIVEPATCH "%s: No symbol@%u\n", + elf->name, symndx); + return -EINVAL; + } val = r->r_addend + elf->sym[symndx].sym->st_value;