diff options
| author | Sean Young <sean@mess.org> | 2026-09-13 15:12:27 +0100 |
|---|---|---|
| committer | Helge Deller <deller@gmx.de> | 2026-09-15 09:30:05 +0200 |
| commit | 7dfa2e8a7a6bd8e86060bf4ea99b54091b3fd971 (patch) | |
| tree | 6fc938ffa3345f480497fcd92d9ba3d7499a44de | |
| parent | ac84978bfd0f23f1cc519f4c62e3f5d0d7002073 (diff) | |
| download | linux-next-7dfa2e8a7a6bd8e86060bf4ea99b54091b3fd971.tar.gz linux-next-7dfa2e8a7a6bd8e86060bf4ea99b54091b3fd971.zip | |
parisc: unwind: Replace open-coded binary search with bsearch()
There is a bug in the binary search where hi can underflow. If
addr is less than the first entry, then "hi = mid - 1" will underflow
to ULONG_MAX. Then we have an out-of-bounds read.
Replace the open-coded binary search with bsearch().
Issue found by an LLM.
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Helge Deller <deller@gmx.de>
| -rw-r--r-- | arch/parisc/kernel/unwind.c | 33 |
1 files changed, 15 insertions, 18 deletions
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index 32103a270a8e..fab9ae22191a 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/sort.h> +#include <linux/bsearch.h> #include <linux/sched/task_stack.h> #include <linux/uaccess.h> @@ -49,27 +50,23 @@ static DEFINE_SPINLOCK(unwind_lock); static struct unwind_table kernel_unwind_table __ro_after_init; static LIST_HEAD(unwind_tables); -static inline const struct unwind_table_entry * -find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr) +static int cmp_unwind_entry(const void *key, const void *elt) { - const struct unwind_table_entry *e = NULL; - unsigned long lo, hi, mid; + unsigned long addr = (unsigned long)key; + const struct unwind_table_entry *e = elt; - lo = 0; - hi = table->length - 1; - - while (lo <= hi) { - mid = (hi - lo) / 2 + lo; - e = &table->table[mid]; - if (addr < e->region_start) - hi = mid - 1; - else if (addr > e->region_end) - lo = mid + 1; - else - return e; - } + if (addr < e->region_start) + return -1; + if (addr > e->region_end) + return 1; + return 0; +} - return NULL; +static inline const struct unwind_table_entry * +find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr) +{ + return bsearch((void *)addr, table->table, table->length, + sizeof(*table->table), cmp_unwind_entry); } static const struct unwind_table_entry * |
