Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/riscv64-cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# build-std resolves a separate workspace, so pass the libc pin as Cargo config too.
[patch.crates-io]
libc = { git = "https://github.com/rust-lang/libc", rev = "1a661633f11a261ff9c00b40875ef72f1cbec818" }
16 changes: 16 additions & 0 deletions .github/workflows/build-manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ on:
- '.github/workflows/ddk-lkm.yml'
- '.github/workflows/ksud.yml'
- '.github/workflows/ksud-extra.yml'
- '.github/workflows/ksuinit.yml'
- '.github/scripts/setup-rust-build.sh'
- '.github/riscv64-cargo.toml'
- 'repack_apk.py'
- 'manager/**'
- 'kernel/**'
Expand All @@ -24,7 +26,9 @@ on:
- '.github/workflows/ddk-lkm.yml'
- '.github/workflows/ksud.yml'
- '.github/workflows/ksud-extra.yml'
- '.github/workflows/ksuinit.yml'
- '.github/scripts/setup-rust-build.sh'
- '.github/riscv64-cargo.toml'
- 'repack_apk.py'
- 'manager/**'
- 'kernel/**'
Expand Down Expand Up @@ -107,6 +111,7 @@ jobs:
include:
- target: aarch64-linux-android
- target: x86_64-linux-android
- target: riscv64-linux-android
uses: ./.github/workflows/ksud.yml
with:
target: ${{ matrix.target }}
Expand Down Expand Up @@ -246,6 +251,12 @@ jobs:
name: ksud-x86_64-linux-android
path: artifacts/ksud-x86_64-linux-android

- name: Download RISC-V ksud
uses: actions/download-artifact@v8
with:
name: ksud-riscv64-linux-android
path: artifacts/ksud-riscv64-linux-android

- name: Place manager apk and ksud artifacts
run: |
mkdir -p manager/app/build/outputs/apk/release
Expand All @@ -255,12 +266,16 @@ jobs:

mkdir -p target/aarch64-linux-android/release
mkdir -p target/x86_64-linux-android/release
mkdir -p target/riscv64-linux-android/release
ARM64_KSUD=$(find artifacts/ksud-aarch64-linux-android -type f -name ksud | head -n 1)
X86_64_KSUD=$(find artifacts/ksud-x86_64-linux-android -type f -name ksud | head -n 1)
RISCV64_KSUD=$(find artifacts/ksud-riscv64-linux-android -type f -name ksud | head -n 1)
test -n "$ARM64_KSUD"
test -n "$X86_64_KSUD"
test -n "$RISCV64_KSUD"
cp -f "$ARM64_KSUD" target/aarch64-linux-android/release/ksud
cp -f "$X86_64_KSUD" target/x86_64-linux-android/release/ksud
cp -f "$RISCV64_KSUD" target/riscv64-linux-android/release/ksud

- name: Prepare signing inputs
if: ${{ github.event_name == 'pull_request' || (github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) || github.ref_type == 'tag' }}
Expand Down Expand Up @@ -296,6 +311,7 @@ jobs:
-t release \
-a arm64-v8a \
-a x86_64 \
-a riscv64 \
-K "$SIGN_KEYSTORE_FILE" \
-A "$SIGN_KEY_ALIAS" \
-P "$SIGN_KEYSTORE_PASSWORD" \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ksud-extra.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
run: |
mv ksuinit-aarch64/ksuinit ./userspace/ksud/bin/aarch64/
mv ksuinit-x86_64/ksuinit ./userspace/ksud/bin/x86_64/
mv ksuinit-riscv64/ksuinit ./userspace/ksud/bin/riscv64/

- name: Setup rustup
run: |
Expand Down
18 changes: 14 additions & 4 deletions .github/workflows/ksud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@ jobs:
run: |
mv ksuinit-aarch64/ksuinit ./userspace/ksud/bin/aarch64/
mv ksuinit-x86_64/ksuinit ./userspace/ksud/bin/x86_64/
mv ksuinit-riscv64/ksuinit ./userspace/ksud/bin/riscv64/

- name: Setup rustup
run: |
rustup update stable
rustup target add ${{ inputs.target }}
if [ "${{ inputs.target }}" = riscv64-linux-android ]; then
rustup toolchain install nightly-2026-09-23 --profile minimal --component rust-src
else
rustup update stable
rustup target add ${{ inputs.target }}
fi

- uses: Swatinem/rust-cache@v2
with:
Expand All @@ -58,8 +63,13 @@ jobs:
if [ "${{ github.event_name }}" = "pull_request" ]; then
export KSU_PACKAGE_NAME="me.weishu.kernelsu.pr"
fi
source .github/scripts/setup-rust-build.sh ${{ inputs.target }} 26
cargo build --target $TRIPLE --release --manifest-path ./userspace/ksud/Cargo.toml
if [ "${{ inputs.target }}" = riscv64-linux-android ]; then
source .github/scripts/setup-rust-build.sh riscv64-linux-android 35
cargo +nightly-2026-09-23 build --config .github/riscv64-cargo.toml -Z build-std=std,panic_abort --target "$TRIPLE" --release --manifest-path ./userspace/ksud/Cargo.toml
else
source .github/scripts/setup-rust-build.sh ${{ inputs.target }} 26
cargo build --target "$TRIPLE" --release --manifest-path ./userspace/ksud/Cargo.toml
fi

- name: Upload ksud artifact
uses: actions/upload-artifact@v7
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/ksuinit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,38 @@ jobs:
with:
name: ksuinit-x86_64
path: target/x86_64-linux-android/release/ksuinit

build-riscv64:
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup Rust
run: rustup toolchain install nightly-2026-09-23 --profile minimal --component rust-src

- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r29

- uses: Swatinem/rust-cache@v2
with:
workspaces: . -> target
cache-targets: false

- name: Build RISC-V ksuinit
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
run: |
source .github/scripts/setup-rust-build.sh riscv64-linux-android 35
BUILTINS="$($CLANG_PATH --print-resource-dir)/lib/linux/libclang_rt.builtins-riscv64-android.a"
export RUSTFLAGS="-C target-feature=+crt-static -C link-arg=-Wl,-z,max-page-size=16384 -C link-arg=-Wno-unused-command-line-argument -C link-arg=$BUILTINS"
cargo +nightly-2026-09-23 build --config .github/riscv64-cargo.toml -Z build-std=std,panic_abort --package ksuinit --target=riscv64-linux-android --release

- name: Upload RISC-V ksuinit artifact
uses: actions/upload-artifact@v7
with:
name: ksuinit-riscv64
path: target/riscv64-linux-android/release/ksuinit
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ edition = "2024"
anyhow = "1"
log = "0.4"

[patch.crates-io]
libc = { git = "https://github.com/rust-lang/libc", rev = "1a661633f11a261ff9c00b40875ef72f1cbec818" }

[profile.release]
strip = true
lto = true
Expand Down
3 changes: 3 additions & 0 deletions kernel/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ kernelsu-objs += hook/arm64/syscall_hook.o
else ifeq ($(CONFIG_X86_64),y)
kernelsu-objs += hook/x86_64/patch_memory.o
kernelsu-objs += hook/x86_64/syscall_hook.o
else ifeq ($(CONFIG_RISCV),y)
kernelsu-objs += hook/riscv64/patch_memory.o
kernelsu-objs += hook/riscv64/syscall_hook.o
endif

kernelsu-objs += infra/file_wrapper.o
Expand Down
2 changes: 1 addition & 1 deletion kernel/feature/adb_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ static long do_ksu_adb_root_handle_execve(const char __user *filename_user, stru
long ksu_adb_root_handle_execve(struct pt_regs *regs)
{
if (static_branch_unlikely(&ksu_adb_root)) {
return do_ksu_adb_root_handle_execve((const char __user *)PT_REGS_PARM1(regs), regs,
return do_ksu_adb_root_handle_execve((const char __user *)PT_REGS_SYSCALL_PARM1(regs), regs,
(unsigned long *)&PT_REGS_PARM3(regs));
}
return 0;
Expand Down
8 changes: 4 additions & 4 deletions kernel/feature/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ static long ksu_handle_execve_sucompat_common(const char __user **filename_user,
struct file *ksud_file;
const struct cred *old_cred;

if (execveat && ((int)PT_REGS_PARM1(regs) != AT_FDCWD || (int)PT_REGS_PARM5(regs) != 0))
if (execveat && ((int)PT_REGS_SYSCALL_PARM1(regs) != AT_FDCWD || (int)PT_REGS_PARM5(regs) != 0))
goto do_orig_execve;

if (unlikely(!filename_user))
Expand Down Expand Up @@ -217,7 +217,7 @@ static long ksu_handle_execve_sucompat_common(const char __user **filename_user,
pending_sucompat = ksu_sulog_capture_sucompat(*filename_user, argv_user, GFP_KERNEL);
// execve(file, argv, environ)
// execveat(fd, file, argv, environ, flags)
orig_regs[0] = regs->__PT_PARM1_REG;
orig_regs[0] = PT_REGS_SYSCALL_PARM1(regs);
orig_regs[1] = regs->__PT_PARM2_REG;
orig_regs[2] = regs->__PT_PARM3_REG;
orig_regs[3] = regs->__PT_SYSCALL_PARM4_REG;
Expand All @@ -226,7 +226,7 @@ static long ksu_handle_execve_sucompat_common(const char __user **filename_user,
regs->__PT_SYSCALL_PARM4_REG = envp;
regs->__PT_PARM3_REG = (unsigned long)argv_user;
regs->__PT_PARM2_REG = empty_user_path();
regs->__PT_PARM1_REG = tmp_fd;
PT_REGS_SYSCALL_PARM1(regs) = tmp_fd;

ret = escape_with_root_profile();
if (ret) {
Expand All @@ -237,7 +237,7 @@ static long ksu_handle_execve_sucompat_common(const char __user **filename_user,
ret = ksu_syscall_table[__NR_execveat](regs);
if (ret < 0) {
ksu_close_fd(tmp_fd);
regs->__PT_PARM1_REG = orig_regs[0];
PT_REGS_SYSCALL_PARM1(regs) = orig_regs[0];
regs->__PT_PARM2_REG = orig_regs[1];
regs->__PT_PARM3_REG = orig_regs[2];
regs->__PT_SYSCALL_PARM4_REG = orig_regs[3];
Expand Down
2 changes: 1 addition & 1 deletion kernel/hook/patch_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#else
#include "asm/insn.h" // IWYU pragma: keep
#endif
#elif __x86_64__
#elif defined(__x86_64__) || defined(__riscv)
#include <asm/ptrace.h>
#else
#error "Unsupported arch"
Expand Down
57 changes: 57 additions & 0 deletions kernel/hook/riscv64/insn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __KSU_RISCV64_INSN_H
#define __KSU_RISCV64_INSN_H

#include <linux/types.h>

static inline unsigned int ksu_riscv_insn_length(u16 insn)
{
if ((insn & 3) != 3)
return 2;
if ((insn & 0x1f) != 0x1f)
return 4;
/* Do not interpret the payload of an unsupported long instruction. */
return 0;
}

static inline bool ksu_riscv_jal_target(u32 insn, unsigned long pc, unsigned long *target)
{
u32 imm;
s32 offset;

/* JAL ra, offset. JAL x0 is a jump, not a call. */
if ((insn & 0xfff) != 0xef)
return false;
imm = ((insn >> 31) << 20) | (((insn >> 12) & 0xff) << 12) | (((insn >> 20) & 1) << 11) |
(((insn >> 21) & 0x3ff) << 1);
offset = (s32)(imm << 11) >> 11;
*target = pc + offset;
return true;
}

static inline bool ksu_riscv_auipc_call_target(u32 upper, u32 next, unsigned int next_len, unsigned long pc,
unsigned long *target)
{
unsigned int reg = (upper >> 7) & 0x1f;
s32 lower;

if ((upper & 0x7f) != 0x17 || !reg)
return false;
if (next_len == 4) {
/* AUIPC rd, imm20; JALR ra, rd, imm12. */
if ((next & 0x707f) != 0x67 || ((next >> 7) & 0x1f) != 1 || ((next >> 15) & 0x1f) != reg)
return false;
lower = (s32)next >> 20;
} else if (next_len == 2) {
/* C.JALR implicitly writes ra. RV64 does not have C.JAL. */
if ((next & 0xf07f) != 0x9002 || ((next >> 7) & 0x1f) != reg)
return false;
lower = 0;
} else {
return false;
}
*target = (pc + (s32)(upper & 0xfffff000) + lower) & ~1UL;
return true;
}

#endif
Loading
Loading