Skip to content

Commit

Permalink
readelf: fix -n for x86-64 ibt/shstk notes.
Browse files Browse the repository at this point in the history
I couldn't work out how to get gcc to actually produce such a thing, but
/bin/dbxtool on my debian box right now has them.

The big mistake here is that GNU property notes' data is always 8-byte
aligned, so we needed to skip that. That lets us get rid of the existing
loop termination hack to skip padding.

While I'm here -- since the symptom was running off the end of the file --
I've also added a bounds check in the property dumping loop.

I wish I had fuzzing infrastructure to run AFL++ against this every time
it changes... In lieu of that I do wonder whether we should add `readelf
-aW /bin/* > /dev/null` as a smoke test that "at least it works for all
the _valid_ binaries on the system you're testing on". That would have
caught this sooner.
  • Loading branch information
enh-google authored and landley committed Mar 15, 2024
1 parent cab0b66 commit 6c23ff0
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions toys/other/readelf.c
Expand Up @@ -370,14 +370,14 @@ static void show_attributes(unsigned long offset, unsigned long size)

static void show_notes(unsigned long offset, unsigned long size)
{
char *note = TT.elf + offset;
char *note = TT.elf + offset, *end = TT.elf + offset + size;

if (!fits("note", -1, offset, size)) return;

printf(" %-20s%11s\tDescription\n", "Owner", "Data size");
while (note < TT.elf+offset+size) {
while (note < end) {
char *p = note, *desc;
unsigned namesz=elf_int(&p), descsz=elf_int(&p), type=elf_int(&p), j=0;
unsigned namesz=elf_int(&p),descsz=elf_int(&p),type=elf_int(&p),j=0;

if (namesz > size || descsz > size)
return error_msg("%s: bad note @%lu", TT.f, offset);
Expand All @@ -392,30 +392,36 @@ static void show_notes(unsigned long offset, unsigned long size)
} else if (type == 4) {
printf("NT_GNU_GOLD_VERSION\t%.*s", descsz, p), j=1;
} else if (type == 5) {
printf("NT_GNU_PROPERTY_TYPE_0\t");
while (descsz-j > 8) { // Ignore 0-padding at the end.
printf("NT_GNU_PROPERTY_TYPE_0\n Properties:");
while (descsz - j > 0) {
int pr_type = elf_int(&p);
int pr_size = elf_int(&p), k, pr_data;

j += 8;
printf("\n Properties: ");
if (p > end) return error_msg("%s: bad property @%lu", TT.f, offset);
if (pr_size != 4) {
// Just hex dump anything we aren't familiar with.
for (k=0;k<pr_size;k++) printf("%02x", *p++);
xputc('\n');
j += pr_size;
} else {
pr_data = elf_int(&p);
j += 4;
elf_int(&p); // Skip padding.
j += 8;
if (pr_type == 0xc0000000) {
printf("arm64 features:");
printf("\tarm64 features:");
if (pr_data & 1) printf(" bti");
if (pr_data & 2) printf(" pac");
xputc('\n');
} else if (pr_type == 0xc0000002) {
printf("\tx86 feature:");
if (pr_data & 1) printf(" ibt");
if (pr_data & 2) printf(" shstk");
xputc('\n');
} else if (pr_type == 0xc0008002) {
printf("x86 isa needed: x86-64v%d", ffs(pr_data));
printf("\tx86 isa needed: x86-64v%d", ffs(pr_data));
} else {
printf("other (%#x): %#x", pr_type, pr_data);
printf("\tother (%#x): %#x", pr_type, pr_data);
}
}
}
Expand Down

0 comments on commit 6c23ff0

Please sign in to comment.