diff --git a/anykernel/anykernel.sh b/anykernel/anykernel.sh index 90058b0237f9..f7e188e44d38 100644 --- a/anykernel/anykernel.sh +++ b/anykernel/anykernel.sh @@ -4,7 +4,7 @@ ### AnyKernel setup # begin properties properties() { ' -kernel.string=Realme GT Neo 2 / Realme X50 Pro B I G S H O T --with-KSU-Next-- +kernel.string=Realme GT Neo 2 / Realme X50 Pro B I G S H O T --with-SukiSU-Ultra-- do.devicecheck=0 do.modules=0 do.systemless=1 diff --git a/anykernel/banner b/anykernel/banner index e18bd0760d7a..5d1b01836f04 100644 --- a/anykernel/banner +++ b/anykernel/banner @@ -1,26 +1,27 @@ - - . . . - ************ .*** - . ////@@@@@@@@@@@@///////////#@** - . *#@@@@@@@@@@@@@@@@@@@@@@@@@******* - . *#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@** - . @@/* @@@@@***, . - . @@@@@@@ @@@@@@& @@@@@@%* . - /@.......@@*******@@@@@@/* . - . /@.......@@*******@ @@@ .... - . .*#(@@@ ### &@ *** . - . ***, @@# &@**@@@** - **********#@@@@@@@@@@@@@@@ @@@@@@@*, - . .* @ @@ @@@@@** . - */@@ @@ #@ @@** - .*@@@@ @@@@@@@ @@@@@* . - . *#@@@@@***********/@@@@@(,. - . **@@@@@@@@** **@@@@@@@@/* - . **@@@@@@@@@@@@** ,*@@@@@**@@@@@** . - **** **@@*, **@@@@@@@@@@@@@@@** *@@@@*, - ** @@** **@@@@@@@@@@@@@@* *@@** .* - . . . **@@@@@@@@@@@@* . ******* - *@@@@@@@@@** - . *@@ ** - ** @* ** - ******* . \ No newline at end of file +%%%%%*==*%#*##*+=-=#%#=+%%%%*--=%%%%%%%%%%%%#%%%%% +%%%%+-=#%*=#*+:::++=+==++*%*-=+=-#%%%##%+*%%####%% +%%*+=-**++=--:::====---=-:-++===+-#%%**%##%%##%%%% +%*-=-===+--+:::====+====+=:-=====+-*%%%%%%#*%%%%%% +*-====**=-+::::==-:::::-===:-=++===-+%%%%%#=**%%%% +=+*##%*=-=-:::--:::::::::-=-:+#+====:=#%%%%###%%%% +%%%%%*+=:=::::---=--::::---=:-#*+===++=#%%%+=#%%%% +%%%%%*=:--::::-::::::::::--=-:+%+====++-:*##*##### +%%%%#*-:=::::-==----::::::---:-#%*====+=:.=+**#### +%%%%%=-:=::=*+#%%%=-:::=#%#+*--#%#===+**=--+=+*### +%%%%*=+-=::::-===--::::--=+==-=+##====++===-==::-+ +%%%#+====-::::---::::::::--==+=++**===+====++-:::. +%%%#=======--::-:::::::::::-+==-:-#+=+++===+++=--: +%%%#=++======-:-::::::::::-*+=--=-*#==++==++=+=-:- +%%%%*=**-=---==-=+=:::::-=*****=--=%#+*#+==*+==--: +%%%%%%##+===----=++++==++=++**++-:=%%*++++=+++=--- +%%%%%%%%%%*=-----=+=+#%####%%%%%+==+%#++#*+++==+-- +%%%%###+####+---+===--#%%%%###%%%-:=%##*+%%#+=*%%% +%%%#####**###*=--==++*#%@%###**#%=:=%%+##%%%%##%%% +%#####**####################***##=:-***#%%%%%%%%%% +%##*+##*#+*********#######*******+::+%%%%%%%%%%%%% +##*=*####+**************+++**#**#*::=%%%%%%%%%%%%% +##*+*###*#**********++++++++**###*::-*%#%%%%%%%%%% +%%######*##********++++++****#***+-::-+*%%%%%%%%%% +@%##%%%%#%%%%%%###**####**++++****=:::+*%%%%%%%%%% +%%#*#%##+##%%%%###+++++++=------=+*-:-=*+#%%%%%%%% + diff --git a/anykernel/modules/system/lib/modules/placeholder b/anykernel/modules/system/lib/modules/placeholder deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/anykernel/patch/placeholder b/anykernel/patch/placeholder deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/anykernel/ramdisk/placeholder b/anykernel/ramdisk/placeholder deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile index 7e1ba2afb907..2db443cb06dc 100644 --- a/arch/arm64/boot/Makefile +++ b/arch/arm64/boot/Makefile @@ -29,6 +29,7 @@ endif DTB_OBJS := $(shell find $(obj)/dts/ -name \*.dtb) DTBO_OBJS := $(shell find $(obj)/dts/ -name \*.dtbo) +PATCH_KPM := /home/user/kernel_realme_sm8250/scripts/patch_kpm # đường dẫn tuyệt đối # Add RTIC DTB to the DTB list if RTIC MPGen is enabled # Note, we keep this for compatibility with @@ -44,6 +45,10 @@ rtic_mp.dtb: vmlinux FORCE $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) +ifeq ($(CONFIG_KPM),y) + $(Q)cd $(obj) && $(PATCH_KPM) + $(Q)mv -f $(obj)/oImage $@ +endif $(obj)/Image.bz2: $(obj)/Image FORCE $(call if_changed,bzip2) diff --git a/arch/arm64/configs/vendor/sm8250_defconfig b/arch/arm64/configs/vendor/sm8250_defconfig index 82da2ef93e65..973a256265c1 100644 --- a/arch/arm64/configs/vendor/sm8250_defconfig +++ b/arch/arm64/configs/vendor/sm8250_defconfig @@ -1,4 +1,7 @@ -CONFIG_LOCALVERSION="-Bigshot-KSU-Next" +# localver +CONFIG_LOCALVERSION="-Bigshot-SukiSU-Suzumi" +CONFIG_LOCALVERSION_AUTO=n +# the rest CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT=y @@ -797,3 +800,13 @@ CONFIG_DEBUG_LIST=y # KernelSU CONFIG_KSU=y CONFIG_KSU_SUSFS=y +CONFIG_KSU_MANUAL_HOOK=y +CONFIG_KPM=y +CONFIG_KALLSYMS=y +CONFIG_KSU_SUSFS_SUS_MOUNT=y +CONFIG_KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER=y +CONFIG_KSU_SUSFS_SUS_PATH=y +CONFIG_KSU_SUSFS_SUS_KSTAT=y +CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT=y +CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT=y +CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT=y diff --git a/build.sh b/build.sh index 2b93d2fbff76..b9fe786ad781 100644 --- a/build.sh +++ b/build.sh @@ -12,8 +12,8 @@ export CLANG_PATH="~/toolchains/bin" export PATH="$CLANG_PATH:$PATH" export CROSS_COMPILE=aarch64-linux-gnu- export CROSS_COMPILE_ARM32=arm-linux-gnueabi- -export KBUILD_BUILD_USER=Amog -export KBUILD_BUILD_HOST=Us +export KBUILD_BUILD_USER=suzumi +export KBUILD_BUILD_HOST=vigilante echo echo "Kernel is going to be built using $KERNEL_DEFCONFIG" diff --git a/drivers/Makefile b/drivers/Makefile index 56957811d415..14dfcfe0f5d0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -193,4 +193,16 @@ obj-$(CONFIG_SIOX) += siox/ obj-$(CONFIG_GNSS) += gnss/ obj-$(CONFIG_SENSORS_SSC) += sensors/ + + + + + + + + + + + + obj-$(CONFIG_KSU) += kernelsu/ diff --git a/drivers/kernelsu b/drivers/kernelsu index b32a3654a683..9e51d0d62734 120000 --- a/drivers/kernelsu +++ b/drivers/kernelsu @@ -1 +1 @@ -../KernelSU-Next/kernel \ No newline at end of file +../KernelSU/kernel \ No newline at end of file diff --git a/fs/dcache.c b/fs/dcache.c index 83d5a35e62b3..500d52824661 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2194,7 +2194,7 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent, if (dentry_cmp(dentry, str, hashlen_len(hashlen)) != 0) continue; #ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { + if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TIF_NON_ROOT_USER_APP_PROC)) { continue; } #endif @@ -2282,7 +2282,7 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name) continue; #ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { + if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TIF_NON_ROOT_USER_APP_PROC)) { continue; } #endif diff --git a/fs/namei.c b/fs/namei.c index f2c839086065..5c328a545efc 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -47,6 +47,15 @@ #include "internal.h" #include "mount.h" +#ifdef CONFIG_KSU_SUSFS_SUS_PATH +extern bool susfs_is_sus_android_data_d_name_found(const char *d_name); +extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name); +extern bool susfs_is_inode_sus_path(struct inode *inode); +extern bool susfs_is_base_dentry_android_data_dir(struct dentry* base); +extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base); +extern const struct qstr susfs_fake_qstr_name; +#endif + #define CREATE_TRACE_POINTS #include @@ -509,6 +518,9 @@ struct nameidata { struct path root; struct inode *inode; /* path.dentry.d_inode */ unsigned int flags; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + unsigned int state; +#endif unsigned seq, m_seq; int last_type; unsigned depth; @@ -535,6 +547,9 @@ static void set_nameidata(struct nameidata *p, int dfd, struct filename *name) p->total_link_count = old ? old->total_link_count : 0; p->saved = old; current->nameidata = p; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + p->state = 0; +#endif } static void restore_nameidata(void) @@ -1008,11 +1023,6 @@ static inline int may_follow_link(struct nameidata *nd) const struct inode *parent; kuid_t puid; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (nd->inode && unlikely(nd->inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - return -ENOENT; - } -#endif if (!sysctl_protected_symlinks) return 0; @@ -1091,11 +1101,6 @@ static int may_linkat(struct path *link) { struct inode *inode = link->dentry->d_inode; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (link->dentry->d_inode && unlikely(link->dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - return -ENOENT; - } -#endif /* Inode writeback is not safe when the uid or gid are invalid. */ if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) @@ -1138,11 +1143,6 @@ static int may_linkat(struct path *link) static int may_create_in_sticky(umode_t dir_mode, kuid_t dir_uid, struct inode * const inode) { -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - return -ENOENT; - } -#endif if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) || (!sysctl_protected_regular && S_ISREG(inode->i_mode)) || @@ -1168,7 +1168,9 @@ const char *get_link(struct nameidata *nd) struct inode *inode = nd->link_inode; int error; const char *res; - +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + nd->state |= ND_STATE_OPEN_LAST; +#endif if (!(nd->flags & LOOKUP_RCU)) { touch_atime(&last->link); cond_resched(); @@ -1644,18 +1646,67 @@ static struct dentry *lookup_dcache(const struct qstr *name, static struct dentry *__lookup_hash(const struct qstr *name, struct dentry *base, unsigned int flags) { + +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct dentry *dentry; + bool found_sus_path = false; +#else struct dentry *dentry = lookup_dcache(name, base, flags); +#endif struct dentry *old; struct inode *dir = base->d_inode; - if (dentry) +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (base && base->d_inode && !found_sus_path) { + if (susfs_is_base_dentry_android_data_dir(base) && + susfs_is_sus_android_data_d_name_found(name->name)) + { + if (flags & (LOOKUP_CREATE | LOOKUP_EXCL)) { + return ERR_PTR(-EACCES); + } + dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags); + found_sus_path = true; + goto retry; + } else if (susfs_is_base_dentry_sdcard_dir(base) && + susfs_is_sus_sdcard_d_name_found(name->name)) + { + dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags); + found_sus_path = true; + goto retry; + } + } + dentry = lookup_dcache(name, base, flags); +retry: +#endif + + if (dentry) +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + { + if (!found_sus_path && !IS_ERR(dentry) && dentry->d_inode && susfs_is_inode_sus_path(dentry->d_inode)) { + dentry = lookup_dcache(&susfs_fake_qstr_name, base, flags); + found_sus_path = true; + goto retry; + } + return dentry; + } +#else return dentry; +#endif /* Don't create child dentry for a dead directory. */ if (unlikely(IS_DEADDIR(dir))) return ERR_PTR(-ENOENT); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (found_sus_path) { + dentry = d_alloc(base, &susfs_fake_qstr_name); + goto skip_orig_flow; + } +#endif dentry = d_alloc(base, name); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH +skip_orig_flow: +#endif if (unlikely(!dentry)) return ERR_PTR(-ENOMEM); @@ -1664,12 +1715,6 @@ static struct dentry *__lookup_hash(const struct qstr *name, dput(dentry); dentry = old; } -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - dput(dentry); - return ERR_PTR(-ENOENT); - } -#endif return dentry; } @@ -1680,6 +1725,9 @@ static int lookup_fast(struct nameidata *nd, struct vfsmount *mnt = nd->path.mnt; struct dentry *dentry, *parent = nd->path.dentry; int status = 1; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + bool is_nd_state_lookup_last_and_open_last = (nd->state & ND_STATE_LOOKUP_LAST || nd->state & ND_STATE_OPEN_LAST); +#endif int err; /* @@ -1690,7 +1738,32 @@ static int lookup_fast(struct nameidata *nd, if (nd->flags & LOOKUP_RCU) { unsigned seq; bool negative; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + unsigned backup_next_seq; + + if (is_nd_state_lookup_last_and_open_last && parent->d_inode) { + if (susfs_is_base_dentry_android_data_dir(parent) && + susfs_is_sus_android_data_d_name_found(nd->last.name)) + { + dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &seq); + goto skip_orig_flow1; + } else if (susfs_is_base_dentry_sdcard_dir(parent) && + susfs_is_sus_sdcard_d_name_found(nd->last.name)) + { + dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &seq); + goto skip_orig_flow1; + } + } +#endif dentry = __d_lookup_rcu(parent, &nd->last, &seq); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode) { + if (susfs_is_inode_sus_path(dentry->d_inode)) { + dentry = __d_lookup_rcu(parent, &susfs_fake_qstr_name, &backup_next_seq); + } + } +skip_orig_flow1: +#endif if (unlikely(!dentry)) { if (unlazy_walk(nd)) return -ECHILD; @@ -1736,7 +1809,30 @@ static int lookup_fast(struct nameidata *nd, /* we'd been told to redo it in non-rcu mode */ status = d_revalidate(dentry, nd->flags); } else { +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (is_nd_state_lookup_last_and_open_last && parent->d_inode) { + if (susfs_is_base_dentry_android_data_dir(parent) && + susfs_is_sus_android_data_d_name_found(nd->last.name)) + { + dentry = __d_lookup(parent, &susfs_fake_qstr_name); + goto skip_orig_flow2; + } else if (susfs_is_base_dentry_sdcard_dir(parent) && + susfs_is_sus_sdcard_d_name_found(nd->last.name)) + { + dentry = __d_lookup(parent, &susfs_fake_qstr_name); + goto skip_orig_flow2; + } + } +#endif dentry = __d_lookup(parent, &nd->last); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (is_nd_state_lookup_last_and_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode) { + if (susfs_is_inode_sus_path(dentry->d_inode)) { + dentry = __d_lookup(parent, &susfs_fake_qstr_name); + } + } +skip_orig_flow2: +#endif if (unlikely(!dentry)) return 0; status = d_revalidate(dentry, nd->flags); @@ -1768,12 +1864,41 @@ static struct dentry *__lookup_slow(const struct qstr *name, struct dentry *dentry, *old; struct inode *inode = dir->d_inode; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(sus_wq); + bool found_sus_path = false; + bool is_nd_flags_lookup_last = (flags & ND_FLAGS_LOOKUP_LAST); +#endif /* Don't go there if it's already dead */ if (unlikely(IS_DEADDIR(inode))) return ERR_PTR(-ENOENT); again: +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (found_sus_path) { + dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq); + goto retry; + } + if (is_nd_flags_lookup_last && !found_sus_path) { + if (susfs_is_base_dentry_android_data_dir(dir) && + susfs_is_sus_android_data_d_name_found(name->name)) + { + dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq); + found_sus_path = true; + goto retry; + } else if (susfs_is_base_dentry_sdcard_dir(dir) && + susfs_is_sus_sdcard_d_name_found(name->name)) + { + dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq); + found_sus_path = true; + goto retry; + } + } +#endif dentry = d_alloc_parallel(dir, name, &wq); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH +retry: +#endif if (IS_ERR(dentry)) return dentry; if (unlikely(!d_in_lookup(dentry))) { @@ -1798,9 +1923,14 @@ static struct dentry *__lookup_slow(const struct qstr *name, } } #ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - dput(dentry); - return ERR_PTR(-ENOENT); + if (is_nd_flags_lookup_last && !found_sus_path) { + if (dentry && !IS_ERR(dentry) && dentry->d_inode) { + if (susfs_is_inode_sus_path(dentry->d_inode)) { + dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &sus_wq); + found_sus_path = true; + goto retry; + } + } } #endif return dentry; @@ -1935,11 +2065,17 @@ static int walk_component(struct nameidata *nd, int flags) if (unlikely(err <= 0)) { if (err < 0) return err; + if (unlikely(!path.dentry)) { +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (nd->state & ND_STATE_LOOKUP_LAST) { + nd->flags |= ND_FLAGS_LOOKUP_LAST; + } +#endif path.dentry = lookup_slow(&nd->last, nd->path.dentry, nd->flags); if (IS_ERR(path.dentry)) return PTR_ERR(path.dentry); - + } path.mnt = nd->path.mnt; err = follow_managed(&path, nd); if (unlikely(err < 0)) @@ -2208,10 +2344,20 @@ static int link_path_walk(const char *name, struct nameidata *nd) for(;;) { u64 hash_len; int type; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct dentry *dentry; +#endif err = may_lookup(nd); if (err) return err; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + dentry = nd->path.dentry; + if (dentry->d_inode && susfs_is_inode_sus_path(dentry->d_inode)) { + // return -ENOENT here since it is walking the sub path of sus path + return -ENOENT; + } +#endif hash_len = hash_name(nd->path.dentry, name); @@ -2237,6 +2383,23 @@ static int link_path_walk(const char *name, struct nameidata *nd) hash_len = this.hash_len; name = this.name; } +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (nd->state & ND_STATE_LAST_SDCARD_SUS_PATH) { + // return -ENOENT here since it is walking the sub path of sus sdcard path + return -ENOENT; + } + if (parent->d_inode) { + if (susfs_is_base_dentry_android_data_dir(parent) && + susfs_is_sus_android_data_d_name_found(name)) + { + nd->state |= ND_STATE_LAST_SDCARD_SUS_PATH; + } else if (susfs_is_base_dentry_sdcard_dir(parent) && + susfs_is_sus_sdcard_d_name_found(name)) + { + nd->state |= ND_STATE_LAST_SDCARD_SUS_PATH; + } + } +#endif } nd->last.hash_len = hash_len; @@ -2293,12 +2456,6 @@ static int link_path_walk(const char *name, struct nameidata *nd) } return -ENOTDIR; } -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - // we deal with sus sub path here - if (nd->inode && unlikely(nd->inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - return 0; - } -#endif } } @@ -2402,7 +2559,9 @@ static inline int lookup_last(struct nameidata *nd) { if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len]) nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; - +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + nd->state |= ND_STATE_LOOKUP_LAST; +#endif nd->flags &= ~LOOKUP_PARENT; return walk_component(nd, 0); } @@ -2488,12 +2647,6 @@ static int filename_lookup(int dfd, struct filename *name, unsigned flags, if (likely(!retval)) audit_inode(name, path->dentry, flags & LOOKUP_PARENT); restore_nameidata(); -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (!retval && path->dentry->d_inode && unlikely(path->dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - putname(name); - return -ENOENT; - } -#endif putname(name); return retval; } @@ -2975,11 +3128,6 @@ static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *vi return error; if (IS_APPEND(dir)) return -EPERM; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - return -ENOENT; - } -#endif if (check_sticky(dir, inode) || IS_APPEND(inode) || IS_IMMUTABLE(inode) || IS_SWAPFILE(inode) || HAS_UNMAPPED_ID(inode)) @@ -3009,20 +3157,8 @@ static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *vi */ static inline int may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child) { -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - int error; -#endif struct user_namespace *s_user_ns; audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (child->d_inode && unlikely(child->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - error = inode_permission(dir, MAY_WRITE | MAY_EXEC); - if (error) { - return error; - } - return -ENOENT; - } -#endif if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) @@ -3152,11 +3288,6 @@ static int may_open(const struct path *path, int acc_mode, int flag) if (!inode) return -ENOENT; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - return -ENOENT; - } -#endif switch (inode->i_mode & S_IFMT) { case S_IFLNK: @@ -3229,20 +3360,7 @@ static inline int open_to_namei_flags(int flag) static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t mode) { struct user_namespace *s_user_ns; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - int error; - - if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC); - if (error) { - return error; - } - return -ENOENT; - } - error = security_path_mknod(dir, dentry, mode, 0); -#else int error = security_path_mknod(dir, dentry, mode, 0); -#endif if (error) return error; @@ -3355,15 +3473,53 @@ static int lookup_open(struct nameidata *nd, struct path *path, int error, create_error = 0; umode_t mode = op->mode; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); - +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + bool found_sus_path = false; + bool is_nd_state_open_last = (nd->state & ND_STATE_OPEN_LAST); +#endif if (unlikely(IS_DEADDIR(dir_inode))) return -ENOENT; file->f_mode &= ~FMODE_CREATED; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (is_nd_state_open_last) { + if (susfs_is_base_dentry_android_data_dir(dir) && + susfs_is_sus_android_data_d_name_found(nd->last.name)) + { + dentry = d_lookup(dir, &susfs_fake_qstr_name); + found_sus_path = true; + goto skip_orig_flow1; + } else if (susfs_is_base_dentry_sdcard_dir(dir) && + susfs_is_sus_sdcard_d_name_found(nd->last.name)) + { + dentry = d_lookup(dir, &susfs_fake_qstr_name); + found_sus_path = true; + goto skip_orig_flow1; + } + } +#endif dentry = d_lookup(dir, &nd->last); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (is_nd_state_open_last && dentry && !IS_ERR(dentry) && dentry->d_inode) { + if (susfs_is_inode_sus_path(dentry->d_inode)) { + dentry = d_lookup(dir, &susfs_fake_qstr_name); + found_sus_path = true; + } + } +skip_orig_flow1: +#endif for (;;) { if (!dentry) { +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (found_sus_path) { + dentry = d_alloc_parallel(dir, &susfs_fake_qstr_name, &wq); + goto skip_orig_flow2; + } +#endif dentry = d_alloc_parallel(dir, &nd->last, &wq); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH +skip_orig_flow2: +#endif if (IS_ERR(dentry)) return PTR_ERR(dentry); } @@ -3381,12 +3537,6 @@ static int lookup_open(struct nameidata *nd, struct path *path, } if (dentry->d_inode) { /* Cached positive dentry: will open in f_op->open */ -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - dput(dentry); - return -ENOENT; - } -#endif goto out_no_open; } @@ -3428,19 +3578,10 @@ static int lookup_open(struct nameidata *nd, struct path *path, if (dir_inode->i_op->atomic_open) { error = atomic_open(nd, dentry, path, file, op, open_flag, mode); - if (unlikely(error == -ENOENT) && create_error) + if (unlikely(error == -ENOENT) && create_error){ error = create_error; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - if (create_error) { - dput(dentry); - return create_error; - } - dput(dentry); - return -ENOENT; + return error; } -#endif - return error; } no_open: @@ -3455,12 +3596,6 @@ static int lookup_open(struct nameidata *nd, struct path *path, } dput(dentry); dentry = res; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { - dput(dentry); - return -ENOENT; - } -#endif } } diff --git a/fs/namespace.c b/fs/namespace.c index e5b65e449b1a..26ffe54ef326 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -40,7 +40,6 @@ extern bool susfs_is_current_zygote_domain(void); static DEFINE_IDA(susfs_mnt_id_ida); static DEFINE_IDA(susfs_mnt_group_ida); -#define CL_ZYGOTE_COPY_MNT_NS BIT(24) /* used by copy_mnt_ns() */ #define CL_COPY_MNT_NS BIT(25) /* used by copy_mnt_ns() */ #endif @@ -1047,6 +1046,12 @@ struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { struct mount *mnt; +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + struct mount *m; + struct mnt_namespace *mnt_ns; + int mnt_id; +#endif + struct dentry *root; if (!type) @@ -1090,10 +1095,24 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void mnt->mnt_parent = mnt; #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT - // If caller process is zygote, then it is a normal mount, so we just reorder the mnt_id + // - If caller process is zygote, then it is a normal mount, so we calculate the next available + // fake mnt_id for this mount if (susfs_is_current_zygote_domain()) { - mnt->mnt.susfs_mnt_id_backup = mnt->mnt_id; - mnt->mnt_id = current->susfs_last_fake_mnt_id++; + mnt_ns = current->nsproxy->mnt_ns; + if (mnt_ns) { + get_mnt_ns(mnt_ns); + rcu_read_lock(); + mnt_id = list_first_entry(&mnt_ns->list, struct mount, mnt_list)->mnt_id; + list_for_each_entry_rcu(m, &mnt_ns->list, mnt_list) { + if (m->mnt_id < DEFAULT_SUS_MNT_ID) { + mnt_id++; + } + } + WRITE_ONCE(mnt->mnt.susfs_mnt_id_backup, READ_ONCE(mnt->mnt_id)); + WRITE_ONCE(mnt->mnt_id, READ_ONCE(mnt_id)); + rcu_read_unlock(); + put_mnt_ns(mnt_ns); + } } #endif @@ -1127,16 +1146,21 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, int err; #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + struct mount *m; + struct mnt_namespace *mnt_ns; + int mnt_id; bool is_current_ksu_domain = susfs_is_current_ksu_domain(); bool is_current_zygote_domain = susfs_is_current_zygote_domain(); - /* - It is very important that we need to use CL_COPY_MNT_NS to identify whether + /* - It is very important that we need to use CL_COPY_MNT_NS to identify whether * the clone is a copy_tree() or single mount like called by __do_loopback() * - if caller process is KSU, consider the following situation: * 1. it is NOT doing unshare => call alloc_vfsmnt() to assign a new sus mnt_id * 2. it is doing unshare => spoof the new mnt_id with the old mnt_id - * - If caller process is zygote and old mnt_id is sus => call alloc_vfsmnt() to assign a new sus mnt_id - * - For the rest of caller process that doing unshare => call alloc_vfsmnt() to assign a new sus mnt_id only for old sus mount + * - For the rest of caller process with sus old->mnt_id => call alloc_vfsmnt() to assign a new sus mnt_id + * - Important notes: Here we can't determine whether the unshare is called by zygisk or not, + * so we can only patch out the unshare code in zygisk source code for now, + * but at least we can deal with old sus mounts using alloc_vfsmnt() */ // Firstly, check if it is KSU process if (unlikely(is_current_ksu_domain)) { @@ -1152,18 +1176,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, } goto bypass_orig_flow; } - // Secondly, check if it is zygote process and no matter it is doing unshare or not - if (likely(is_current_zygote_domain) && (old->mnt_id >= DEFAULT_SUS_MNT_ID)) { - /* Important Note: - * - Here we can't determine whether the unshare is called zygisk or not, - * so we can only patch out the unshare code in zygisk source code for now - * - But at least we can deal with old sus mounts using alloc_vfsmnt() - */ - mnt = alloc_vfsmnt(old->mnt_devname, true, 0); - goto bypass_orig_flow; - } - // Lastly, for other process that is doing unshare operation, but only deal with old sus mount - if ((flag & CL_COPY_MNT_NS) && (old->mnt_id >= DEFAULT_SUS_MNT_ID)) { + // Lastly, just check if old->mnt_id is sus + if (old->mnt_id >= DEFAULT_SUS_MNT_ID) { mnt = alloc_vfsmnt(old->mnt_devname, true, 0); goto bypass_orig_flow; } @@ -1226,9 +1240,27 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT // If caller process is zygote and not doing unshare, so we just reorder the mnt_id - if (likely(is_current_zygote_domain) && !(flag & CL_ZYGOTE_COPY_MNT_NS)) { - mnt->mnt.susfs_mnt_id_backup = mnt->mnt_id; - mnt->mnt_id = current->susfs_last_fake_mnt_id++; + // - If caller process is zygote, then it is a normal mount, so we calculate the next available + // fake mnt_id for this mount, but there is one situation that the previous clone_mnt is not + // yet attached to the current mnt_ns during copy_tree() so that it will fail to calculate + // the correct fake mnt_id. + // - Currently we have a tmep fix for this in copy_tree(), but maybe not reliable for other devices + if (likely(is_current_zygote_domain) && !(flag & CL_COPY_MNT_NS)) { + mnt_ns = current->nsproxy->mnt_ns; + if (mnt_ns) { + rcu_read_lock(); + get_mnt_ns(mnt_ns); + mnt_id = list_first_entry(&mnt_ns->list, struct mount, mnt_list)->mnt_id; + list_for_each_entry_rcu(m, &mnt_ns->list, mnt_list) { + if (m->mnt_id < DEFAULT_SUS_MNT_ID) { + mnt_id++; + } + } + WRITE_ONCE(mnt->mnt.susfs_mnt_id_backup, READ_ONCE(mnt->mnt_id)); + WRITE_ONCE(mnt->mnt_id, READ_ONCE(mnt_id)); + rcu_read_unlock(); + put_mnt_ns(mnt_ns); + } } #endif @@ -1817,35 +1849,6 @@ static inline bool may_mandlock(void) } #endif -static int can_umount(const struct path *path, int flags) -{ - struct mount *mnt = real_mount(path->mnt); - if (!may_mount()) - return -EPERM; - if (path->dentry != path->mnt->mnt_root) - return -EINVAL; - if (!check_mnt(mnt)) - return -EINVAL; - if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */ - return -EINVAL; - if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) - return -EPERM; - return 0; -} -// caller is responsible for flags being sane -int path_umount(struct path *path, int flags) -{ - struct mount *mnt = real_mount(path->mnt); - int ret; - ret = can_umount(path, flags); - if (!ret) - ret = do_umount(mnt, flags); - /* we mustn't call path_put() as that would clear mnt_expiry_mark */ - dput(path->dentry); - mntput_no_expire(mnt); - return ret; -} - /* * Now umount can handle mount points as well as block devices. * This is important for filesystems which use unnamed block devices. @@ -1941,6 +1944,9 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, int flag) { struct mount *res, *p, *q, *r, *parent; + #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + bool is_current_zygote_domain = susfs_is_current_zygote_domain(); + #endif if (!(flag & CL_COPY_UNBINDABLE) && IS_MNT_UNBINDABLE(mnt)) return ERR_PTR(-EINVAL); @@ -1957,6 +1963,10 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, p = mnt; list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { struct mount *s; + #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + int attach_mnt_count = 0; + #endif + if (!is_subdir(r->mnt_mountpoint, dentry)) continue; @@ -1989,6 +1999,15 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, lock_mount_hash(); list_add_tail(&q->mnt_list, &res->mnt_list); attach_mnt(q, parent, p->mnt_mp); + #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + if (is_current_zygote_domain && + !(flag & CL_COPY_MNT_NS) && + q->mnt_id < DEFAULT_SUS_MNT_ID) + { + attach_mnt_count++; + q->mnt_id += attach_mnt_count; + } + #endif unlock_mount_hash(); } } @@ -3183,10 +3202,6 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT // Always let clone_mnt() in copy_tree() know it is from copy_mnt_ns() copy_flags |= CL_COPY_MNT_NS; - if (is_zygote_pid) { - // Let clone_mnt() in copy_tree() know copy_mnt_ns() is run by zygote process - copy_flags |= CL_ZYGOTE_COPY_MNT_NS; - } #endif new = copy_tree(old, old->mnt.mnt_root, copy_flags); @@ -3226,11 +3241,10 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, p = next_mnt(p, old); } #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT - // current->susfs_last_fake_mnt_id -> to record last valid fake mnt_id to zygote pid // q->mnt.susfs_mnt_id_backup -> original mnt_id // q->mnt_id -> will be modified to the fake mnt_id - // Here We are only interested in processes of which original mnt namespace belongs to zygote + // Here We are only interested in processes of which original mnt namespace belongs to zygote // Also we just make use of existing 'q' mount pointer, no need to delcare extra mount pointer if (is_zygote_pid) { last_entry_mnt_id = list_first_entry(&new_ns->list, struct mount, mnt_list)->mnt_id; @@ -3242,10 +3256,6 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, q->mnt_id = last_entry_mnt_id++; } } - // Assign the 'last_entry_mnt_id' to 'current->susfs_last_fake_mnt_id' for later use. - // should be fine here assuming zygote is forking/unsharing app in one single thread. - // Or should we put a lock here? - current->susfs_last_fake_mnt_id = last_entry_mnt_id; #endif namespace_unlock(); diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c index d6a1eab90e37..f233b1c9e6d5 100644 --- a/fs/notify/fdinfo.c +++ b/fs/notify/fdinfo.c @@ -102,7 +102,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) inode = igrab(fsnotify_conn_inode(mark->connector)); if (inode) { #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && + if (likely(susfs_is_current_non_root_user_app_proc()) && unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) { struct path path; char *pathname = kmalloc(PAGE_SIZE, GFP_KERNEL); diff --git a/fs/open.c b/fs/open.c index 3159a9570368..de9b720fe298 100644 --- a/fs/open.c +++ b/fs/open.c @@ -353,6 +353,209 @@ extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int int *flags); #endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool susfs_is_sus_su_hooks_enabled __read_mostly; +extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, + int *flags); +#endif + /* * access() needs to use the real uid/gid, not the effective uid/gid. * We do this by temporarily clearing all FS-related capabilities and @@ -372,6 +575,180 @@ long do_faccessat(int dfd, const char __user *filename, int mode) ksu_handle_faccessat(&dfd, &filename, &mode, NULL); #endif +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (likely(susfs_is_sus_su_hooks_enabled)) { + ksu_handle_faccessat(&dfd, &filename, &mode, NULL); + } +#endif + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 3cbe85f8add2..b6543c9fad11 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -61,7 +61,7 @@ static int seq_show(struct seq_file *m, void *v) #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT mnt = real_mount(file->f_path.mnt); - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && + if (likely(current->susfs_task_state & TIF_NON_ROOT_USER_APP_PROC) && mnt->mnt_id >= DEFAULT_SUS_MNT_ID) { for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) { } } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index fb46ebd7e767..dfe3379685a4 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -24,6 +24,10 @@ #include #endif +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT +#include +#endif + #include #include #include diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 3dfa54a6dcb9..d7c344505751 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c @@ -23,6 +23,7 @@ #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT extern bool susfs_is_current_ksu_domain(void); +bool susfs_hide_sus_mnts_for_all_procs = true; // hide sus mounts for all processes by default #endif static __poll_t mounts_poll(struct file *file, poll_table *wait) @@ -110,7 +111,8 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt) int err; #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT - if (unlikely((r->mnt_id >= DEFAULT_SUS_MNT_ID) && !susfs_is_current_ksu_domain())) + if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID) && + (susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain())) return 0; #endif @@ -151,7 +153,8 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) int err; #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT - if (unlikely((r->mnt_id >= DEFAULT_SUS_MNT_ID) && !susfs_is_current_ksu_domain())) + if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID) && + (susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain())) return 0; #endif @@ -220,7 +223,8 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt) int err; #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT - if (unlikely((r->mnt_id >= DEFAULT_SUS_MNT_ID) && !susfs_is_current_ksu_domain())) + if (unlikely(r->mnt_id >= DEFAULT_SUS_MNT_ID) && + (susfs_hide_sus_mnts_for_all_procs || !susfs_is_current_ksu_domain())) return 0; #endif diff --git a/fs/readdir.c b/fs/readdir.c index dd82d352cb17..738834a3bb2f 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -20,15 +20,18 @@ #include #include #include -#ifdef CONFIG_KSU_SUSFS_SUS_PATH -#include -#endif #include #ifdef CONFIG_KSU_SUSFS_SUS_PATH -extern int susfs_sus_ino_for_filldir64(unsigned long ino); +#include +extern bool susfs_is_inode_sus_path(struct inode *inode); +extern bool susfs_is_sus_android_data_d_name_found(const char *d_name); +extern bool susfs_is_sus_sdcard_d_name_found(const char *d_name); +extern bool susfs_is_base_dentry_android_data_dir(struct dentry* base); +extern bool susfs_is_base_dentry_sdcard_dir(struct dentry* base); #endif + int iterate_dir(struct file *file, struct dir_context *ctx) { struct inode *inode = file_inode(file); @@ -125,6 +128,11 @@ struct old_linux_dirent { struct readdir_callback { struct dir_context ctx; struct old_linux_dirent __user * dirent; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct super_block *sb; + bool is_base_dentry_android_data_root_dir; + bool is_base_dentry_sdcard_root_dir; +#endif int result; }; @@ -135,6 +143,9 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen, container_of(ctx, struct readdir_callback, ctx); struct old_linux_dirent __user * dirent; unsigned long d_ino; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif if (buf->result) return -EINVAL; @@ -146,6 +157,28 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen, buf->result = -EOVERFLOW; return -EOVERFLOW; } +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (buf->is_base_dentry_android_data_root_dir) { + if (susfs_is_sus_android_data_d_name_found(name)) { + return true; + } + } else if (buf->is_base_dentry_sdcard_root_dir) { + if (susfs_is_sus_sdcard_d_name_found(name)) { + return true; + } + } + + inode = ilookup(buf->sb, ino); + if (!inode) { + goto orig_flow; + } + if (susfs_is_inode_sus_path(inode)) { + iput(inode); + return true; + } + iput(inode); +orig_flow: +#endif buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -173,10 +206,35 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd, .ctx.actor = fillonedir, .dirent = dirent }; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif if (!f.file) return -EBADF; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + buf.sb = f.file->f_inode->i_sb; + inode = f.file->f_path.dentry->d_inode; + if (f.file->f_path.dentry && inode) { + if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_android_data_root_dir = true; + buf.is_base_dentry_sdcard_root_dir = false; + goto orig_flow; + } + if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_sdcard_root_dir = true; + buf.is_base_dentry_android_data_root_dir = false; + goto orig_flow; + } + } + buf.is_base_dentry_android_data_root_dir = false; + buf.is_base_dentry_sdcard_root_dir = false; +orig_flow: +#endif + error = iterate_dir(f.file, &buf.ctx); if (buf.result) error = buf.result; @@ -201,6 +259,11 @@ struct linux_dirent { struct getdents_callback { struct dir_context ctx; struct linux_dirent __user * current_dir; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct super_block *sb; + bool is_base_dentry_android_data_root_dir; + bool is_base_dentry_sdcard_root_dir; +#endif struct linux_dirent __user * previous; int count; int error; @@ -217,9 +280,7 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, sizeof(long)); #ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && susfs_sus_ino_for_filldir64(ino)) { - return 0; - } + struct inode *inode; #endif buf->error = verify_dirent_name(name, namlen); if (unlikely(buf->error)) @@ -239,6 +300,29 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, if (__put_user(offset, &dirent->d_off)) goto efault; } + +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (buf->is_base_dentry_android_data_root_dir) { + if (susfs_is_sus_android_data_d_name_found(name)) { + return true; + } + } else if (buf->is_base_dentry_sdcard_root_dir) { + if (susfs_is_sus_sdcard_d_name_found(name)) { + return true; + } + } + + inode = ilookup(buf->sb, ino); + if (!inode) { + goto orig_flow; + } + if (susfs_is_inode_sus_path(inode)) { + iput(inode); + return true; + } + iput(inode); +orig_flow: +#endif dirent = buf->current_dir; if (__put_user(d_ino, &dirent->d_ino)) goto efault; @@ -271,10 +355,35 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, .current_dir = dirent }; int error; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif if (!access_ok(VERIFY_WRITE, dirent, count)) return -EFAULT; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + buf.sb = f.file->f_inode->i_sb; + inode = f.file->f_path.dentry->d_inode; + if (f.file->f_path.dentry && inode) { + if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_android_data_root_dir = true; + buf.is_base_dentry_sdcard_root_dir = false; + goto orig_flow; + } + if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_sdcard_root_dir = true; + buf.is_base_dentry_android_data_root_dir = false; + goto orig_flow; + } + } + buf.is_base_dentry_android_data_root_dir = false; + buf.is_base_dentry_sdcard_root_dir = false; +orig_flow: +#endif + f = fdget_pos(fd); if (!f.file) return -EBADF; @@ -296,6 +405,11 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, struct getdents_callback64 { struct dir_context ctx; struct linux_dirent64 __user * current_dir; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct super_block *sb; + bool is_base_dentry_android_data_root_dir; + bool is_base_dentry_sdcard_root_dir; +#endif struct linux_dirent64 __user * previous; int count; int error; @@ -311,9 +425,7 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, sizeof(u64)); #ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && susfs_sus_ino_for_filldir64(ino)) { - return 0; - } + struct inode *inode; #endif buf->error = verify_dirent_name(name, namlen); if (unlikely(buf->error)) @@ -328,6 +440,29 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, if (__put_user(offset, &dirent->d_off)) goto efault; } + +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (buf->is_base_dentry_android_data_root_dir) { + if (susfs_is_sus_android_data_d_name_found(name)) { + return true; + } + } else if (buf->is_base_dentry_sdcard_root_dir) { + if (susfs_is_sus_sdcard_d_name_found(name)) { + return true; + } + } + + inode = ilookup(buf->sb, ino); + if (!inode) { + goto orig_flow; + } + if (susfs_is_inode_sus_path(inode)) { + iput(inode); + return true; + } + iput(inode); +orig_flow: +#endif dirent = buf->current_dir; if (__put_user(ino, &dirent->d_ino)) goto efault; @@ -362,6 +497,9 @@ int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, .current_dir = dirent }; int error; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif if (!access_ok(VERIFY_WRITE, dirent, count)) return -EFAULT; @@ -370,6 +508,27 @@ int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, if (!f.file) return -EBADF; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + buf.sb = f.file->f_inode->i_sb; + inode = f.file->f_path.dentry->d_inode; + if (f.file->f_path.dentry && inode) { + if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_android_data_root_dir = true; + buf.is_base_dentry_sdcard_root_dir = false; + goto orig_flow; + } + if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_sdcard_root_dir = true; + buf.is_base_dentry_android_data_root_dir = false; + goto orig_flow; + } + } + buf.is_base_dentry_android_data_root_dir = false; + buf.is_base_dentry_sdcard_root_dir = false; +orig_flow: +#endif error = iterate_dir(f.file, &buf.ctx); if (error >= 0) error = buf.error; @@ -403,6 +562,11 @@ struct compat_old_linux_dirent { struct compat_readdir_callback { struct dir_context ctx; struct compat_old_linux_dirent __user *dirent; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct super_block *sb; + bool is_base_dentry_android_data_root_dir; + bool is_base_dentry_sdcard_root_dir; +#endif int result; }; @@ -415,13 +579,12 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name, struct compat_old_linux_dirent __user *dirent; compat_ulong_t d_ino; - if (buf->result) - return -EINVAL; #ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && susfs_sus_ino_for_filldir64(ino)) { - return 0; - } + struct inode *inode; #endif + + if (buf->result) + return -EINVAL; buf->result = verify_dirent_name(name, namlen); if (buf->result < 0) return buf->result; @@ -430,6 +593,29 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name, buf->result = -EOVERFLOW; return -EOVERFLOW; } + +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (buf->is_base_dentry_android_data_root_dir) { + if (susfs_is_sus_android_data_d_name_found(name)) { + return true; + } + } else if (buf->is_base_dentry_sdcard_root_dir) { + if (susfs_is_sus_sdcard_d_name_found(name)) { + return true; + } + } + + inode = ilookup(buf->sb, ino); + if (!inode) { + goto orig_flow; + } + if (susfs_is_inode_sus_path(inode)) { + iput(inode); + return true; + } + iput(inode); +orig_flow: +#endif buf->result++; dirent = buf->dirent; if (!access_ok(VERIFY_WRITE, dirent, @@ -457,10 +643,34 @@ COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd, .ctx.actor = compat_fillonedir, .dirent = dirent }; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif if (!f.file) return -EBADF; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + buf.sb = f.file->f_inode->i_sb; + inode = f.file->f_path.dentry->d_inode; + if (f.file->f_path.dentry && inode) { + if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_android_data_root_dir = true; + buf.is_base_dentry_sdcard_root_dir = false; + goto orig_flow; + } + if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_sdcard_root_dir = true; + buf.is_base_dentry_android_data_root_dir = false; + goto orig_flow; + } + } + buf.is_base_dentry_android_data_root_dir = false; + buf.is_base_dentry_sdcard_root_dir = false; +orig_flow: +#endif error = iterate_dir(f.file, &buf.ctx); if (buf.result) error = buf.result; @@ -479,6 +689,11 @@ struct compat_linux_dirent { struct compat_getdents_callback { struct dir_context ctx; struct compat_linux_dirent __user *current_dir; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct super_block *sb; + bool is_base_dentry_android_data_root_dir; + bool is_base_dentry_sdcard_root_dir; +#endif struct compat_linux_dirent __user *previous; int count; int error; @@ -494,14 +709,12 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen, int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) + namlen + 2, sizeof(compat_long_t)); +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; -#ifdef CONFIG_KSU_SUSFS_SUS_PATH - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && susfs_sus_ino_for_filldir64(ino)) { - return 0; - } -#endif d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->error = -EOVERFLOW; @@ -514,6 +727,29 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen, if (__put_user(offset, &dirent->d_off)) goto efault; } + +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (buf->is_base_dentry_android_data_root_dir) { + if (susfs_is_sus_android_data_d_name_found(name)) { + return true; + } + } else if (buf->is_base_dentry_sdcard_root_dir) { + if (susfs_is_sus_sdcard_d_name_found(name)) { + return true; + } + } + + inode = ilookup(buf->sb, ino); + if (!inode) { + goto orig_flow; + } + if (susfs_is_inode_sus_path(inode)) { + iput(inode); + return true; + } + iput(inode); +orig_flow: +#endif dirent = buf->current_dir; if (__put_user(d_ino, &dirent->d_ino)) goto efault; @@ -546,6 +782,9 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd, .count = count }; int error; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + struct inode *inode; +#endif if (!access_ok(VERIFY_WRITE, dirent, count)) return -EFAULT; @@ -554,6 +793,27 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd, if (!f.file) return -EBADF; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + buf.sb = f.file->f_inode->i_sb; + inode = f.file->f_path.dentry->d_inode; + if (f.file->f_path.dentry && inode) { + if (susfs_is_base_dentry_android_data_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_android_data_root_dir = true; + buf.is_base_dentry_sdcard_root_dir = false; + goto orig_flow; + } + if (susfs_is_base_dentry_sdcard_dir(f.file->f_path.dentry)) + { + buf.is_base_dentry_sdcard_root_dir = true; + buf.is_base_dentry_android_data_root_dir = false; + goto orig_flow; + } + } + buf.is_base_dentry_android_data_root_dir = false; + buf.is_base_dentry_sdcard_root_dir = false; +orig_flow: +#endif error = iterate_dir(f.file, &buf.ctx); if (error >= 0) error = buf.error; diff --git a/fs/stat.c b/fs/stat.c index 62a2d72de565..484bdeeb851b 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -24,6 +24,9 @@ #include #include +#include "internal.h" +#include "mount.h" + #ifdef CONFIG_KSU_SUSFS_SUS_KSTAT extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat); #endif @@ -40,7 +43,7 @@ extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat * void generic_fillattr(struct inode *inode, struct kstat *stat) { #ifdef CONFIG_KSU_SUSFS_SUS_KSTAT - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && + if (likely(susfs_is_current_non_root_user_app_proc()) && unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) { susfs_sus_ino_for_generic_fillattr(inode->i_ino, stat); stat->mode = inode->i_mode; @@ -166,10 +169,6 @@ int vfs_statx_fd(unsigned int fd, struct kstat *stat, } EXPORT_SYMBOL(vfs_statx_fd); -#ifdef CONFIG_KSU -extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags); -#endif - /** * vfs_statx - Get basic and extra attributes by filename * @dfd: A file descriptor representing the base dir for a relative filename @@ -192,10 +191,11 @@ int vfs_statx(int dfd, const char __user *filename, int flags, int error = -EINVAL; unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT; -#ifdef CONFIG_KSU - ksu_handle_stat(&dfd, &filename, &flags); +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + struct mount *mnt; #endif + if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0) return -EINVAL; @@ -213,7 +213,15 @@ int vfs_statx(int dfd, const char __user *filename, int flags, goto out; error = vfs_getattr(&path, stat, request_mask, flags); +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + mnt = real_mount(path.mnt); + if (likely(susfs_is_current_non_root_user_app_proc())) { + for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) {} + } + stat->mnt_id = mnt->mnt_id; +#else path_put(&path); +#endif if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; diff --git a/fs/statfs.c b/fs/statfs.c index e65f977f6f91..8311dcd09a39 100644 --- a/fs/statfs.c +++ b/fs/statfs.c @@ -78,7 +78,7 @@ int vfs_statfs(const struct path *path, struct kstatfs *buf) struct mount *mnt; mnt = real_mount(path->mnt); - if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { + if (likely(susfs_is_current_non_root_user_app_proc())) { for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) {} } error = statfs_by_dentry(mnt->mnt.mnt_root, buf); @@ -109,22 +109,6 @@ int user_statfs(const char __user *pathname, struct kstatfs *st) goto retry; } } -#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS - /* - When mounting overlay, the f_flags are set with 'ro' and 'relatime', - * but this is an abnormal status, as when we inspect the output from mountinfo, - * we will find that all partitions set with 'ro' will have 'noatime' set as well. - * - But what is strange here is that the vfsmnt f_flags of the lowest layer has corrent f_flags set, - * and still it is always changed to 'relatime' instead of 'noatime' for the final result, - * I can't think of any other reason to explain about this, maybe the f_flags is set by its own - * filesystem implementation but not the one from overlayfs. - * - Anyway we just cannot use the retrieved f_flags from ovl_getattr() of overlayfs, - * we need to run one more check for user_statfs() and fd_statfs() by ourselves. - */ - if (unlikely((st->f_flags & ST_RDONLY) && (st->f_flags & ST_RELATIME))) { - st->f_flags &= ~ST_RELATIME; - st->f_flags |= ST_NOATIME; - } -#endif return error; } @@ -136,12 +120,6 @@ int fd_statfs(int fd, struct kstatfs *st) error = vfs_statfs(&f.file->f_path, st); fdput(f); } -#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS - if (unlikely((st->f_flags & ST_RDONLY) && (st->f_flags & ST_RELATIME))) { - st->f_flags &= ~ST_RELATIME; - st->f_flags |= ST_NOATIME; - } -#endif return error; } diff --git a/fs/susfs.c b/fs/susfs.c index 2d9576899da5..b24ffddefcb0 100644 --- a/fs/susfs.c +++ b/fs/susfs.c @@ -34,107 +34,302 @@ bool susfs_is_log_enabled __read_mostly = true; /* sus_path */ #ifdef CONFIG_KSU_SUSFS_SUS_PATH -static DEFINE_HASHTABLE(SUS_PATH_HLIST, 10); -static int susfs_update_sus_path_inode(char *target_pathname) { - struct path p; +static LIST_HEAD(LH_SUS_PATH_ANDROID_DATA); +static LIST_HEAD(LH_SUS_PATH_SDCARD); +static struct st_android_data_path android_data_path = {0}; +static struct st_sdcard_path sdcard_path = {0}; +#define NON_EXISTED_FILENAME "..!5!u!S!" // used to re-test the dcache lookup, make sure you don't have file named like this!! +const struct qstr susfs_fake_qstr_name = QSTR_INIT(NON_EXISTED_FILENAME, strlen(NON_EXISTED_FILENAME)); + +int susfs_set_i_state_on_external_dir(char __user* user_info, int cmd) { + struct path path; + int err = 0; struct inode *inode = NULL; - const char *dev_type; + char *info = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL); + char *tmp_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + char *resolved_pathname = NULL; - if (kern_path(target_pathname, LOOKUP_FOLLOW, &p)) { - SUSFS_LOGE("Failed opening file '%s'\n", target_pathname); - return 1; + if (!info) { + err = -ENOMEM; + return err; } - // - We don't allow paths of which filesystem type is "tmpfs" or "fuse". - // For tmpfs, because its starting inode->i_ino will begin with 1 again, - // so it will cause wrong comparison in function susfs_sus_ino_for_filldir64() - // For fuse, which is almost storage related, sus_path should not handle any paths of - // which filesystem is "fuse" as well, since app can write to "fuse" and lookup files via - // like binder / system API (you can see the uid is changed to 1000)/ - // - so sus_path should be applied only on read-only filesystem like "erofs" or "f2fs", but not "tmpfs" or "fuse", - // people may rely on HMA for /data isolation instead. - dev_type = p.mnt->mnt_sb->s_type->name; - if (!strcmp(dev_type, "tmpfs") || - !strcmp(dev_type, "fuse")) { - SUSFS_LOGE("target_pathname: '%s' cannot be added since its filesystem type is '%s'\n", - target_pathname, dev_type); - path_put(&p); - return 1; + if (!tmp_buf) { + err = -ENOMEM; + goto out_kfree_info; } - inode = d_inode(p.dentry); - if (!inode) { - SUSFS_LOGE("inode is NULL\n"); - path_put(&p); - return 1; + err = strncpy_from_user(info, user_info, SUSFS_MAX_LEN_PATHNAME-1); + if (err < 0) { + SUSFS_LOGE("failed copying from userspace\n"); + goto out_kfree_tmp_buf; } - if (!(inode->i_state & INODE_STATE_SUS_PATH)) { - spin_lock(&inode->i_lock); - inode->i_state |= INODE_STATE_SUS_PATH; - spin_unlock(&inode->i_lock); + err = kern_path(info, LOOKUP_FOLLOW, &path); + if (err) { + SUSFS_LOGE("Failed opening file '%s'\n", info); + goto out_kfree_tmp_buf; } - path_put(&p); - return 0; + + resolved_pathname = d_path(&path, tmp_buf, PAGE_SIZE); + if (!resolved_pathname) { + err = -ENOMEM; + goto out_path_put_path; + } + + inode = d_inode(path.dentry); + if (!inode) { + err = -EINVAL; + goto out_path_put_path; + } + + if (cmd == CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH) { + strncpy(android_data_path.pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME-1); + android_data_path.i_ino = inode->i_ino; + android_data_path.s_magic = inode->i_sb->s_magic; + SUSFS_LOGI("Set android data root dir: '%s', ino: '%lu', magic: '%lu'\n", + android_data_path.pathname, android_data_path.i_ino, android_data_path.s_magic); + } else if (cmd == CMD_SUSFS_SET_SDCARD_ROOT_PATH) { + strncpy(sdcard_path.pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME-1); + sdcard_path.i_ino = inode->i_ino; + sdcard_path.s_magic = inode->i_sb->s_magic; + SUSFS_LOGI("Set sdcard root dir: '%s', ino: '%lu', magic: '%lu'\n", + sdcard_path.pathname, sdcard_path.i_ino, sdcard_path.s_magic); + } else { + err = -EINVAL; + } + +out_path_put_path: + path_put(&path); +out_kfree_tmp_buf: + kfree(tmp_buf); +out_kfree_info: + kfree(info); + return err; } int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info) { + struct st_susfs_sus_path_list *cursor = NULL, *temp = NULL; + struct st_susfs_sus_path_list *new_list = NULL; struct st_susfs_sus_path info; - struct st_susfs_sus_path_hlist *new_entry, *tmp_entry; - struct hlist_node *tmp_node; - int bkt; - bool update_hlist = false; + struct path path; + struct inode *inode = NULL; + char *resolved_pathname = NULL, *tmp_buf = NULL; + int err = 0; - if (copy_from_user(&info, user_info, sizeof(info))) { + err = copy_from_user(&info, user_info, sizeof(info)); + if (err) { SUSFS_LOGE("failed copying from userspace\n"); - return 1; + return err; } - spin_lock(&susfs_spin_lock); - hash_for_each_safe(SUS_PATH_HLIST, bkt, tmp_node, tmp_entry, node) { - if (!strcmp(tmp_entry->target_pathname, info.target_pathname)) { - hash_del(&tmp_entry->node); - kfree(tmp_entry); - update_hlist = true; - break; - } + err = kern_path(info.target_pathname, LOOKUP_FOLLOW, &path); + if (err) { + SUSFS_LOGE("Failed opening file '%s'\n", info.target_pathname); + return err; } - spin_unlock(&susfs_spin_lock); - new_entry = kmalloc(sizeof(struct st_susfs_sus_path_hlist), GFP_KERNEL); - if (!new_entry) { - SUSFS_LOGE("no enough memory\n"); - return 1; + if (!path.dentry->d_inode) { + err = -EINVAL; + goto out_path_put_path; } + inode = d_inode(path.dentry); - new_entry->target_ino = info.target_ino; - strncpy(new_entry->target_pathname, info.target_pathname, SUSFS_MAX_LEN_PATHNAME-1); - if (susfs_update_sus_path_inode(new_entry->target_pathname)) { - kfree(new_entry); - return 1; + tmp_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!tmp_buf) { + err = -ENOMEM; + goto out_path_put_path; } - spin_lock(&susfs_spin_lock); - hash_add(SUS_PATH_HLIST, &new_entry->node, info.target_ino); - if (update_hlist) { - SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s' is successfully updated to SUS_PATH_HLIST\n", - new_entry->target_ino, new_entry->target_pathname); - } else { - SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s' is successfully added to SUS_PATH_HLIST\n", - new_entry->target_ino, new_entry->target_pathname); + + resolved_pathname = d_path(&path, tmp_buf, PAGE_SIZE); + if (!resolved_pathname) { + err = -ENOMEM; + goto out_kfree_tmp_buf; } - spin_unlock(&susfs_spin_lock); - return 0; + + if (strstr(resolved_pathname, android_data_path.pathname)) { + if (android_data_path.i_ino == 0) { + err = -EINVAL; + SUSFS_LOGE("android_data_path is not configured yet, plz do like 'ksu_susfs set_android_data_root_path /sdcard/Android/data' first after your screen is unlocked\n"); + goto out_kfree_tmp_buf; + } + list_for_each_entry_safe(cursor, temp, &LH_SUS_PATH_ANDROID_DATA, list) { + if (unlikely(!strcmp(cursor->info.target_pathname, path.dentry->d_name.name))) { + spin_lock(&susfs_spin_lock); + cursor->info.target_ino = info.target_ino; + strncpy(cursor->info.target_pathname, path.dentry->d_name.name, SUSFS_MAX_LEN_PATHNAME - 1); + strncpy(cursor->target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1); + cursor->info.i_uid = info.i_uid; + cursor->path_len = strlen(cursor->info.target_pathname); + SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', i_uid: '%u', is successfully updated to LH_SUS_PATH_ANDROID_DATA\n", + cursor->info.target_ino, cursor->target_pathname, cursor->info.i_uid); + spin_unlock(&susfs_spin_lock); + goto out_kfree_tmp_buf; + } + } + new_list = kmalloc(sizeof(struct st_susfs_sus_path_list), GFP_KERNEL); + if (!new_list) { + err = -ENOMEM; + goto out_kfree_tmp_buf; + } + new_list->info.target_ino = info.target_ino; + strncpy(new_list->info.target_pathname, path.dentry->d_name.name, SUSFS_MAX_LEN_PATHNAME - 1); + strncpy(new_list->target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1); + new_list->info.i_uid = info.i_uid; + new_list->path_len = strlen(new_list->info.target_pathname); + INIT_LIST_HEAD(&new_list->list); + spin_lock(&susfs_spin_lock); + list_add_tail(&new_list->list, &LH_SUS_PATH_ANDROID_DATA); + SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', i_uid: '%u', is successfully added to LH_SUS_PATH_ANDROID_DATA\n", + new_list->info.target_ino, new_list->target_pathname, new_list->info.i_uid); + spin_unlock(&susfs_spin_lock); + goto out_kfree_tmp_buf; + } else if (strstr(resolved_pathname, sdcard_path.pathname)) { + if (sdcard_path.i_ino == 0) { + err = -EINVAL; + SUSFS_LOGE("sdcard_path is not configured yet, plz do like 'ksu_susfs set_sdcard_root_path /sdcard' first after your screen is unlocked\n"); + goto out_kfree_tmp_buf; + } + list_for_each_entry_safe(cursor, temp, &LH_SUS_PATH_SDCARD, list) { + if (unlikely(!strcmp(cursor->info.target_pathname, path.dentry->d_name.name))) { + spin_lock(&susfs_spin_lock); + cursor->info.target_ino = info.target_ino; + strncpy(cursor->info.target_pathname, path.dentry->d_name.name, SUSFS_MAX_LEN_PATHNAME - 1); + strncpy(cursor->target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1); + cursor->info.i_uid = info.i_uid; + cursor->path_len = strlen(cursor->info.target_pathname); + SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', i_uid: '%u', is successfully updated to LH_SUS_PATH_SDCARD\n", + cursor->info.target_ino, cursor->target_pathname, cursor->info.i_uid); + spin_unlock(&susfs_spin_lock); + goto out_kfree_tmp_buf; + } + } + new_list = kmalloc(sizeof(struct st_susfs_sus_path_list), GFP_KERNEL); + if (!new_list) { + err = -ENOMEM; + goto out_kfree_tmp_buf; + } + new_list->info.target_ino = info.target_ino; + strncpy(new_list->info.target_pathname, path.dentry->d_name.name, SUSFS_MAX_LEN_PATHNAME - 1); + strncpy(new_list->target_pathname, resolved_pathname, SUSFS_MAX_LEN_PATHNAME - 1); + new_list->info.i_uid = info.i_uid; + new_list->path_len = strlen(new_list->info.target_pathname); + INIT_LIST_HEAD(&new_list->list); + spin_lock(&susfs_spin_lock); + list_add_tail(&new_list->list, &LH_SUS_PATH_SDCARD); + SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', i_uid: '%u', is successfully added to LH_SUS_PATH_SDCARD\n", + new_list->info.target_ino, new_list->target_pathname, new_list->info.i_uid); + spin_unlock(&susfs_spin_lock); + goto out_kfree_tmp_buf; + } + + spin_lock(&inode->i_lock); + inode->i_state |= INODE_STATE_SUS_PATH; + SUSFS_LOGI("pathname: '%s', ino: '%lu', is flagged as INODE_STATE_SUS_PATH\n", resolved_pathname, info.target_ino); + spin_unlock(&inode->i_lock); +out_kfree_tmp_buf: + kfree(tmp_buf); +out_path_put_path: + path_put(&path); + return err; +} + +static inline bool is_i_uid_in_android_data_not_allowed(uid_t i_uid) { + return (likely(susfs_is_current_non_root_user_app_proc()) && + unlikely(current_uid().val != i_uid)); } -int susfs_sus_ino_for_filldir64(unsigned long ino) { - struct st_susfs_sus_path_hlist *entry; +static inline bool is_i_uid_in_sdcard_not_allowed(void) { + return (likely(susfs_is_current_non_root_user_app_proc())); +} - hash_for_each_possible(SUS_PATH_HLIST, entry, node, ino) { - if (entry->target_ino == ino) - return 1; +static inline bool is_i_uid_not_allowed(uid_t i_uid) { + return (likely(susfs_is_current_non_root_user_app_proc()) && + unlikely(current_uid().val != i_uid)); +} + +bool susfs_is_base_dentry_android_data_dir(struct dentry* base) { + return ((base->d_sb->s_magic == android_data_path.s_magic) && + (base->d_inode->i_ino == android_data_path.i_ino)); +} + +bool susfs_is_base_dentry_sdcard_dir(struct dentry* base) { + return ((base->d_sb->s_magic == sdcard_path.s_magic) && + (base->d_inode->i_ino == sdcard_path.i_ino)); +} + +bool susfs_is_sus_android_data_d_name_found(const char *d_name) { + struct st_susfs_sus_path_list *cursor = NULL, *temp = NULL; + + if (d_name[0] == '\0') { + return false; } - return 0; + + list_for_each_entry_safe(cursor, temp, &LH_SUS_PATH_ANDROID_DATA, list) { + // - we use strstr here because we cannot retrieve the dentry of fuse_dentry + // and attacker can still use path travesal attack to detect the path, but + // lucky we can check for the uid so it won't let them fool us + if (!strncmp(d_name, cursor->info.target_pathname, cursor->path_len) && + (d_name[cursor->path_len] == '\0' || d_name[cursor->path_len] == '/') && + is_i_uid_in_android_data_not_allowed(cursor->info.i_uid)) + { + SUSFS_LOGI("hiding path '%s'\n", cursor->target_pathname); + return true; + } + } + return false; +} + +bool susfs_is_sus_sdcard_d_name_found(const char *d_name) { + struct st_susfs_sus_path_list *cursor = NULL, *temp = NULL; + + if (d_name[0] == '\0') { + return false; + } + list_for_each_entry_safe(cursor, temp, &LH_SUS_PATH_SDCARD, list) { + if (!strncmp(d_name, cursor->info.target_pathname, cursor->path_len) && + (d_name[cursor->path_len] == '\0' || d_name[cursor->path_len] == '/') && + is_i_uid_in_sdcard_not_allowed()) + { + SUSFS_LOGI("hiding path '%s'\n", cursor->target_pathname); + return true; + } + } + return false; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) +bool susfs_is_inode_sus_path(struct mnt_idmap* idmap, struct inode *inode) { + if (unlikely(inode->i_state & INODE_STATE_SUS_PATH && + is_i_uid_not_allowed(i_uid_into_vfsuid(idmap, inode).val))) + { + SUSFS_LOGI("hiding path with ino '%lu'\n", inode->i_ino); + return true; + } + return false; } +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) +bool susfs_is_inode_sus_path(struct inode *inode) { + if (unlikely(inode->i_state & INODE_STATE_SUS_PATH && + is_i_uid_not_allowed(i_uid_into_mnt(i_user_ns(inode), inode).val))) + { + SUSFS_LOGI("hiding path with ino '%lu'\n", inode->i_ino); + return true; + } + return false; +} +#else +bool susfs_is_inode_sus_path(struct inode *inode) { + if (unlikely(inode->i_state & INODE_STATE_SUS_PATH && + is_i_uid_not_allowed(inode->i_uid.val))) + { + SUSFS_LOGI("hiding path with ino '%lu'\n", inode->i_ino); + return true; + } + return false; +} +#endif + #endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH /* sus_mount */ @@ -315,14 +510,6 @@ static int susfs_update_sus_kstat_inode(char *target_pathname) { return 1; } - // We don't allow path of which filesystem type is "tmpfs", because its inode->i_ino is starting from 1 again, - // which will cause wrong comparison in function susfs_sus_ino_for_filldir64() - if (strcmp(p.mnt->mnt_sb->s_type->name, "tmpfs") == 0) { - SUSFS_LOGE("target_pathname: '%s' cannot be added since its filesystem is 'tmpfs'\n", target_pathname); - path_put(&p); - return 1; - } - inode = d_inode(p.dentry); if (!inode) { path_put(&p); @@ -843,8 +1030,7 @@ struct filename* susfs_get_redirected_path(unsigned long ino) { /* sus_su */ #ifdef CONFIG_KSU_SUSFS_SUS_SU -bool susfs_is_sus_su_hooks_enabled __read_mostly = false; -static int susfs_sus_su_working_mode = 0; +extern int susfs_sus_su_working_mode; extern void ksu_susfs_enable_sus_su(void); extern void ksu_susfs_disable_sus_su(void); @@ -871,8 +1057,6 @@ int susfs_sus_su(struct st_sus_su* __user user_info) { return 2; } ksu_susfs_enable_sus_su(); - susfs_sus_su_working_mode = SUS_SU_WITH_HOOKS; - susfs_is_sus_su_hooks_enabled = true; SUSFS_LOGI("core kprobe hooks for ksu are disabled!\n"); SUSFS_LOGI("non-kprobe hook sus_su is enabled!\n"); SUSFS_LOGI("sus_su mode: %d\n", SUS_SU_WITH_HOOKS); @@ -882,9 +1066,7 @@ int susfs_sus_su(struct st_sus_su* __user user_info) { SUSFS_LOGE("current sus_su mode is already %d\n", SUS_SU_DISABLED); return 1; } - susfs_is_sus_su_hooks_enabled = false; ksu_susfs_disable_sus_su(); - susfs_sus_su_working_mode = SUS_SU_DISABLED; if (last_working_mode == SUS_SU_WITH_HOOKS) { SUSFS_LOGI("core kprobe hooks for ksu are enabled!\n"); goto out; @@ -901,6 +1083,106 @@ int susfs_sus_su(struct st_sus_su* __user user_info) { } #endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU +static int copy_config_to_buf(const char *config_string, char *buf_ptr, size_t *copied_size, size_t bufsize) { + size_t tmp_size = strlen(config_string); + + *copied_size += tmp_size; + if (*copied_size >= bufsize) { + SUSFS_LOGE("bufsize is not big enough to hold the string.\n"); + return -EINVAL; + } + strncpy(buf_ptr, config_string, tmp_size); + return 0; +} + +int susfs_get_enabled_features(char __user* buf, size_t bufsize) { + char *kbuf = NULL, *buf_ptr = NULL; + size_t copied_size = 0; + int err = 0; + + kbuf = kzalloc(bufsize, GFP_KERNEL); + if (!kbuf) { + return -ENOMEM; + } + + buf_ptr = kbuf; +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + err = copy_config_to_buf("CONFIG_KSU_SUSFS_SUS_PATH\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_SUS_MOUNT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_SUS_KSTAT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_TRY_UMOUNT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME + err = copy_config_to_buf("CONFIG_KSU_SUSFS_SPOOF_UNAME\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG + err = copy_config_to_buf("CONFIG_KSU_SUSFS_ENABLE_LOG\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS + err = copy_config_to_buf("CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG + err = copy_config_to_buf("CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_OPEN_REDIRECT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_SUS_SU + err = copy_config_to_buf("CONFIG_KSU_SUSFS_SUS_SU\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif +#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT + err = copy_config_to_buf("CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT\n", buf_ptr, &copied_size, bufsize); + if (err) goto out_kfree_kbuf; + buf_ptr = kbuf + copied_size; +#endif + err = copy_to_user((void __user*)buf, (void *)kbuf, bufsize); +out_kfree_kbuf: + kfree(kbuf); + return err; +} + + /* susfs_init */ void susfs_init(void) { spin_lock_init(&susfs_spin_lock); diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index d41de55cdfb9..9cea85f71f88 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -47,7 +47,7 @@ extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned extern void ptrace_disable(struct task_struct *); extern int ptrace_request(struct task_struct *child, long request, unsigned long addr, unsigned long data); -extern void ptrace_notify(int exit_code); +extern void ptrace_notify(int exit_code, unsigned long message); extern void __ptrace_link(struct task_struct *child, struct task_struct *new_parent, const struct cred *ptracer_cred); @@ -142,8 +142,7 @@ static inline bool ptrace_event_enabled(struct task_struct *task, int event) static inline void ptrace_event(int event, unsigned long message) { if (unlikely(ptrace_event_enabled(current, event))) { - current->ptrace_message = message; - ptrace_notify((event << 8) | SIGTRAP); + ptrace_notify((event << 8) | SIGTRAP, message); } else if (event == PTRACE_EVENT_EXEC) { /* legacy EXEC report via SIGTRAP */ if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED) diff --git a/include/linux/stat.h b/include/linux/stat.h index 528c4baad091..56614af83d4a 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -47,6 +47,7 @@ struct kstat { struct timespec64 ctime; struct timespec64 btime; /* File creation time */ u64 blocks; + u64 mnt_id; }; #endif diff --git a/include/linux/susfs.h b/include/linux/susfs.h index ef31283dbc41..5d33b24b491e 100644 --- a/include/linux/susfs.h +++ b/include/linux/susfs.h @@ -8,7 +8,7 @@ #include #include -#define SUSFS_VERSION "v1.5.5" +#define SUSFS_VERSION "v1.5.9" #if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) #define SUSFS_VARIANT "NON-GKI" #else @@ -29,12 +29,26 @@ struct st_susfs_sus_path { unsigned long target_ino; char target_pathname[SUSFS_MAX_LEN_PATHNAME]; + unsigned int i_uid; }; -struct st_susfs_sus_path_hlist { - unsigned long target_ino; +struct st_susfs_sus_path_list { + struct list_head list; + struct st_susfs_sus_path info; char target_pathname[SUSFS_MAX_LEN_PATHNAME]; - struct hlist_node node; + size_t path_len; +}; + +struct st_android_data_path { + unsigned long i_ino; + unsigned long s_magic; + char pathname[SUSFS_MAX_LEN_PATHNAME]; +}; + +struct st_sdcard_path { + unsigned long i_ino; + unsigned long s_magic; + char pathname[SUSFS_MAX_LEN_PATHNAME]; }; #endif @@ -127,8 +141,10 @@ struct st_sus_su { /***********************/ /* sus_path */ #ifdef CONFIG_KSU_SUSFS_SUS_PATH +int susfs_set_i_state_on_external_dir(char __user* user_info, int cmd); int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info); -int susfs_sus_ino_for_filldir64(unsigned long ino); + + #endif /* sus_mount */ #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT @@ -180,6 +196,9 @@ struct filename* susfs_get_redirected_path(unsigned long ino); int susfs_get_sus_su_working_mode(void); int susfs_sus_su(struct st_sus_su* __user user_info); #endif + +int susfs_get_enabled_features(char __user* buf, size_t bufsize); + /* susfs_init */ void susfs_init(void); diff --git a/include/linux/susfs_def.h b/include/linux/susfs_def.h index 7442047d0aa9..0c3fe6a7dde6 100644 --- a/include/linux/susfs_def.h +++ b/include/linux/susfs_def.h @@ -8,7 +8,11 @@ /********/ /* shared with userspace ksu_susfs tool */ #define CMD_SUSFS_ADD_SUS_PATH 0x55550 +#define CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH 0x55551 +#define CMD_SUSFS_SET_SDCARD_ROOT_PATH 0x55552 #define CMD_SUSFS_ADD_SUS_MOUNT 0x55560 +#define CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS 0x55561 +#define CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE 0x55562 #define CMD_SUSFS_ADD_SUS_KSTAT 0x55570 #define CMD_SUSFS_UPDATE_SUS_KSTAT 0x55571 #define CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY 0x55572 @@ -42,21 +46,41 @@ /* * inode->i_state => storing flag 'INODE_STATE_' * mount->mnt.susfs_mnt_id_backup => storing original mnt_id of normal mounts or custom sus mnt_id of sus mounts - * task_struct->susfs_last_fake_mnt_id => storing last valid fake mnt_id - * task_struct->susfs_task_state => storing flag 'TASK_STRUCT_' + * inode->i_mapping->flags => storing flag 'AS_FLAGS_' + * nd->state => storing flag 'ND_STATE_' + * nd->flags => storing flag 'ND_FLAGS_' + * task_struct->thread_info.flags => storing flag 'TIF_' */ - #define INODE_STATE_SUS_PATH BIT(24) #define INODE_STATE_SUS_MOUNT BIT(25) #define INODE_STATE_SUS_KSTAT BIT(26) #define INODE_STATE_OPEN_REDIRECT BIT(27) -#define TASK_STRUCT_NON_ROOT_USER_APP_PROC BIT(24) +#define TIF_NON_ROOT_USER_APP_PROC 33 // thread_info->flags is unsigned long :D + +#define AS_FLAGS_ANDROID_DATA_ROOT_DIR 28 +#define AS_FLAGS_SDCARD_ROOT_DIR 29 +#define BIT_ANDROID_DATA_ROOT_DIR BIT(28) +#define BIT_ANDROID_SDCARD_ROOT_DIR BIT(29) +#define ND_STATE_LOOKUP_LAST 32 +#define ND_STATE_OPEN_LAST 64 +#define ND_STATE_LAST_SDCARD_SUS_PATH 128 +#define ND_FLAGS_LOOKUP_LAST 0x2000000 + #define MAGIC_MOUNT_WORKDIR "/debug_ramdisk/workdir" #define DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS "/data/adb/susfs_umount_for_zygote_system_process" #define DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT "/data/adb/susfs_no_auto_add_sus_bind_mount" #define DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT "/data/adb/susfs_no_auto_add_sus_ksu_default_mount" #define DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT "/data/adb/susfs_no_auto_add_try_umount_for_bind_mount" +static inline bool susfs_is_current_non_root_user_app_proc(void) { + return test_ti_thread_flag(¤t->thread_info, TIF_NON_ROOT_USER_APP_PROC); +} + +static inline void susfs_set_current_non_root_user_app_proc(void) { + set_ti_thread_flag(¤t->thread_info, TIF_NON_ROOT_USER_APP_PROC); +} + + #endif // #ifndef KSU_SUSFS_DEF_H diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 05589a3e37f4..21b02f1b56dc 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -57,14 +57,14 @@ struct linux_binprm; /* * ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall(struct pt_regs *regs) +static inline int ptrace_report_syscall(struct pt_regs *regs, unsigned long message) { int ptrace = current->ptrace; if (!(ptrace & PT_PTRACED)) return 0; - ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0), message); /* * this isn't the same as continuing with a signal, but it will do @@ -101,7 +101,7 @@ static inline int ptrace_report_syscall(struct pt_regs *regs) static inline __must_check int tracehook_report_syscall_entry( struct pt_regs *regs) { - return ptrace_report_syscall(regs); + return ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_ENTRY); } /** @@ -131,7 +131,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) return; } - ptrace_report_syscall(regs); + ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_EXIT); } /** @@ -148,7 +148,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) static inline void tracehook_signal_handler(int stepping) { if (stepping) - ptrace_notify(SIGTRAP); + ptrace_notify(SIGTRAP, 0); } /** diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h index d5a1b8a492b9..07f58baabb9a 100644 --- a/include/uapi/linux/ptrace.h +++ b/include/uapi/linux/ptrace.h @@ -68,6 +68,9 @@ struct ptrace_peeksiginfo_args { #define PTRACE_SECCOMP_GET_FILTER 0x420c #define PTRACE_SECCOMP_GET_METADATA 0x420d +#define PTRACE_EVENTMSG_SYSCALL_ENTRY 1 +#define PTRACE_EVENTMSG_SYSCALL_EXIT 2 + struct seccomp_metadata { __u64 filter_off; /* Input: which filter */ __u64 flags; /* Output: filter's flags */ diff --git a/kernel/signal.c b/kernel/signal.c index 61e5823ae1b1..fbc860183f85 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2034,7 +2034,8 @@ static inline bool may_ptrace_stop(void) * If we actually decide not to stop at all because the tracer * is gone, we keep current->exit_code unless clear_code. */ -static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) +static void ptrace_stop(int exit_code, int why, int clear_code, + unsigned long message, siginfo_t *info) __releases(¤t->sighand->siglock) __acquires(¤t->sighand->siglock) { @@ -2080,6 +2081,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) */ smp_wmb(); + current->ptrace_message = message; current->last_siginfo = info; current->exit_code = exit_code; @@ -2158,6 +2160,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) */ spin_lock_irq(¤t->sighand->siglock); current->last_siginfo = NULL; + current->ptrace_message = 0; /* LISTENING can be set only during STOP traps, clear it */ current->jobctl &= ~JOBCTL_LISTENING; @@ -2170,7 +2173,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) recalc_sigpending_tsk(current); } -static void ptrace_do_notify(int signr, int exit_code, int why) +static void ptrace_do_notify(int signr, int exit_code, int why, unsigned long message) { siginfo_t info; @@ -2181,17 +2184,17 @@ static void ptrace_do_notify(int signr, int exit_code, int why) info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); /* Let the debugger run. */ - ptrace_stop(exit_code, why, 1, &info); + ptrace_stop(exit_code, why, 1, message, &info); } -void ptrace_notify(int exit_code) +void ptrace_notify(int exit_code, unsigned long message) { BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); if (unlikely(current->task_works)) task_work_run(); spin_lock_irq(¤t->sighand->siglock); - ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED); + ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED, message); spin_unlock_irq(¤t->sighand->siglock); } @@ -2346,10 +2349,10 @@ static void do_jobctl_trap(void) signr = SIGTRAP; WARN_ON_ONCE(!signr); ptrace_do_notify(signr, signr | (PTRACE_EVENT_STOP << 8), - CLD_STOPPED); + CLD_STOPPED, 0); } else { WARN_ON_ONCE(!signr); - ptrace_stop(signr, CLD_STOPPED, 0, NULL); + ptrace_stop(signr, CLD_STOPPED, 0, 0, NULL); current->exit_code = 0; } } @@ -2403,7 +2406,7 @@ static int ptrace_signal(int signr, siginfo_t *info) * comment in dequeue_signal(). */ current->jobctl |= JOBCTL_STOP_DEQUEUED; - ptrace_stop(signr, CLD_TRAPPED, 0, info); + ptrace_stop(signr, CLD_TRAPPED, 0, 0, info); /* We're back. Did the debugger cancel the sig? */ signr = current->exit_code; diff --git a/scripts/patch_kpm b/scripts/patch_kpm new file mode 100755 index 000000000000..412eebb5a10d Binary files /dev/null and b/scripts/patch_kpm differ diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 5ca29cbf2fa1..f91a3fb92d40 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -118,7 +118,7 @@ scm_version() git --no-optional-locks status -uno --porcelain 2>/dev/null || git diff-index --name-only HEAD } | grep -qvE '^(.. )?scripts/package'; then - printf '%s' -dirty + printf '%s' '' fi # All done with git @@ -142,7 +142,7 @@ scm_version() # Are there uncommitted changes? # These are represented by + after the changeset id. case "$hgid" in - *+|*+\ *) printf '%s' -dirty ;; + *+|*+\ *) printf '%s' '' ;; esac # All done with mercurial diff --git a/scripts/setup-kpm.sh b/scripts/setup-kpm.sh new file mode 100755 index 000000000000..644001739750 --- /dev/null +++ b/scripts/setup-kpm.sh @@ -0,0 +1,48 @@ +#!/usr/bin/bash + +function log() { + echo "[setup-kpm.sh] $@" +} + +SELF_DIR=$(git -C $(dirname $0) rev-parse --show-toplevel) + +if ! [ -f "scripts/patch_kpm" ]; then + log "No patch_kpm! downloading..." + + TAG=$(curl -s https://api.github.com/repos/SukiSU-Ultra/SukiSU_KernelPatch_patch/releases/latest | jq -r '.tag_name') + <<< $(curl -L --silent https://api.github.com/repos/SukiSU-Ultra/SukiSU_KernelPatch_patch/releases) + log "Latest tag is: $TAG" + + curl -Ls -o "scripts/patch_kpm" "https://github.com/SukiSU-Ultra/SukiSU_KernelPatch_patch/releases/download/$TAG/patch_linux" + + if [ $? -eq 0 ]; then + log "Download ok" + else + log "Download fail ($?)! abort!" + exit 1 + fi + + if [[ $(stat -c %s "scripts/patch_kpm") -lt 1024 ]]; then + log "Error! downloaded file corrupted (file too small)! abort!" + exit 1 + fi + + chmod +x "scripts/patch_kpm" + if [ $? -eq 0 ]; then + log "Set permission ok" + else + log "Failed to set permission! abort!" + exit 1 + fi +fi + + +if ! grep -q "CONFIG_KPM" arch/arm64/configs/gki_defconfig; then + log "Adding CONFIG_KPM=y" + echo "CONFIG_KPM=y" >> arch/arm64/configs/gki_defconfig +fi + +if ! grep -q "kpmpatch" arch/arm64/boot/Makefile; then + log "Adding auto kpm patch" + patch -p1 < $SELF_DIR/patches/02-add-auto-kpm-patch.patch +fi diff --git a/setup-kpm.sh b/setup-kpm.sh new file mode 100755 index 000000000000..aa07ae3c7327 --- /dev/null +++ b/setup-kpm.sh @@ -0,0 +1,49 @@ +#!/usr/bin/bash + +function log() { + echo "[setup-kpm.sh] $@" +} + +SELF_DIR=$(git -C $(dirname $0) rev-parse --show-toplevel) + +if ! [ -f "scripts/patch_kpm" ]; then + log "No patch_kpm! downloading..." + + TAG=$(curl -s https://api.github.com/repos/SukiSU-Ultra/SukiSU_KernelPatch_patch/releases/latest | jq -r '.tag_name') + #TAG=0.11-beta + <<< $(curl -L --silent https://api.github.com/repos/SukiSU-Ultra/SukiSU_KernelPatch_patch/releases) + log "Latest tag is: $TAG" + + curl -Ls -o "scripts/patch_kpm" "https://github.com/SukiSU-Ultra/SukiSU_KernelPatch_patch/releases/download/$TAG/patch_linux" + + if [ $? -eq 0 ]; then + log "Download ok" + else + log "Download fail ($?)! abort!" + exit 1 + fi + + if [[ $(stat -c %s "scripts/patch_kpm") -lt 1024 ]]; then + log "Error! downloaded file corrupted (file too small)! abort!" + exit 1 + fi + + chmod +x "scripts/patch_kpm" + if [ $? -eq 0 ]; then + log "Set permission ok" + else + log "Failed to set permission! abort!" + exit 1 + fi +fi + + +if ! grep -q "CONFIG_KPM" arch/arm64/configs/vendor/sm8250_defconfig; then + log "Adding CONFIG_KPM=y" + echo "CONFIG_KPM=y" >> arch/arm64/configs/vendor/sm8250_defconfig +fi + +if ! grep -q "kpmpatch" arch/arm64/boot/Makefile; then + log "Adding auto kpm patch" + patch -p1 < $SELF_DIR/patches/02-add-auto-kpm-patch.patch +fi diff --git a/zip.sh b/zip.sh index 5f3fe8fbb8c2..e9ebb81c69d5 100644 --- a/zip.sh +++ b/zip.sh @@ -3,8 +3,8 @@ cp out/arch/arm64/boot/dtbo.img ./anykernel/ [ -n "$(find ./anykernel -maxdepth 1 -type f -name '*.zip')" ] && rm ./anykernel/*.zip -cd anykernel && zip -r Bigshot-kernel-AOSP-KSU-Next-$(date +"%d-%m-%Y"-%H%M).zip * -#mv Bigshot-kernel-AOSP-AOSP-KSU-Next-$(date +"%d-%m-%Y-%H%M").zip ../out/ +cd anykernel && zip -r Bigshot-kernel-AOSP-SukiSU-KPM-$(date +"%d-%m-%Y"-%H%M).zip * +#mv Bigshot-kernel-AOSP-AOSP-SukiSU-$(date +"%d-%m-%Y-%H%M").zip ../out/ cd ..