elf_lookup must defend against bad chain in hash table
https://github.com/upx/upx/issues/871 fuzzing from leon.weiss AT @ruhr-uni-bochum.de
This commit is contained in:
parent
0a61ffea3a
commit
0870514194
@ -8650,25 +8650,27 @@ unsigned PackLinuxElf::elf_hash(char const *p)
|
|||||||
Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const
|
Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const
|
||||||
{
|
{
|
||||||
if (hashtab && dynsym && dynstr) {
|
if (hashtab && dynsym && dynstr) {
|
||||||
unsigned const nbucket = get_te32(&hashtab[0]);
|
unsigned const n_bucket = get_te32(&hashtab[0]);
|
||||||
unsigned const *const buckets = &hashtab[2];
|
unsigned const *const buckets = &hashtab[2];
|
||||||
unsigned const *const chains = &buckets[nbucket];
|
unsigned const *const chains = &buckets[n_bucket];
|
||||||
if (nbucket) {
|
if (n_bucket) {
|
||||||
unsigned const m = elf_hash(name) % nbucket;
|
unsigned const m = elf_hash(name) % n_bucket;
|
||||||
unsigned nvisit = 0;
|
unsigned nvisit = 0;
|
||||||
unsigned si;
|
unsigned si;
|
||||||
for (si= get_te32(&buckets[m]); si; ) {
|
if ((file_size + file_image) <= (void const *)chains) {
|
||||||
|
throwCantPack("bad n_bucket %#x\n", n_bucket);
|
||||||
|
}
|
||||||
|
for (si= get_te32(&buckets[m]); si; si = get_te32(&chains[si])) {
|
||||||
|
if (n_bucket <= si) {
|
||||||
|
throwCantPack("bad DT_HASH chain %d\n", si);
|
||||||
|
}
|
||||||
char const *const p= get_dynsym_name(si, (unsigned)-1);
|
char const *const p= get_dynsym_name(si, (unsigned)-1);
|
||||||
if (p && 0==strcmp(name, p)) {
|
if (p && 0==strcmp(name, p)) {
|
||||||
return &dynsym[si];
|
return &dynsym[si];
|
||||||
}
|
}
|
||||||
if (nbucket <= ++nvisit) {
|
if (n_bucket <= ++nvisit) {
|
||||||
throwCantPack("circular DT_HASH chain %d\n", si);
|
throwCantPack("circular DT_HASH chain %d\n", si);
|
||||||
}
|
}
|
||||||
si= get_te32(&chains[si]);
|
|
||||||
if (nbucket <= si) { // bad hashtab
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8737,25 +8739,27 @@ Elf32_Sym const *PackLinuxElf32::elf_lookup(char const *name) const
|
|||||||
Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const
|
Elf64_Sym const *PackLinuxElf64::elf_lookup(char const *name) const
|
||||||
{
|
{
|
||||||
if (hashtab && dynsym && dynstr) {
|
if (hashtab && dynsym && dynstr) {
|
||||||
unsigned const nbucket = get_te32(&hashtab[0]);
|
unsigned const n_bucket = get_te32(&hashtab[0]);
|
||||||
unsigned const *const buckets = &hashtab[2];
|
unsigned const *const buckets = &hashtab[2];
|
||||||
unsigned const *const chains = &buckets[nbucket];
|
unsigned const *const chains = &buckets[n_bucket];
|
||||||
if (nbucket) { // -rust-musl can have "empty" hashtab
|
if (n_bucket) { // -rust-musl can have "empty" hashtab
|
||||||
unsigned const m = elf_hash(name) % nbucket;
|
unsigned const m = elf_hash(name) % n_bucket;
|
||||||
unsigned nvisit = 0;
|
unsigned nvisit = 0;
|
||||||
unsigned si;
|
unsigned si;
|
||||||
for (si= get_te32(&buckets[m]); si; ) {
|
if ((file_size + file_image) <= (void const *)chains) {
|
||||||
|
throwCantPack("bad n_bucket %#x\n", n_bucket);
|
||||||
|
}
|
||||||
|
for (si= get_te32(&buckets[m]); si; si = get_te32(&chains[si])) {
|
||||||
|
if (n_bucket <= si) {
|
||||||
|
throwCantPack("bad DT_HASH chain %d\n", si);
|
||||||
|
}
|
||||||
char const *const p= get_dynsym_name(si, (unsigned)-1);
|
char const *const p= get_dynsym_name(si, (unsigned)-1);
|
||||||
if (p && 0==strcmp(name, p)) {
|
if (p && 0==strcmp(name, p)) {
|
||||||
return &dynsym[si];
|
return &dynsym[si];
|
||||||
}
|
}
|
||||||
if (nbucket <= ++nvisit) {
|
if (n_bucket <= ++nvisit) {
|
||||||
throwCantPack("circular DT_HASH chain %d\n", si);
|
throwCantPack("circular DT_HASH chain %d\n", si);
|
||||||
}
|
}
|
||||||
si = get_te32(&chains[si]);
|
|
||||||
if (nbucket <= si) { // bad hashtab
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user