Commit 5dcdcf49 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Luis Henriques

s390: fix normalization bug in exception table sorting

commit bcb7825a upstream.

The normalization pass in the sorting routine of the relative exception
table serves two purposes:
- it ensures that the address fields of the exception table entries are
  fully ordered, so that no ambiguities arise between entries with
  identical instruction offsets (i.e., when two instructions that are
  exactly 8 bytes apart each have an exception table entry associated with
  them)
- it ensures that the offsets of both the instruction and the fixup fields
  of each entry are relative to their final location after sorting.

Commit eb608fb3 ("s390/exceptions: switch to relative exception table
entries") ported the relative exception table format from x86, but modified
the sorting routine to only normalize the instruction offset field and not
the fixup offset field. The result is that the fixup offset of each entry
will be relative to the original location of the entry before sorting,
likely leading to crashes when those entries are dereferenced.

Fixes: eb608fb3 ("s390/exceptions: switch to relative exception table entries")
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 4b9cc54a
...@@ -52,12 +52,16 @@ void sort_extable(struct exception_table_entry *start, ...@@ -52,12 +52,16 @@ void sort_extable(struct exception_table_entry *start,
int i; int i;
/* Normalize entries to being relative to the start of the section */ /* Normalize entries to being relative to the start of the section */
for (p = start, i = 0; p < finish; p++, i += 8) for (p = start, i = 0; p < finish; p++, i += 8) {
p->insn += i; p->insn += i;
p->fixup += i + 4;
}
sort(start, finish - start, sizeof(*start), cmp_ex, NULL); sort(start, finish - start, sizeof(*start), cmp_ex, NULL);
/* Denormalize all entries */ /* Denormalize all entries */
for (p = start, i = 0; p < finish; p++, i += 8) for (p = start, i = 0; p < finish; p++, i += 8) {
p->insn -= i; p->insn -= i;
p->fixup -= i + 4;
}
} }
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment