kernel: Apply the SUSFS patch
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
#include <linux/printk.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
#include <linux/susfs.h>
|
||||
#include <linux/susfs_def.h>
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
#include "manager.h"
|
||||
#include "kernel_umount.h"
|
||||
#include "klog.h" // IWYU pragma: keep
|
||||
@@ -21,6 +26,79 @@
|
||||
|
||||
#include "sulog.h"
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
extern u32 susfs_zygote_sid;
|
||||
extern bool susfs_is_mnt_devname_ksu(struct path *path);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
extern void susfs_run_sus_path_loop(uid_t uid);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
extern bool susfs_is_log_enabled __read_mostly;
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
static bool susfs_is_umount_for_zygote_system_process_enabled = false;
|
||||
static bool susfs_is_umount_for_zygote_iso_service_enabled = false;
|
||||
extern void susfs_reorder_mnt_id(void);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
extern bool susfs_is_auto_add_sus_bind_mount_enabled;
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
extern bool susfs_is_auto_add_sus_ksu_default_mount_enabled;
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
extern bool susfs_is_auto_add_try_umount_for_bind_mount_enabled;
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
|
||||
static inline void susfs_on_post_fs_data(void) {
|
||||
struct path path;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (!kern_path(DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS, 0, &path)) {
|
||||
susfs_is_umount_for_zygote_system_process_enabled = true;
|
||||
path_put(&path);
|
||||
}
|
||||
pr_info("susfs_is_umount_for_zygote_system_process_enabled: %d\n", susfs_is_umount_for_zygote_system_process_enabled);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT, 0, &path)) {
|
||||
susfs_is_auto_add_sus_bind_mount_enabled = false;
|
||||
path_put(&path);
|
||||
}
|
||||
pr_info("susfs_is_auto_add_sus_bind_mount_enabled: %d\n", susfs_is_auto_add_sus_bind_mount_enabled);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT, 0, &path)) {
|
||||
susfs_is_auto_add_sus_ksu_default_mount_enabled = false;
|
||||
path_put(&path);
|
||||
}
|
||||
pr_info("susfs_is_auto_add_sus_ksu_default_mount_enabled: %d\n", susfs_is_auto_add_sus_ksu_default_mount_enabled);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
if (!kern_path(DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT, 0, &path)) {
|
||||
susfs_is_auto_add_try_umount_for_bind_mount_enabled = false;
|
||||
path_put(&path);
|
||||
}
|
||||
pr_info("susfs_is_auto_add_try_umount_for_bind_mount_enabled: %d\n", susfs_is_auto_add_try_umount_for_bind_mount_enabled);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
}
|
||||
|
||||
static inline bool is_some_system_uid(uid_t uid)
|
||||
{
|
||||
return (uid >= 1000 && uid < 10000);
|
||||
}
|
||||
|
||||
static inline bool is_zygote_isolated_service_uid(uid_t uid)
|
||||
{
|
||||
return ((uid >= 90000 && uid < 100000) || (uid >= 1090000 && uid < 1100000));
|
||||
}
|
||||
|
||||
static inline bool is_zygote_normal_app_uid(uid_t uid)
|
||||
{
|
||||
return ((uid >= 10000 && uid < 19999) || (uid >= 1010000 && uid < 1019999));
|
||||
}
|
||||
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
static bool ksu_kernel_umount_enabled = true;
|
||||
|
||||
static int kernel_umount_feature_get(u64 *value)
|
||||
@@ -54,12 +132,15 @@ static bool should_umount(struct path *path)
|
||||
pr_info("ignore global mnt namespace process: %d\n", current_uid().val);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
return susfs_is_mnt_devname_ksu(path);
|
||||
#else
|
||||
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
|
||||
const char *fstype = path->mnt->mnt_sb->s_type->name;
|
||||
return strcmp(fstype, "overlay") == 0;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
|
||||
@@ -97,7 +178,12 @@ static int ksu_sys_umount(const char *mnt, int flags)
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
void try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid)
|
||||
#else
|
||||
void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
#endif
|
||||
{
|
||||
struct path path;
|
||||
int ret;
|
||||
@@ -118,6 +204,12 @@ void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
|
||||
if (susfs_is_log_enabled) {
|
||||
pr_info("susfs: umounting '%s' for uid: %d\n", mnt, uid);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = ksu_umount_mnt(mnt, &path, flags);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
@@ -126,11 +218,78 @@ void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
void susfs_try_umount_all(uid_t uid) {
|
||||
susfs_try_umount(uid);
|
||||
/* For Legacy KSU only */
|
||||
try_umount("/odm", true, 0, uid);
|
||||
try_umount("/system", true, 0, uid);
|
||||
try_umount("/vendor", true, 0, uid);
|
||||
try_umount("/product", true, 0, uid);
|
||||
try_umount("/system_ext", true, 0, uid);
|
||||
// - For '/data/adb/modules' we pass 'false' here because it is a loop device that we can't determine whether
|
||||
// its dev_name is KSU or not, and it is safe to just umount it if it is really a mountpoint
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH, uid);
|
||||
try_umount("/data/adb/kpm", false, MNT_DETACH, uid);
|
||||
/* For both Legacy KSU and Magic Mount KSU */
|
||||
try_umount("/debug_ramdisk", true, MNT_DETACH, uid);
|
||||
try_umount("/sbin", false, MNT_DETACH, uid);
|
||||
|
||||
// try umount hosts file
|
||||
try_umount("/system/etc/hosts", false, MNT_DETACH, uid);
|
||||
|
||||
// try umount lsposed dex2oat bins
|
||||
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH, uid);
|
||||
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH, uid);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct umount_tw {
|
||||
struct callback_head cb;
|
||||
const struct cred *old_cred;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
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);
|
||||
}
|
||||
|
||||
uid_t uid = current_uid().val;
|
||||
|
||||
// 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, uid);
|
||||
try_umount("/system", true, 0, uid);
|
||||
try_umount("/vendor", true, 0, uid);
|
||||
try_umount("/product", true, 0, uid);
|
||||
try_umount("/system_ext", true, 0, uid);
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH, uid);
|
||||
try_umount("/data/adb/kpm", false, MNT_DETACH, uid);
|
||||
|
||||
// try umount ksu temp path
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH, uid);
|
||||
try_umount("/sbin", false, MNT_DETACH, uid);
|
||||
|
||||
// try umount lsposed dex2oat bins
|
||||
try_umount("/system/etc/hosts", false, MNT_DETACH, uid);
|
||||
|
||||
// try umount lsposed dex2oat bins
|
||||
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH, uid);
|
||||
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH, uid);
|
||||
|
||||
if (saved)
|
||||
revert_creds(saved);
|
||||
|
||||
if (tw->old_cred)
|
||||
put_cred(tw->old_cred);
|
||||
|
||||
kfree(tw);
|
||||
}
|
||||
#else
|
||||
static void umount_tw_func(struct callback_head *cb)
|
||||
{
|
||||
struct umount_tw *tw = container_of(cb, struct umount_tw, cb);
|
||||
@@ -165,7 +324,106 @@ static void umount_tw_func(struct callback_head *cb)
|
||||
|
||||
kfree(tw);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
|
||||
{
|
||||
struct umount_tw *tw;
|
||||
|
||||
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
|
||||
if (!ksu_module_mounted) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ksu_kernel_umount_enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ksu_uid_should_umount(new_uid)) {
|
||||
return 0;
|
||||
} else {
|
||||
pr_info("uid: %d should not umount!\n", current_uid().val);
|
||||
}
|
||||
|
||||
// We only interest in process spwaned by zygote
|
||||
if (!susfs_is_sid_equal(current->cred->security, susfs_zygote_sid)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if spawned process is isolated service first, and force to do umount if so
|
||||
if (is_zygote_isolated_service_uid(new_uid) && susfs_is_umount_for_zygote_iso_service_enabled) {
|
||||
goto do_umount;
|
||||
}
|
||||
|
||||
// - Since ksu maanger app uid is excluded in allow_list_arr, so ksu_uid_should_umount(manager_uid)
|
||||
// will always return true, that's why we need to explicitly check if new_uid.val belongs to
|
||||
// ksu manager
|
||||
if (ksu_is_manager_uid_valid() &&
|
||||
(new_uid % 1000000 == ksu_get_manager_uid())) // % 1000000 in case it is private space uid
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if spawned process is normal user app and needs to be umounted
|
||||
if (likely(is_zygote_normal_app_uid(new_uid) && ksu_uid_should_umount(new_uid))) {
|
||||
goto do_umount;
|
||||
}
|
||||
|
||||
// Lastly, Check if spawned process is some system process and needs to be umounted
|
||||
if (unlikely(is_some_system_uid(new_uid) && susfs_is_umount_for_zygote_system_process_enabled)) {
|
||||
goto do_umount;
|
||||
}
|
||||
#if __SULOG_GATE
|
||||
ksu_sulog_report_syscall(new_uid, NULL, "setuid", NULL);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
do_umount:
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
// susfs come first, and lastly umount by ksu, make sure umount in reversed order
|
||||
susfs_try_umount_all(new_uid);
|
||||
#else
|
||||
tw = kmalloc(sizeof(*tw), GFP_ATOMIC);
|
||||
if (!tw)
|
||||
return 0;
|
||||
|
||||
tw->old_cred = get_current_cred();
|
||||
tw->cb.func = umount_tw_func;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||
int err = task_work_add(current, &tw->cb, TWA_RESUME);
|
||||
#else
|
||||
int err = task_work_add(current, &tw->cb, true);
|
||||
#endif
|
||||
if (err) {
|
||||
if (tw->old_cred) {
|
||||
put_cred(tw->old_cred);
|
||||
}
|
||||
kfree(tw);
|
||||
pr_warn("unmount add task_work failed\n");
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
|
||||
get_task_struct(current);
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
// We can reorder the mnt_id now after all sus mounts are umounted
|
||||
susfs_reorder_mnt_id();
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
|
||||
susfs_set_current_proc_umounted();
|
||||
|
||||
put_task_struct(current);
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
susfs_run_sus_path_loop(new_uid);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
|
||||
{
|
||||
struct umount_tw *tw;
|
||||
@@ -221,6 +479,7 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ksu_kernel_umount_init(void)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user