diff options
| author | Ali Ahmet Memis <ali@iusegentoo.com> | 2026-08-21 01:45:27 +0000 |
|---|---|---|
| committer | Stafford Horne <shorne@gmail.com> | 2026-08-29 07:32:26 +0100 |
| commit | 78004e9a87f240df03e2f73120d291763c32e0a7 (patch) | |
| tree | 137c22dd795222931b9d2bf2501d37cd766741aa /arch/mips/boot/ecoff.h | |
| download | linux-stable-78004e9a87f240df03e2f73120d291763c32e0a7.tar.gz linux-stable-78004e9a87f240df03e2f73120d291763c32e0a7.zip | |
openrisc: fix arbitrary kernel memory access via or1k_atomic syscallgrafted
sys_or1k_atomic() (syscall 244 in the "or1k" ABI) takes two user
pointers, v1 and v2, and swaps the words they point to in hand-written
assembly.
l.lwz r29,0(r4)
l.lwz r27,0(r5)
l.sw 0(r4),r27
l.sw 0(r5),r29
The pointers are not checked with access_ok(). The four memory
accesses also have no exception table entries.
A caller passes a kernel address as either pointer, and the syscall
reads from and writes to it directly.
This gives an unprivileged process a kernel read/write primitive. It
overwrites kernel data such as the sys_call_table, gaining code
execution in kernel context.
Check both pointers before entering the critical section. Add fixups
for the four memory accesses so faults on valid but unmapped user
addresses return -EFAULT.
[shorne@gmail.com: fix comment style]
Fixes: 9d02a4283e9c ("OpenRISC: Boot code")
Cc: stable@vger.kernel.org
Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com>
Signed-off-by: Stafford Horne <shorne@gmail.com>
Diffstat (limited to 'arch/mips/boot/ecoff.h')
| -rw-r--r-- | arch/mips/boot/ecoff.h | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/arch/mips/boot/ecoff.h b/arch/mips/boot/ecoff.h new file mode 100644 index 000000000..5be79ebfc --- /dev/null +++ b/arch/mips/boot/ecoff.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Some ECOFF definitions. + */ + +#include <stdint.h> + +typedef struct filehdr { + uint16_t f_magic; /* magic number */ + uint16_t f_nscns; /* number of sections */ + int32_t f_timdat; /* time & date stamp */ + int32_t f_symptr; /* file pointer to symbolic header */ + int32_t f_nsyms; /* sizeof(symbolic hdr) */ + uint16_t f_opthdr; /* sizeof(optional hdr) */ + uint16_t f_flags; /* flags */ +} FILHDR; +#define FILHSZ sizeof(FILHDR) + +#define MIPSEBMAGIC 0x160 +#define MIPSELMAGIC 0x162 + +typedef struct scnhdr { + char s_name[8]; /* section name */ + int32_t s_paddr; /* physical address, aliased s_nlib */ + int32_t s_vaddr; /* virtual address */ + int32_t s_size; /* section size */ + int32_t s_scnptr; /* file ptr to raw data for section */ + int32_t s_relptr; /* file ptr to relocation */ + int32_t s_lnnoptr; /* file ptr to gp histogram */ + uint16_t s_nreloc; /* number of relocation entries */ + uint16_t s_nlnno; /* number of gp histogram entries */ + int32_t s_flags; /* flags */ +} SCNHDR; +#define SCNHSZ sizeof(SCNHDR) +#define SCNROUND ((int32_t)16) + +typedef struct aouthdr { + int16_t magic; /* see above */ + int16_t vstamp; /* version stamp */ + int32_t tsize; /* text size in bytes, padded to DW bdry*/ + int32_t dsize; /* initialized data " " */ + int32_t bsize; /* uninitialized data " " */ + int32_t entry; /* entry pt. */ + int32_t text_start; /* base of text used for this file */ + int32_t data_start; /* base of data used for this file */ + int32_t bss_start; /* base of bss used for this file */ + int32_t gprmask; /* general purpose register mask */ + int32_t cprmask[4]; /* co-processor register masks */ + int32_t gp_value; /* the gp value used for this object */ +} AOUTHDR; +#define AOUTHSZ sizeof(AOUTHDR) + +#define OMAGIC 0407 +#define NMAGIC 0410 +#define ZMAGIC 0413 +#define SMAGIC 0411 +#define LIBMAGIC 0443 + +#define N_TXTOFF(f, a) \ + ((a).magic == ZMAGIC || (a).magic == LIBMAGIC ? 0 : \ + ((a).vstamp < 23 ? \ + ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + 7) & 0xfffffff8) : \ + ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + SCNROUND-1) & ~(SCNROUND-1)) ) ) +#define N_DATOFF(f, a) \ + N_TXTOFF(f, a) + (a).tsize; |
