From 78004e9a87f240df03e2f73120d291763c32e0a7 Mon Sep 17 00:00:00 2001 From: Ali Ahmet Memis Date: Fri, 21 Aug 2026 01:45:27 +0000 Subject: openrisc: fix arbitrary kernel memory access via or1k_atomic syscall 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 Signed-off-by: Stafford Horne --- drivers/clk/sprd/composite.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 drivers/clk/sprd/composite.c (limited to 'drivers/clk/sprd/composite.c') diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c new file mode 100644 index 000000000..ad6b6383e --- /dev/null +++ b/drivers/clk/sprd/composite.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Spreadtrum composite clock driver +// +// Copyright (C) 2017 Spreadtrum, Inc. +// Author: Chunyan Zhang + +#include + +#include "composite.h" + +static int sprd_comp_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return divider_determine_rate(hw, req, NULL, cc->div.width, 0); +} + +static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate); +} + +static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_div_helper_set_rate(&cc->common, &cc->div, + rate, parent_rate); +} + +static u8 sprd_comp_get_parent(struct clk_hw *hw) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_get_parent(&cc->common, &cc->mux); +} + +static int sprd_comp_set_parent(struct clk_hw *hw, u8 index) +{ + struct sprd_comp *cc = hw_to_sprd_comp(hw); + + return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index); +} + +const struct clk_ops sprd_comp_ops = { + .get_parent = sprd_comp_get_parent, + .set_parent = sprd_comp_set_parent, + + .determine_rate = sprd_comp_determine_rate, + .recalc_rate = sprd_comp_recalc_rate, + .set_rate = sprd_comp_set_rate, +}; +EXPORT_SYMBOL_GPL(sprd_comp_ops); -- cgit v1.3.1