Skip to content

Commit

Permalink
kernel: Allow to re-enable sucompat
Browse files Browse the repository at this point in the history
  • Loading branch information
tiann committed Feb 16, 2025
1 parent 9bb39ff commit 4593ae8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 39 deletions.
81 changes: 44 additions & 37 deletions kernel/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ int ksu_handle_devpts(struct inode *inode)

#ifdef CONFIG_KPROBES

static int sys_faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
int *dfd = (int *)&PT_REGS_PARM1(real_regs);
Expand All @@ -202,17 +202,18 @@ static int sys_faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_faccessat(dfd, filename_user, mode, NULL);
}

static int sys_newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
int *dfd = (int *)&PT_REGS_PARM1(real_regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(real_regs);
const char __user **filename_user =
(const char **)&PT_REGS_PARM2(real_regs);
int *flags = (int *)&PT_REGS_SYSCALL_PARM4(real_regs);

return ksu_handle_stat(dfd, filename_user, flags);
}

static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
struct pt_regs *real_regs = PT_REAL_REGS(regs);
const char __user **filename_user =
Expand All @@ -222,21 +223,6 @@ static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
NULL);
}

static struct kprobe faccessat_kp = {
.symbol_name = SYS_FACCESSAT_SYMBOL,
.pre_handler = sys_faccessat_handler_pre,
};

static struct kprobe newfstatat_kp = {
.symbol_name = SYS_NEWFSTATAT_SYMBOL,
.pre_handler = sys_newfstatat_handler_pre,
};

static struct kprobe execve_kp = {
.symbol_name = SYS_EXECVE_SYMBOL,
.pre_handler = sys_execve_handler_pre,
};

static int pts_unix98_lookup_pre(struct kprobe *p, struct pt_regs *regs)
{
struct inode *inode;
Expand All @@ -246,35 +232,56 @@ static int pts_unix98_lookup_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_devpts(inode);
}

static struct kprobe pts_unix98_lookup_kp = { .symbol_name =
"pts_unix98_lookup",
.pre_handler =
pts_unix98_lookup_pre };

#endif

static struct kprobe *init_kprobe(const char *name,
kprobe_pre_handler_t handler)
{
struct kprobe *kp = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
if (!kp)
return NULL;
kp->symbol_name = name;
kp->pre_handler = handler;

int ret = register_kprobe(kp);
pr_info("sucompat: register_%s kprobe: %d\n", name, ret);
if (ret) {
kfree(kp);
return NULL;
}

return kp;
}

static void destroy_kprobe(struct kprobe **kp_ptr)
{
struct kprobe *kp = *kp_ptr;
if (!kp)
return;
unregister_kprobe(kp);
synchronize_rcu();
kfree(kp);
*kp_ptr = NULL;
}

static struct kprobe *su_kps[4];

// sucompat: permited process can execute 'su' to gain root access.
void ksu_sucompat_init()
{
#ifdef CONFIG_KPROBES
int ret;
ret = register_kprobe(&execve_kp);
pr_info("sucompat: execve_kp: %d\n", ret);
ret = register_kprobe(&newfstatat_kp);
pr_info("sucompat: newfstatat_kp: %d\n", ret);
ret = register_kprobe(&faccessat_kp);
pr_info("sucompat: faccessat_kp: %d\n", ret);
ret = register_kprobe(&pts_unix98_lookup_kp);
pr_info("sucompat: devpts_kp: %d\n", ret);
su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre);
su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre);
su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre);
su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre);
#endif
}

void ksu_sucompat_exit()
{
#ifdef CONFIG_KPROBES
unregister_kprobe(&execve_kp);
unregister_kprobe(&newfstatat_kp);
unregister_kprobe(&faccessat_kp);
unregister_kprobe(&pts_unix98_lookup_kp);
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
destroy_kprobe(&su_kps[i]);
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ fun SettingScreen(navigator: DestinationsNavigator) {
title = stringResource(id = R.string.settings_disable_su),
summary = stringResource(id = R.string.settings_disable_su_summary),
checked = isSuDisabled,
enabled = !isSuDisabled // we can't re-enable su if it's disabled.

This comment has been minimized.

Copy link
@backslashxx

backslashxx Feb 17, 2025

Contributor

oh keks, it is here, it got lost.

) { checked ->
val shouldEnable = !checked
if (Natives.setSuEnabled(shouldEnable)) {
Expand Down Expand Up @@ -502,4 +501,4 @@ private fun TopBar(
@Composable
private fun SettingsPreview() {
SettingScreen(EmptyDestinationsNavigator)
}
}

3 comments on commit 4593ae8

@backslashxx
Copy link
Contributor

@backslashxx backslashxx commented on 4593ae8 Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a neat feature. Works great.

will this feature eventually be per-app?
might be neat to actually put on app profile.

say something like Termux needs sucompat, but not KernelFlasher.

@tiann
Copy link
Owner Author

@tiann tiann commented on 4593ae8 Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not. This feature is used for resisting side channel attack.
Adding per-app feature can't achieve it.

@backslashxx
Copy link
Contributor

@backslashxx backslashxx commented on 4593ae8 Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried adding sucompat init and exit on __ksu_is_allow_uid conditions, so what happens
is that when a non-allowed app runs in background, it just turns off sucompat

yeah its a no go. I only realized it now, that, that question was dumb.

Please sign in to comment.