kernel: rework umount with task_work
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
#include "linux/slab.h"
|
||||
#include <linux/slab.h>
|
||||
#include <linux/task_work.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/capability.h>
|
||||
@@ -508,8 +510,44 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
ksu_umount_mnt(&path, flags);
|
||||
}
|
||||
|
||||
struct umount_tw {
|
||||
struct callback_head cb;
|
||||
const struct cred *old_cred;
|
||||
};
|
||||
|
||||
static void umount_tw_func(struct callback_head *cb)
|
||||
{
|
||||
struct umount_tw *tw = container_of(cb, struct umount_tw, cb);
|
||||
const struct cred *saved = NULL;
|
||||
if (tw->old_cred) {
|
||||
saved = override_creds(tw->old_cred);
|
||||
}
|
||||
|
||||
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
|
||||
// filter the mountpoint whose target is `/data/adb`
|
||||
try_umount("/odm", true, 0);
|
||||
try_umount("/system", true, 0);
|
||||
try_umount("/vendor", true, 0);
|
||||
try_umount("/product", true, 0);
|
||||
try_umount("/system_ext", true, 0);
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||
try_umount("/data/adb/kpm", false, MNT_DETACH);
|
||||
|
||||
// try umount ksu temp path
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||
|
||||
if (saved)
|
||||
revert_creds(saved);
|
||||
|
||||
if (tw->old_cred)
|
||||
put_cred(tw->old_cred);
|
||||
|
||||
kfree(tw);
|
||||
}
|
||||
|
||||
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
{
|
||||
struct umount_tw *tw;
|
||||
if (!new || !old) {
|
||||
return 0;
|
||||
}
|
||||
@@ -587,19 +625,21 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val, current->pid);
|
||||
#endif
|
||||
|
||||
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
|
||||
// filter the mountpoint whose target is `/data/adb`
|
||||
try_umount("/odm", true, 0);
|
||||
try_umount("/system", true, 0);
|
||||
try_umount("/vendor", true, 0);
|
||||
try_umount("/product", true, 0);
|
||||
try_umount("/system_ext", true, 0);
|
||||
tw = kmalloc(sizeof(*tw), GFP_ATOMIC);
|
||||
if (!tw)
|
||||
return 0;
|
||||
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||
try_umount("/data/adb/kpm", false, MNT_DETACH);
|
||||
tw->old_cred = get_current_cred();
|
||||
tw->cb.func = umount_tw_func;
|
||||
|
||||
// try umount ksu temp path
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||
int err = task_work_add(current, &tw->cb, TWA_RESUME);
|
||||
if (err) {
|
||||
if (tw->old_cred) {
|
||||
put_cred(tw->old_cred);
|
||||
}
|
||||
kfree(tw);
|
||||
pr_warn("unmount add task_work failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -653,7 +693,8 @@ static struct kprobe reboot_kp = {
|
||||
};
|
||||
|
||||
// 2. cap_task_fix_setuid hook for handling setuid
|
||||
static int cap_task_fix_setuid_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
static int cap_task_fix_setuid_handler_pre(struct kprobe *p,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct cred *new = (struct cred *)PT_REGS_PARM1(regs);
|
||||
const struct cred *old = (const struct cred *)PT_REGS_PARM2(regs);
|
||||
|
||||
Reference in New Issue
Block a user