KernelSU-Next + SuSFS 1.5.3 Patched
This commit is contained in:
parent
1589ebebbd
commit
157e80e925
32 changed files with 1677 additions and 22 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -144,4 +144,7 @@ all.config
|
|||
kernel/configs/android-*.cfg
|
||||
|
||||
# KSU
|
||||
drivers/kernelsu
|
||||
drivers/kernelsu
|
||||
|
||||
# Failed patch
|
||||
*.rej
|
|
@ -5333,6 +5333,7 @@ CONFIG_TZIC_USE_TRUSTONIC=y
|
|||
# KernelSU
|
||||
#
|
||||
CONFIG_KSU=y
|
||||
CONFIG_KSU_SUSFS=y
|
||||
# CONFIG_KSU_DEBUG is not set
|
||||
|
||||
#
|
||||
|
|
1
clean.sh
1
clean.sh
|
@ -9,7 +9,6 @@ then
|
|||
if [ "$1" == "all" ]; then
|
||||
clean_prebuilt
|
||||
clean
|
||||
git reset --hard
|
||||
elif [ "$1" == "lite" ]; then
|
||||
clean_temp
|
||||
clean_external
|
||||
|
|
|
@ -13,6 +13,8 @@ obj-y := open.o read_write.o file_table.o super.o \
|
|||
pnode.o splice.o sync.o utimes.o \
|
||||
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
|
||||
|
||||
obj-$(CONFIG_KSU_SUSFS) += susfs.o
|
||||
|
||||
ifeq ($(CONFIG_BLOCK),y)
|
||||
obj-y += buffer.o block_dev.o direct-io.o mpage.o
|
||||
else
|
||||
|
|
11
fs/dcache.c
11
fs/dcache.c
|
@ -2220,6 +2220,11 @@ seqretry:
|
|||
continue;
|
||||
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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
*seqp = seq;
|
||||
return dentry;
|
||||
|
@ -2303,6 +2308,12 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
|
|||
if (dentry->d_name.hash != hash)
|
||||
continue;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (dentry->d_inode && unlikely(dentry->d_inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_lock(&dentry->d_lock);
|
||||
if (dentry->d_parent != parent)
|
||||
goto next;
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
#define DEVPTS_DEFAULT_PTMX_MODE 0000
|
||||
#define PTMX_MINOR 2
|
||||
|
||||
#if defined(CONFIG_KSU_SUSFS_SUS_SU)
|
||||
extern bool ksu_devpts_hook;
|
||||
extern int ksu_handle_devpts(struct inode*);
|
||||
#endif
|
||||
/*
|
||||
* sysctl support for setting limits on the number of Unix98 ptys allocated.
|
||||
* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
|
||||
|
@ -565,8 +569,14 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
|
|||
*
|
||||
* Returns whatever was passed as priv in devpts_pty_new for a given inode.
|
||||
*/
|
||||
|
||||
void *devpts_get_priv(struct dentry *dentry)
|
||||
{
|
||||
#if defined(CONFIG_KSU_SUSFS_SUS_SU)
|
||||
if (ksu_devpts_hook) {
|
||||
ksu_handle_devpts(dentry->d_inode);
|
||||
}
|
||||
#endif
|
||||
if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC)
|
||||
return NULL;
|
||||
return dentry->d_fsdata;
|
||||
|
|
12
fs/exec.c
12
fs/exec.c
|
@ -1938,6 +1938,13 @@ extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
|
|||
/*
|
||||
* sys_execve() executes a new program.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
extern bool susfs_is_sus_su_hooks_enabled __read_mostly;
|
||||
extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void *argv,
|
||||
void *envp, int *flags);
|
||||
#endif
|
||||
|
||||
static int do_execveat_common(int fd, struct filename *filename,
|
||||
struct user_arg_ptr argv,
|
||||
struct user_arg_ptr envp,
|
||||
|
@ -1959,6 +1966,11 @@ static int do_execveat_common(int fd, struct filename *filename,
|
|||
if (IS_ERR(filename))
|
||||
return PTR_ERR(filename);
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
if (susfs_is_sus_su_hooks_enabled)
|
||||
ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We move the actual failure in case of RLIMIT_NPROC excess from
|
||||
* set*uid() to execve() because too many poorly written programs
|
||||
|
|
21
fs/inode.c
21
fs/inode.c
|
@ -23,6 +23,10 @@
|
|||
|
||||
#include <crypto/fmp.h>
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
extern bool susfs_is_current_ksu_domain(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Inode locking rules:
|
||||
*
|
||||
|
@ -1644,6 +1648,11 @@ int generic_update_time(struct inode *inode, struct timespec *time, int flags)
|
|||
{
|
||||
int iflags = I_DIRTY_TIME;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (susfs_is_current_ksu_domain()) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (flags & S_ATIME)
|
||||
inode->i_atime = *time;
|
||||
if (flags & S_VERSION)
|
||||
|
@ -1668,6 +1677,12 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
|
|||
{
|
||||
int (*update_time)(struct inode *, struct timespec *, int);
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (susfs_is_current_ksu_domain()) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
update_time = inode->i_op->update_time ? inode->i_op->update_time :
|
||||
generic_update_time;
|
||||
|
||||
|
@ -1725,6 +1740,12 @@ void touch_atime(const struct path *path)
|
|||
struct inode *inode = d_inode(path->dentry);
|
||||
struct timespec now;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (susfs_is_current_ksu_domain()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!__atime_needs_update(path, inode, false))
|
||||
return;
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ extern int finish_automount(struct vfsmount *, struct path *);
|
|||
extern int sb_prepare_remount_readonly(struct super_block *);
|
||||
|
||||
extern void __init mnt_init(void);
|
||||
int path_umount(struct path *path, int flags);
|
||||
|
||||
extern int __mnt_want_write(struct vfsmount *);
|
||||
extern int __mnt_want_write_file(struct file *);
|
||||
|
|
137
fs/namei.c
137
fs/namei.c
|
@ -932,6 +932,12 @@ 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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!sysctl_protected_symlinks)
|
||||
return 0;
|
||||
|
||||
|
@ -1008,6 +1014,12 @@ static int may_linkat(struct path *link)
|
|||
{
|
||||
struct inode *inode;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (link->dentry->d_inode && unlikely(link->dentry->d_inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!sysctl_protected_hardlinks)
|
||||
return 0;
|
||||
|
||||
|
@ -1047,6 +1059,12 @@ 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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
|
||||
(!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
|
||||
likely(!(dir_mode & S_ISVTX)) ||
|
||||
|
@ -1581,6 +1599,9 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
|
|||
unsigned int flags)
|
||||
{
|
||||
struct dentry *old;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
int error;
|
||||
#endif
|
||||
|
||||
/* Don't create child dentry for a dead directory. */
|
||||
if (unlikely(IS_DEADDIR(dir))) {
|
||||
|
@ -1593,6 +1614,19 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
|
|||
dput(dentry);
|
||||
dentry = old;
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
if ((flags & (LOOKUP_CREATE | LOOKUP_EXCL))) {
|
||||
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
|
||||
if (error) {
|
||||
dput(dentry);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
}
|
||||
dput(dentry);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
#endif
|
||||
return dentry;
|
||||
}
|
||||
|
||||
|
@ -1741,6 +1775,12 @@ again:
|
|||
dentry = old;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
dput(dentry);
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
#endif
|
||||
out:
|
||||
inode_unlock_shared(inode);
|
||||
return dentry;
|
||||
|
@ -2213,6 +2253,12 @@ OK:
|
|||
}
|
||||
return -ENOTDIR;
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
// we deal with sus sub path here
|
||||
if (nd->inode && unlikely(nd->inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2392,6 +2438,12 @@ 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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
putname(name);
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
putname(name);
|
||||
return retval;
|
||||
}
|
||||
|
@ -2874,6 +2926,12 @@ static int may_delete(struct vfsmount *mnt, struct inode *dir, struct dentry *vi
|
|||
if (IS_APPEND(dir))
|
||||
return -EPERM;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (unlikely(inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (check_sticky(dir, inode) || IS_APPEND(inode) ||
|
||||
IS_IMMUTABLE(inode) || IS_SWAPFILE(inode) || HAS_UNMAPPED_ID(inode))
|
||||
return -EPERM;
|
||||
|
@ -2902,8 +2960,20 @@ 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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
error = inode_permission2(mnt, dir, MAY_WRITE | MAY_EXEC);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
if (child->d_inode)
|
||||
return -EEXIST;
|
||||
if (IS_DEADDIR(dir))
|
||||
|
@ -3003,6 +3073,12 @@ static int may_open(struct path *path, int acc_mode, int flag)
|
|||
if (!inode)
|
||||
return -ENOENT;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (unlikely(inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
case S_IFLNK:
|
||||
return -ELOOP;
|
||||
|
@ -3074,7 +3150,20 @@ 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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
error = inode_permission2(dir->mnt, 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;
|
||||
|
||||
|
@ -3221,6 +3310,12 @@ 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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
dput(dentry);
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
goto out_no_open;
|
||||
}
|
||||
|
||||
|
@ -3264,6 +3359,16 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
|||
mode, opened);
|
||||
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 & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
if (create_error) {
|
||||
dput(dentry);
|
||||
return create_error;
|
||||
}
|
||||
dput(dentry);
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -3279,6 +3384,12 @@ no_open:
|
|||
}
|
||||
dput(dentry);
|
||||
dentry = res;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (dentry->d_inode && unlikely(dentry->d_inode->i_state & 16777216) && likely(current_cred()->user->android_kabi_reserved2 & 16777216)) {
|
||||
dput(dentry);
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3634,12 +3745,19 @@ out2:
|
|||
return file;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
extern struct filename* susfs_get_redirected_path(unsigned long ino);
|
||||
#endif
|
||||
|
||||
struct file *do_filp_open(int dfd, struct filename *pathname,
|
||||
const struct open_flags *op)
|
||||
{
|
||||
struct nameidata nd;
|
||||
int flags = op->lookup_flags;
|
||||
struct file *filp;
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
struct filename *fake_pathname;
|
||||
#endif
|
||||
|
||||
set_nameidata(&nd, dfd, pathname);
|
||||
filp = path_openat(&nd, op, flags | LOOKUP_RCU);
|
||||
|
@ -3647,6 +3765,25 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
|
|||
filp = path_openat(&nd, op, flags);
|
||||
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
||||
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
if (!IS_ERR(filp) && unlikely(filp->f_inode->i_state & 134217728) && current_uid().val < 2000) {
|
||||
fake_pathname = susfs_get_redirected_path(filp->f_inode->i_ino);
|
||||
if (!IS_ERR(fake_pathname)) {
|
||||
restore_nameidata();
|
||||
filp_close(filp, NULL);
|
||||
// no need to do `putname(pathname);` here as it will be done by calling process
|
||||
set_nameidata(&nd, dfd, fake_pathname);
|
||||
filp = path_openat(&nd, op, flags | LOOKUP_RCU);
|
||||
if (unlikely(filp == ERR_PTR(-ECHILD)))
|
||||
filp = path_openat(&nd, op, flags);
|
||||
if (unlikely(filp == ERR_PTR(-ESTALE)))
|
||||
filp = path_openat(&nd, op, flags | LOOKUP_REVAL);
|
||||
restore_nameidata();
|
||||
putname(fake_pathname);
|
||||
return filp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
restore_nameidata();
|
||||
return filp;
|
||||
}
|
||||
|
|
153
fs/namespace.c
153
fs/namespace.c
|
@ -46,6 +46,23 @@
|
|||
#define KDP_MOUNT_VENDOR_LEN strlen(KDP_MOUNT_VENDOR)
|
||||
#endif /*CONFIG_RKP_NS_PROT */
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
extern bool susfs_is_current_ksu_domain(void);
|
||||
extern bool susfs_is_current_zygote_domain(void);
|
||||
#define CL_SUSFS_COPY_MNT_NS 0x1000000
|
||||
#define DEFAULT_SUS_MNT_GROUP_ID 1000
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
extern int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target);
|
||||
#endif
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
extern void susfs_auto_add_try_umount_for_bind_mount(struct path *path);
|
||||
#endif
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
extern void susfs_auto_add_sus_ksu_default_mount(const char __user *to_pathname);
|
||||
#endif
|
||||
|
||||
/* Maximum number of mounts in a mount namespace */
|
||||
unsigned int sysctl_mount_max __read_mostly = 100000;
|
||||
|
||||
|
@ -290,6 +307,20 @@ static int mnt_alloc_vfsmount(struct mount *mnt)
|
|||
static void mnt_free_id(struct mount *mnt)
|
||||
{
|
||||
int id = mnt->mnt_id;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
int orig_id;
|
||||
// If mnt->mnt.android_kabi_reserved4 is not zero, it means mnt->mnt_id is spoofed,
|
||||
// so here we return the original mnt_id for being freed.
|
||||
if (unlikely(mnt->mnt.android_kabi_reserved4)) {
|
||||
orig_id = mnt->mnt.android_kabi_reserved4;
|
||||
spin_lock(&mnt_id_lock);
|
||||
ida_remove(&mnt_id_ida, orig_id);
|
||||
if (mnt_id_start > orig_id)
|
||||
mnt_id_start = orig_id;
|
||||
spin_unlock(&mnt_id_lock);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
spin_lock(&mnt_id_lock);
|
||||
ida_remove(&mnt_id_ida, id);
|
||||
if (mnt_id_start > id)
|
||||
|
@ -297,6 +328,14 @@ static void mnt_free_id(struct mount *mnt)
|
|||
spin_unlock(&mnt_id_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
static void susfs_mnt_alloc_group_id(struct mount *mnt)
|
||||
{
|
||||
// Just assign the same default sus mount_group_id to mnt->mnt_group_id
|
||||
mnt->mnt_group_id = DEFAULT_SUS_MNT_GROUP_ID;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate a new peer group ID
|
||||
*
|
||||
|
@ -324,6 +363,14 @@ static int mnt_alloc_group_id(struct mount *mnt)
|
|||
void mnt_release_group_id(struct mount *mnt)
|
||||
{
|
||||
int id = mnt->mnt_group_id;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
// If mnt->mnt_group_id >= DEFAULT_SUS_MNT_GROUP_ID, it means 'mnt' is sus mount,
|
||||
// here we don't need to free the mnt_group_id and just simply return and do nothing.
|
||||
if (unlikely(mnt->mnt_group_id >= DEFAULT_SUS_MNT_GROUP_ID)) {
|
||||
mnt->mnt_group_id = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ida_remove(&mnt_group_ida, id);
|
||||
if (mnt_group_start > id)
|
||||
mnt_group_start = id;
|
||||
|
@ -1271,6 +1318,14 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
|
|||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||
#endif
|
||||
mnt->mnt_parent = mnt;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (susfs_is_current_zygote_domain()) {
|
||||
mnt->mnt.android_kabi_reserved4 = mnt->mnt_id;
|
||||
mnt->mnt_id = current->android_kabi_reserved8++;
|
||||
}
|
||||
#endif
|
||||
|
||||
lock_mount_hash();
|
||||
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
|
||||
unlock_mount_hash();
|
||||
|
@ -1396,6 +1451,14 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
|
|||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||
#endif
|
||||
mnt->mnt_parent = mnt;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (susfs_is_current_zygote_domain() && !(flag & CL_SUSFS_COPY_MNT_NS)) {
|
||||
mnt->mnt.android_kabi_reserved4 = mnt->mnt_id;
|
||||
mnt->mnt_id = current->android_kabi_reserved8++;
|
||||
}
|
||||
#endif
|
||||
|
||||
lock_mount_hash();
|
||||
list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
|
||||
unlock_mount_hash();
|
||||
|
@ -2370,6 +2433,17 @@ static int invent_group_ids(struct mount *mnt, bool recurse)
|
|||
{
|
||||
struct mount *p;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (susfs_is_current_ksu_domain()) {
|
||||
for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
|
||||
if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
|
||||
susfs_mnt_alloc_group_id(p);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
|
||||
if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
|
||||
int err = mnt_alloc_group_id(p);
|
||||
|
@ -2748,6 +2822,24 @@ static int do_loopback(struct path *path, const char *old_name,
|
|||
umount_tree(mnt, UMOUNT_SYNC);
|
||||
unlock_mount_hash();
|
||||
}
|
||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT) || defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||
// Check if bind mounted path should be hidden and umounted automatically.
|
||||
// And we target only process with ksu domain.
|
||||
if (susfs_is_current_ksu_domain()) {
|
||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
||||
if (susfs_auto_add_sus_bind_mount(old_name, &old_path)) {
|
||||
goto orig_flow;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||
susfs_auto_add_try_umount_for_bind_mount(path);
|
||||
#endif
|
||||
}
|
||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
||||
orig_flow:
|
||||
#endif
|
||||
#endif // #if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT) || defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||
|
||||
out2:
|
||||
unlock_mount(mp);
|
||||
out:
|
||||
|
@ -3434,6 +3526,13 @@ long do_mount(const char *dev_name, const char __user *dir_name,
|
|||
retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
|
||||
dev_name, data_page);
|
||||
#endif
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
if (!retval && (!(flags & (MS_REMOUNT | MS_BIND | MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)))) {
|
||||
if (susfs_is_current_ksu_domain()) {
|
||||
susfs_auto_add_sus_ksu_default_mount(dir_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dput_out:
|
||||
path_put(&path);
|
||||
return retval;
|
||||
|
@ -3511,6 +3610,10 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|||
struct mount *old;
|
||||
struct mount *new;
|
||||
int copy_flags;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
bool is_zygote_pid = susfs_is_current_zygote_domain();
|
||||
int last_entry_mnt_id = 0;
|
||||
#endif
|
||||
|
||||
BUG_ON(!ns);
|
||||
|
||||
|
@ -3530,6 +3633,12 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|||
copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
|
||||
if (user_ns != ns->user_ns)
|
||||
copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (is_zygote_pid) {
|
||||
// Let clone_mnt() in copy_tree() know we only interested in function called by copy_mnt_ns()
|
||||
copy_flags |= CL_SUSFS_COPY_MNT_NS;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_RKP_NS_PROT
|
||||
new = copy_tree(old, old->mnt->mnt_root, copy_flags);
|
||||
#else
|
||||
|
@ -3586,6 +3695,29 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
|
|||
#endif
|
||||
p = next_mnt(p, old);
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
// current->android_kabi_reserved8 -> to record last valid fake mnt_id to zygote pid
|
||||
// q->mnt.android_kabi_reserved4 -> 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
|
||||
// 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;
|
||||
list_for_each_entry(q, &new_ns->list, mnt_list) {
|
||||
if (unlikely(q->mnt.mnt_root->d_inode->i_state & 33554432)) {
|
||||
continue;
|
||||
}
|
||||
q->mnt.android_kabi_reserved4 = q->mnt_id;
|
||||
q->mnt_id = last_entry_mnt_id++;
|
||||
}
|
||||
}
|
||||
// Assign the 'last_entry_mnt_id' to 'current->android_kabi_reserved8' 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->android_kabi_reserved8 = last_entry_mnt_id;
|
||||
#endif
|
||||
|
||||
namespace_unlock();
|
||||
|
||||
if (rootmnt)
|
||||
|
@ -4211,3 +4343,24 @@ const struct proc_ns_operations mntns_operations = {
|
|||
.install = mntns_install,
|
||||
.owner = mntns_owner,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
extern void susfs_try_umount_all(uid_t uid);
|
||||
void susfs_run_try_umount_for_current_mnt_ns(void) {
|
||||
struct mount *mnt;
|
||||
struct mnt_namespace *mnt_ns;
|
||||
|
||||
mnt_ns = current->nsproxy->mnt_ns;
|
||||
// Lock the namespace
|
||||
namespace_lock();
|
||||
list_for_each_entry(mnt, &mnt_ns->list, mnt_list) {
|
||||
// Change the sus mount to be private
|
||||
if (mnt->mnt.mnt_root->d_inode->i_state & 33554432) {
|
||||
change_mnt_propagation(mnt, MS_PRIVATE);
|
||||
}
|
||||
}
|
||||
// Unlock the namespace
|
||||
namespace_unlock();
|
||||
susfs_try_umount_all(current_uid().val);
|
||||
}
|
||||
#endif
|
13
fs/open.c
13
fs/open.c
|
@ -369,6 +369,13 @@ extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int
|
|||
* We do this by temporarily clearing all FS-related capabilities and
|
||||
* switching the fsuid/fsgid around to the real ones.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
|
||||
{
|
||||
const struct cred *old_cred;
|
||||
|
@ -383,6 +390,12 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
|
|||
ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
if (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;
|
||||
|
||||
|
|
|
@ -115,6 +115,16 @@ static int ovl_getattr(const struct path *path, struct kstat *stat,
|
|||
const struct cred *old_cred;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
|
||||
ovl_path_lowerdata(dentry, &realpath);
|
||||
if (likely(realpath.mnt && realpath.dentry)) {
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
err = vfs_getattr(&realpath, stat, request_mask, flags);
|
||||
ovl_revert_creds(old_cred);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
ovl_path_real(dentry, &realpath);
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
err = vfs_getattr(&realpath, stat, request_mask, flags);
|
||||
|
|
|
@ -148,6 +148,9 @@ u64 ovl_dentry_version_get(struct dentry *dentry);
|
|||
void ovl_dentry_version_inc(struct dentry *dentry);
|
||||
void ovl_path_upper(struct dentry *dentry, struct path *path);
|
||||
void ovl_path_lower(struct dentry *dentry, struct path *path);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
|
||||
void ovl_path_lowerdata(struct dentry *dentry, struct path *path);
|
||||
#endif
|
||||
enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
|
||||
int ovl_path_next(int idx, struct dentry *dentry, struct path *path);
|
||||
struct dentry *ovl_dentry_upper(struct dentry *dentry);
|
||||
|
|
|
@ -499,7 +499,19 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
|
|||
if (!od)
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
|
||||
ovl_path_lowerdata(file->f_path.dentry, &realpath);
|
||||
if (likely(realpath.mnt && realpath.dentry)) {
|
||||
// We still use '__OVL_PATH_UPPER' here which should be fine.
|
||||
type = __OVL_PATH_UPPER;
|
||||
goto bypass_orig_flow;
|
||||
}
|
||||
#endif
|
||||
|
||||
type = ovl_path_real(file->f_path.dentry, &realpath);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
|
||||
bypass_orig_flow:
|
||||
#endif
|
||||
realfile = ovl_path_open(&realpath, file->f_flags);
|
||||
if (IS_ERR(realfile)) {
|
||||
kfree(od);
|
||||
|
|
|
@ -186,6 +186,20 @@ void ovl_path_lower(struct dentry *dentry, struct path *path)
|
|||
*path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL };
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
|
||||
void ovl_path_lowerdata(struct dentry *dentry, struct path *path)
|
||||
{
|
||||
struct ovl_entry *oe = dentry->d_fsdata;
|
||||
|
||||
if (oe->numlower) {
|
||||
path->mnt = oe->lowerstack[oe->numlower - 1].mnt;
|
||||
path->dentry = oe->lowerstack[oe->numlower - 1].dentry;
|
||||
} else {
|
||||
*path = (struct path) { };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ovl_want_write(struct dentry *dentry)
|
||||
{
|
||||
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
|
||||
|
@ -654,6 +668,18 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|||
struct path path;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
|
||||
ovl_path_lowerdata(root_dentry, &path);
|
||||
if (likely(path.mnt && path.dentry)) {
|
||||
err = vfs_statfs(&path, buf);
|
||||
if (!err) {
|
||||
buf->f_namelen = 255; // 255 for erofs, ext2/4, f2fs
|
||||
buf->f_type = path.dentry->d_sb->s_magic;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
ovl_path_real(root_dentry, &path);
|
||||
|
||||
err = vfs_statfs(&path, buf);
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#ifdef KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||
extern int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m);
|
||||
#endif
|
||||
|
||||
enum {
|
||||
FLAG_DELETE = 0,
|
||||
FLAG_REPLACE,
|
||||
|
@ -13,6 +17,12 @@ static char new_command_line[COMMAND_LINE_SIZE];
|
|||
|
||||
static int cmdline_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
#ifdef KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||
if (!susfs_spoof_cmdline_or_bootconfig(m)) {
|
||||
seq_putc(m, '\n');
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
seq_puts(m, new_command_line);
|
||||
seq_putc(m, '\n');
|
||||
return 0;
|
||||
|
|
|
@ -375,6 +375,10 @@ static void show_vma_header_prefix(struct seq_file *m,
|
|||
MAJOR(dev), MINOR(dev), ino);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
extern void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino);
|
||||
#endif
|
||||
|
||||
static void
|
||||
show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
|
||||
{
|
||||
|
@ -390,8 +394,17 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
|
|||
|
||||
if (file) {
|
||||
struct inode *inode = file_inode(vma->vm_file);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (unlikely(inode->i_state & 67108864)) {
|
||||
susfs_sus_ino_for_show_map_vma(inode->i_ino, &dev, &ino);
|
||||
goto bypass_orig_flow;
|
||||
}
|
||||
#endif
|
||||
dev = inode->i_sb->s_dev;
|
||||
ino = inode->i_ino;
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
bypass_orig_flow:
|
||||
#endif
|
||||
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
#include "pnode.h"
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
extern bool susfs_is_current_ksu_domain(void);
|
||||
#endif
|
||||
|
||||
static unsigned mounts_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
|
@ -99,6 +103,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
|
|||
struct super_block *sb = mnt_path.dentry->d_sb;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (unlikely((r->mnt.mnt_root->d_inode->i_state & 33554432) && !susfs_is_current_ksu_domain()))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (sb->s_op->show_devname) {
|
||||
err = sb->s_op->show_devname(m, mnt_path.dentry);
|
||||
if (err)
|
||||
|
@ -135,6 +144,11 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
|
|||
struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (unlikely((r->mnt.mnt_root->d_inode->i_state & 33554432) && !susfs_is_current_ksu_domain()))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
|
||||
MAJOR(sb->s_dev), MINOR(sb->s_dev));
|
||||
if (sb->s_op->show_path) {
|
||||
|
@ -199,6 +213,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
|
|||
struct super_block *sb = mnt_path.dentry->d_sb;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (unlikely((r->mnt.mnt_root->d_inode->i_state & 33554432) && !susfs_is_current_ksu_domain()))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* device */
|
||||
if (sb->s_op->show_devname) {
|
||||
seq_puts(m, "device ");
|
||||
|
|
|
@ -286,6 +286,10 @@ struct getdents_callback64 {
|
|||
int error;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
extern int susfs_sus_ino_for_filldir64(unsigned long ino);
|
||||
#endif
|
||||
|
||||
static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
||||
loff_t offset, u64 ino, unsigned int d_type)
|
||||
{
|
||||
|
@ -295,6 +299,11 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
|||
int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
|
||||
sizeof(u64));
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
if (likely(current_cred()->user->android_kabi_reserved2 & 16777216) && susfs_sus_ino_for_filldir64(ino)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
buf->error = verify_dirent_name(name, namlen);
|
||||
if (unlikely(buf->error))
|
||||
return buf->error;
|
||||
|
|
14
fs/stat.c
14
fs/stat.c
|
@ -18,6 +18,10 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* generic_fillattr - Fill in the basic attributes from the inode struct
|
||||
* @inode: Inode to use as the source
|
||||
|
@ -29,6 +33,16 @@
|
|||
*/
|
||||
void generic_fillattr(struct inode *inode, struct kstat *stat)
|
||||
{
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (unlikely(inode->i_state & 67108864)) {
|
||||
susfs_sus_ino_for_generic_fillattr(inode->i_ino, stat);
|
||||
stat->mode = inode->i_mode;
|
||||
stat->rdev = inode->i_rdev;
|
||||
stat->uid = inode->i_uid;
|
||||
stat->gid = inode->i_gid;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
stat->dev = inode->i_sb->s_dev;
|
||||
stat->ino = inode->i_ino;
|
||||
stat->mode = inode->i_mode;
|
||||
|
|
22
fs/statfs.c
22
fs/statfs.c
|
@ -89,6 +89,22 @@ retry:
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -100,6 +116,12 @@ 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;
|
||||
}
|
||||
|
||||
|
|
891
fs/susfs.c
Normal file
891
fs/susfs.c
Normal file
|
@ -0,0 +1,891 @@
|
|||
#include <linux/version.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/init_task.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/susfs.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0)
|
||||
#include "pnode.h"
|
||||
#endif
|
||||
|
||||
static spinlock_t susfs_spin_lock;
|
||||
#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
|
||||
static const char *magic_mount_workdir = "/debug_ramdisk/workdir";
|
||||
#endif
|
||||
|
||||
extern bool susfs_is_current_ksu_domain(void);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
extern void ksu_try_umount(const char *mnt, bool check_mnt, int flags);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
bool susfs_is_log_enabled __read_mostly = true;
|
||||
#define SUSFS_LOGI(fmt, ...) if (susfs_is_log_enabled) pr_info("susfs:[%u][%d][%s] " fmt, current_uid().val, current->pid, __func__, ##__VA_ARGS__)
|
||||
#define SUSFS_LOGE(fmt, ...) if (susfs_is_log_enabled) pr_err("susfs:[%u][%d][%s]" fmt, current_uid().val, current->pid, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define SUSFS_LOGI(fmt, ...)
|
||||
#define SUSFS_LOGE(fmt, ...)
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
struct inode *inode = NULL;
|
||||
|
||||
if (kern_path(target_pathname, LOOKUP_FOLLOW, &p)) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", 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) {
|
||||
SUSFS_LOGE("inode is NULL\n");
|
||||
path_put(&p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
path_put(&p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int susfs_add_sus_path(struct st_susfs_sus_path* __user user_info) {
|
||||
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;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(info))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int susfs_sus_ino_for_filldir64(unsigned long ino) {
|
||||
struct st_susfs_sus_path_hlist *entry;
|
||||
|
||||
hash_for_each_possible(SUS_PATH_HLIST, entry, node, ino) {
|
||||
if (entry->target_ino == ino)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
|
||||
/* sus_mount */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
static LIST_HEAD(LH_SUS_MOUNT);
|
||||
static void susfs_update_sus_mount_inode(char *target_pathname) {
|
||||
struct path p;
|
||||
struct inode *inode = NULL;
|
||||
int err = 0;
|
||||
|
||||
err = kern_path(target_pathname, LOOKUP_FOLLOW, &p);
|
||||
if (err) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", target_pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
inode = d_inode(p.dentry);
|
||||
if (!inode) {
|
||||
path_put(&p);
|
||||
SUSFS_LOGE("inode is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_MOUNT;
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
path_put(&p);
|
||||
}
|
||||
|
||||
int susfs_add_sus_mount(struct st_susfs_sus_mount* __user user_info) {
|
||||
struct st_susfs_sus_mount_list *cursor = NULL, *temp = NULL;
|
||||
struct st_susfs_sus_mount_list *new_list = NULL;
|
||||
struct st_susfs_sus_mount info;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(info))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
|
||||
#ifdef CONFIG_MIPS
|
||||
info.target_dev = new_decode_dev(info.target_dev);
|
||||
#else
|
||||
info.target_dev = huge_decode_dev(info.target_dev);
|
||||
#endif /* CONFIG_MIPS */
|
||||
#else
|
||||
info.target_dev = old_decode_dev(info.target_dev);
|
||||
#endif /* defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) */
|
||||
|
||||
list_for_each_entry_safe(cursor, temp, &LH_SUS_MOUNT, list) {
|
||||
if (unlikely(!strcmp(cursor->info.target_pathname, info.target_pathname))) {
|
||||
spin_lock(&susfs_spin_lock);
|
||||
memcpy(&cursor->info, &info, sizeof(info));
|
||||
susfs_update_sus_mount_inode(cursor->info.target_pathname);
|
||||
SUSFS_LOGI("target_pathname: '%s', target_dev: '%lu', is successfully updated to LH_SUS_MOUNT\n",
|
||||
cursor->info.target_pathname, cursor->info.target_dev);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
new_list = kmalloc(sizeof(struct st_susfs_sus_mount_list), GFP_KERNEL);
|
||||
if (!new_list) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(&new_list->info, &info, sizeof(info));
|
||||
susfs_update_sus_mount_inode(new_list->info.target_pathname);
|
||||
|
||||
INIT_LIST_HEAD(&new_list->list);
|
||||
spin_lock(&susfs_spin_lock);
|
||||
list_add_tail(&new_list->list, &LH_SUS_MOUNT);
|
||||
SUSFS_LOGI("target_pathname: '%s', target_dev: '%lu', is successfully added to LH_SUS_MOUNT\n",
|
||||
new_list->info.target_pathname, new_list->info.target_dev);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target) {
|
||||
struct inode *inode;
|
||||
|
||||
inode = path_target->dentry->d_inode;
|
||||
if (!inode) return 1;
|
||||
if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_MOUNT;
|
||||
spin_unlock(&inode->i_lock);
|
||||
SUSFS_LOGI("set SUS_MOUNT inode state for source bind mount path '%s'\n", pathname);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
void susfs_auto_add_sus_ksu_default_mount(const char __user *to_pathname) {
|
||||
char *pathname = NULL;
|
||||
struct path path;
|
||||
struct inode *inode;
|
||||
|
||||
pathname = kmalloc(SUSFS_MAX_LEN_PATHNAME, GFP_KERNEL);
|
||||
if (!pathname) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return;
|
||||
}
|
||||
// Here we need to re-retrieve the struct path as we want the new struct path, not the old one
|
||||
if (strncpy_from_user(pathname, to_pathname, SUSFS_MAX_LEN_PATHNAME-1) < 0) {
|
||||
SUSFS_LOGE("strncpy_from_user()\n");
|
||||
goto out_free_pathname;
|
||||
return;
|
||||
}
|
||||
if ((!strncmp(pathname, "/data/adb/modules", 17) ||
|
||||
!strncmp(pathname, "/debug_ramdisk", 14) ||
|
||||
!strncmp(pathname, "/system", 7) ||
|
||||
!strncmp(pathname, "/system_ext", 11) ||
|
||||
!strncmp(pathname, "/vendor", 7) ||
|
||||
!strncmp(pathname, "/product", 8) ||
|
||||
!strncmp(pathname, "/odm", 4)) &&
|
||||
!kern_path(pathname, LOOKUP_FOLLOW, &path)) {
|
||||
goto set_inode_sus_mount;
|
||||
}
|
||||
goto out_free_pathname;
|
||||
set_inode_sus_mount:
|
||||
inode = path.dentry->d_inode;
|
||||
if (!inode) {
|
||||
goto out_path_put;
|
||||
return;
|
||||
}
|
||||
if (!(inode->i_state & INODE_STATE_SUS_MOUNT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_MOUNT;
|
||||
spin_unlock(&inode->i_lock);
|
||||
SUSFS_LOGI("set SUS_MOUNT inode state for default KSU mount path '%s'\n", pathname);
|
||||
}
|
||||
out_path_put:
|
||||
path_put(&path);
|
||||
out_free_pathname:
|
||||
kfree(pathname);
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
|
||||
/* sus_kstat */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
static DEFINE_HASHTABLE(SUS_KSTAT_HLIST, 10);
|
||||
static int susfs_update_sus_kstat_inode(char *target_pathname) {
|
||||
struct path p;
|
||||
struct inode *inode = NULL;
|
||||
int err = 0;
|
||||
|
||||
err = kern_path(target_pathname, LOOKUP_FOLLOW, &p);
|
||||
if (err) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", 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);
|
||||
SUSFS_LOGE("inode is NULL\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(inode->i_state & INODE_STATE_SUS_KSTAT)) {
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_state |= INODE_STATE_SUS_KSTAT;
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
path_put(&p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int susfs_add_sus_kstat(struct st_susfs_sus_kstat* __user user_info) {
|
||||
struct st_susfs_sus_kstat info;
|
||||
struct st_susfs_sus_kstat_hlist *new_entry, *tmp_entry;
|
||||
struct hlist_node *tmp_node;
|
||||
int bkt;
|
||||
bool update_hlist = false;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(info))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strlen(info.target_pathname) == 0) {
|
||||
SUSFS_LOGE("target_pathname is an empty string\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock(&susfs_spin_lock);
|
||||
hash_for_each_safe(SUS_KSTAT_HLIST, bkt, tmp_node, tmp_entry, node) {
|
||||
if (!strcmp(tmp_entry->info.target_pathname, info.target_pathname)) {
|
||||
hash_del(&tmp_entry->node);
|
||||
kfree(tmp_entry);
|
||||
update_hlist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
|
||||
new_entry = kmalloc(sizeof(struct st_susfs_sus_kstat_hlist), GFP_KERNEL);
|
||||
if (!new_entry) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
|
||||
#ifdef CONFIG_MIPS
|
||||
info.spoofed_dev = new_decode_dev(info.spoofed_dev);
|
||||
#else
|
||||
info.spoofed_dev = huge_decode_dev(info.spoofed_dev);
|
||||
#endif /* CONFIG_MIPS */
|
||||
#else
|
||||
info.spoofed_dev = old_decode_dev(info.spoofed_dev);
|
||||
#endif /* defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) */
|
||||
|
||||
new_entry->target_ino = info.target_ino;
|
||||
memcpy(&new_entry->info, &info, sizeof(info));
|
||||
|
||||
if (susfs_update_sus_kstat_inode(new_entry->info.target_pathname)) {
|
||||
kfree(new_entry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock(&susfs_spin_lock);
|
||||
hash_add(SUS_KSTAT_HLIST, &new_entry->node, info.target_ino);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
|
||||
if (update_hlist) {
|
||||
SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%llu', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully added to SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
|
||||
new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
|
||||
new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
|
||||
new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
|
||||
new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
|
||||
new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
|
||||
} else {
|
||||
SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%llu', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully updated to SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
|
||||
new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
|
||||
new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
|
||||
new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
|
||||
new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
|
||||
new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
|
||||
}
|
||||
#else
|
||||
if (update_hlist) {
|
||||
SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%u', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully added to SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
|
||||
new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
|
||||
new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
|
||||
new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
|
||||
new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
|
||||
new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
|
||||
} else {
|
||||
SUSFS_LOGI("is_statically: '%d', target_ino: '%lu', target_pathname: '%s', spoofed_ino: '%lu', spoofed_dev: '%lu', spoofed_nlink: '%u', spoofed_size: '%u', spoofed_atime_tv_sec: '%ld', spoofed_mtime_tv_sec: '%ld', spoofed_ctime_tv_sec: '%ld', spoofed_atime_tv_nsec: '%ld', spoofed_mtime_tv_nsec: '%ld', spoofed_ctime_tv_nsec: '%ld', spoofed_blksize: '%lu', spoofed_blocks: '%llu', is successfully updated to SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.is_statically, new_entry->info.target_ino, new_entry->info.target_pathname,
|
||||
new_entry->info.spoofed_ino, new_entry->info.spoofed_dev,
|
||||
new_entry->info.spoofed_nlink, new_entry->info.spoofed_size,
|
||||
new_entry->info.spoofed_atime_tv_sec, new_entry->info.spoofed_mtime_tv_sec, new_entry->info.spoofed_ctime_tv_sec,
|
||||
new_entry->info.spoofed_atime_tv_nsec, new_entry->info.spoofed_mtime_tv_nsec, new_entry->info.spoofed_ctime_tv_nsec,
|
||||
new_entry->info.spoofed_blksize, new_entry->info.spoofed_blocks);
|
||||
}
|
||||
#endif
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int susfs_update_sus_kstat(struct st_susfs_sus_kstat* __user user_info) {
|
||||
struct st_susfs_sus_kstat info;
|
||||
struct st_susfs_sus_kstat_hlist *new_entry, *tmp_entry;
|
||||
struct hlist_node *tmp_node;
|
||||
int bkt;
|
||||
int err = 0;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(info))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock(&susfs_spin_lock);
|
||||
hash_for_each_safe(SUS_KSTAT_HLIST, bkt, tmp_node, tmp_entry, node) {
|
||||
if (!strcmp(tmp_entry->info.target_pathname, info.target_pathname)) {
|
||||
if (susfs_update_sus_kstat_inode(tmp_entry->info.target_pathname)) {
|
||||
err = 1;
|
||||
goto out_spin_unlock;
|
||||
}
|
||||
new_entry = kmalloc(sizeof(struct st_susfs_sus_kstat_hlist), GFP_KERNEL);
|
||||
if (!new_entry) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
err = 1;
|
||||
goto out_spin_unlock;
|
||||
}
|
||||
memcpy(&new_entry->info, &tmp_entry->info, sizeof(tmp_entry->info));
|
||||
SUSFS_LOGI("updating target_ino from '%lu' to '%lu' for pathname: '%s' in SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.target_ino, info.target_ino, info.target_pathname);
|
||||
new_entry->target_ino = info.target_ino;
|
||||
new_entry->info.target_ino = info.target_ino;
|
||||
if (info.spoofed_size > 0) {
|
||||
SUSFS_LOGI("updating spoofed_size from '%lld' to '%lld' for pathname: '%s' in SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.spoofed_size, info.spoofed_size, info.target_pathname);
|
||||
new_entry->info.spoofed_size = info.spoofed_size;
|
||||
}
|
||||
if (info.spoofed_blocks > 0) {
|
||||
SUSFS_LOGI("updating spoofed_blocks from '%llu' to '%llu' for pathname: '%s' in SUS_KSTAT_HLIST\n",
|
||||
new_entry->info.spoofed_blocks, info.spoofed_blocks, info.target_pathname);
|
||||
new_entry->info.spoofed_blocks = info.spoofed_blocks;
|
||||
}
|
||||
hash_del(&tmp_entry->node);
|
||||
kfree(tmp_entry);
|
||||
hash_add(SUS_KSTAT_HLIST, &new_entry->node, info.target_ino);
|
||||
goto out_spin_unlock;
|
||||
}
|
||||
}
|
||||
out_spin_unlock:
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat) {
|
||||
struct st_susfs_sus_kstat_hlist *entry;
|
||||
|
||||
hash_for_each_possible(SUS_KSTAT_HLIST, entry, node, ino) {
|
||||
if (entry->target_ino == ino) {
|
||||
stat->dev = entry->info.spoofed_dev;
|
||||
stat->ino = entry->info.spoofed_ino;
|
||||
stat->nlink = entry->info.spoofed_nlink;
|
||||
stat->size = entry->info.spoofed_size;
|
||||
stat->atime.tv_sec = entry->info.spoofed_atime_tv_sec;
|
||||
stat->atime.tv_nsec = entry->info.spoofed_atime_tv_nsec;
|
||||
stat->mtime.tv_sec = entry->info.spoofed_mtime_tv_sec;
|
||||
stat->mtime.tv_nsec = entry->info.spoofed_mtime_tv_nsec;
|
||||
stat->ctime.tv_sec = entry->info.spoofed_ctime_tv_sec;
|
||||
stat->ctime.tv_nsec = entry->info.spoofed_ctime_tv_nsec;
|
||||
stat->blocks = entry->info.spoofed_blocks;
|
||||
stat->blksize = entry->info.spoofed_blksize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino) {
|
||||
struct st_susfs_sus_kstat_hlist *entry;
|
||||
|
||||
hash_for_each_possible(SUS_KSTAT_HLIST, entry, node, ino) {
|
||||
if (entry->target_ino == ino) {
|
||||
*out_dev = entry->info.spoofed_dev;
|
||||
*out_ino = entry->info.spoofed_ino;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
|
||||
/* try_umount */
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
static LIST_HEAD(LH_TRY_UMOUNT_PATH);
|
||||
int susfs_add_try_umount(struct st_susfs_try_umount* __user user_info) {
|
||||
struct st_susfs_try_umount_list *cursor = NULL, *temp = NULL;
|
||||
struct st_susfs_try_umount_list *new_list = NULL;
|
||||
struct st_susfs_try_umount info;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(info))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(cursor, temp, &LH_TRY_UMOUNT_PATH, list) {
|
||||
if (unlikely(!strcmp(info.target_pathname, cursor->info.target_pathname))) {
|
||||
SUSFS_LOGE("target_pathname: '%s' is already created in LH_TRY_UMOUNT_PATH\n", info.target_pathname);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
new_list = kmalloc(sizeof(struct st_susfs_try_umount_list), GFP_KERNEL);
|
||||
if (!new_list) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(&new_list->info, &info, sizeof(info));
|
||||
|
||||
INIT_LIST_HEAD(&new_list->list);
|
||||
spin_lock(&susfs_spin_lock);
|
||||
list_add_tail(&new_list->list, &LH_TRY_UMOUNT_PATH);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
SUSFS_LOGI("target_pathname: '%s', mnt_mode: %d, is successfully added to LH_TRY_UMOUNT_PATH\n", new_list->info.target_pathname, new_list->info.mnt_mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void susfs_try_umount(uid_t target_uid) {
|
||||
struct st_susfs_try_umount_list *cursor = NULL;
|
||||
|
||||
// We should umount in reversed order
|
||||
list_for_each_entry_reverse(cursor, &LH_TRY_UMOUNT_PATH, list) {
|
||||
SUSFS_LOGI("umounting '%s' for uid: %d\n", cursor->info.target_pathname, target_uid);
|
||||
if (cursor->info.mnt_mode == TRY_UMOUNT_DEFAULT) {
|
||||
ksu_try_umount(cursor->info.target_pathname, false, 0);
|
||||
} else if (cursor->info.mnt_mode == TRY_UMOUNT_DETACH) {
|
||||
ksu_try_umount(cursor->info.target_pathname, false, MNT_DETACH);
|
||||
} else {
|
||||
SUSFS_LOGE("failed umounting '%s' for uid: %d, mnt_mode '%d' not supported\n",
|
||||
cursor->info.target_pathname, target_uid, cursor->info.mnt_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
void susfs_auto_add_try_umount_for_bind_mount(struct path *path) {
|
||||
struct st_susfs_try_umount_list *cursor = NULL, *temp = NULL;
|
||||
struct st_susfs_try_umount_list *new_list = NULL;
|
||||
char *pathname = NULL, *dpath = NULL;
|
||||
#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
|
||||
bool is_magic_mount_path = false;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
if (path->dentry->d_inode->i_state & INODE_STATE_SUS_KSTAT) {
|
||||
SUSFS_LOGI("skip adding path to try_umount list as its inode is flagged INODE_STATE_SUS_KSTAT already\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
pathname = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!pathname) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dpath = d_path(path, pathname, PAGE_SIZE);
|
||||
if (!dpath) {
|
||||
SUSFS_LOGE("dpath is NULL\n");
|
||||
goto out_free_pathname;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
|
||||
if (strstr(dpath, magic_mount_workdir)) {
|
||||
is_magic_mount_path = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
list_for_each_entry_safe(cursor, temp, &LH_TRY_UMOUNT_PATH, list) {
|
||||
#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
|
||||
if (is_magic_mount_path && strstr(dpath, cursor->info.target_pathname)) {
|
||||
goto out_free_pathname;
|
||||
}
|
||||
#endif
|
||||
if (unlikely(!strcmp(dpath, cursor->info.target_pathname))) {
|
||||
SUSFS_LOGE("target_pathname: '%s', ino: %lu, is already created in LH_TRY_UMOUNT_PATH\n",
|
||||
dpath, path->dentry->d_inode->i_ino);
|
||||
goto out_free_pathname;
|
||||
}
|
||||
}
|
||||
|
||||
new_list = kmalloc(sizeof(struct st_susfs_try_umount_list), GFP_KERNEL);
|
||||
if (!new_list) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
goto out_free_pathname;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
|
||||
if (is_magic_mount_path) {
|
||||
strncpy(new_list->info.target_pathname, dpath + strlen(magic_mount_workdir), SUSFS_MAX_LEN_PATHNAME-1);
|
||||
goto out_add_to_list;
|
||||
}
|
||||
#endif
|
||||
strncpy(new_list->info.target_pathname, dpath, SUSFS_MAX_LEN_PATHNAME-1);
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT
|
||||
out_add_to_list:
|
||||
#endif
|
||||
|
||||
new_list->info.mnt_mode = TRY_UMOUNT_DETACH;
|
||||
|
||||
INIT_LIST_HEAD(&new_list->list);
|
||||
spin_lock(&susfs_spin_lock);
|
||||
list_add_tail(&new_list->list, &LH_TRY_UMOUNT_PATH);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
SUSFS_LOGI("target_pathname: '%s', ino: %lu, mnt_mode: %d, is successfully added to LH_TRY_UMOUNT_PATH\n",
|
||||
new_list->info.target_pathname, path->dentry->d_inode->i_ino, new_list->info.mnt_mode);
|
||||
out_free_pathname:
|
||||
kfree(pathname);
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
|
||||
/* spoof_uname */
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
static spinlock_t susfs_uname_spin_lock;
|
||||
static struct st_susfs_uname my_uname;
|
||||
static void susfs_my_uname_init(void) {
|
||||
memset(&my_uname, 0, sizeof(my_uname));
|
||||
}
|
||||
|
||||
int susfs_set_uname(struct st_susfs_uname* __user user_info) {
|
||||
struct st_susfs_uname info;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(struct st_susfs_uname))) {
|
||||
SUSFS_LOGE("failed copying from userspace.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock(&susfs_uname_spin_lock);
|
||||
if (!strcmp(info.release, "default")) {
|
||||
strncpy(my_uname.release, utsname()->release, __NEW_UTS_LEN);
|
||||
} else {
|
||||
strncpy(my_uname.release, info.release, __NEW_UTS_LEN);
|
||||
}
|
||||
if (!strcmp(info.version, "default")) {
|
||||
strncpy(my_uname.version, utsname()->version, __NEW_UTS_LEN);
|
||||
} else {
|
||||
strncpy(my_uname.version, info.version, __NEW_UTS_LEN);
|
||||
}
|
||||
spin_unlock(&susfs_uname_spin_lock);
|
||||
SUSFS_LOGI("setting spoofed release: '%s', version: '%s'\n",
|
||||
my_uname.release, my_uname.version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void susfs_spoof_uname(struct new_utsname* tmp) {
|
||||
if (unlikely(my_uname.release[0] == '\0' || spin_is_locked(&susfs_uname_spin_lock)))
|
||||
return;
|
||||
strncpy(tmp->release, my_uname.release, __NEW_UTS_LEN);
|
||||
strncpy(tmp->version, my_uname.version, __NEW_UTS_LEN);
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
|
||||
/* set_log */
|
||||
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
void susfs_set_log(bool enabled) {
|
||||
spin_lock(&susfs_spin_lock);
|
||||
susfs_is_log_enabled = enabled;
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
if (susfs_is_log_enabled) {
|
||||
pr_info("susfs: enable logging to kernel");
|
||||
} else {
|
||||
pr_info("susfs: disable logging to kernel");
|
||||
}
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
|
||||
/* spoof_cmdline_or_bootconfig */
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||
static char *fake_cmdline_or_bootconfig = NULL;
|
||||
int susfs_set_cmdline_or_bootconfig(char* __user user_fake_cmdline_or_bootconfig) {
|
||||
int res;
|
||||
|
||||
if (!fake_cmdline_or_bootconfig) {
|
||||
// 4096 is enough I guess
|
||||
fake_cmdline_or_bootconfig = kmalloc(SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE, GFP_KERNEL);
|
||||
if (!fake_cmdline_or_bootconfig) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&susfs_spin_lock);
|
||||
memset(fake_cmdline_or_bootconfig, 0, SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE);
|
||||
res = strncpy_from_user(fake_cmdline_or_bootconfig, user_fake_cmdline_or_bootconfig, SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE-1);
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
|
||||
if (res > 0) {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
|
||||
SUSFS_LOGI("fake_cmdline_or_bootconfig is set, length of string: %lu\n", strlen(fake_cmdline_or_bootconfig));
|
||||
#else
|
||||
SUSFS_LOGI("fake_cmdline_or_bootconfig is set, length of string: %u\n", strlen(fake_cmdline_or_bootconfig));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
SUSFS_LOGI("failed setting fake_cmdline_or_bootconfig\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m) {
|
||||
if (fake_cmdline_or_bootconfig != NULL) {
|
||||
seq_puts(m, fake_cmdline_or_bootconfig);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* open_redirect */
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
static DEFINE_HASHTABLE(OPEN_REDIRECT_HLIST, 10);
|
||||
static int susfs_update_open_redirect_inode(struct st_susfs_open_redirect_hlist *new_entry) {
|
||||
struct path path_target;
|
||||
struct inode *inode_target;
|
||||
int err = 0;
|
||||
|
||||
err = kern_path(new_entry->target_pathname, LOOKUP_FOLLOW, &path_target);
|
||||
if (err) {
|
||||
SUSFS_LOGE("Failed opening file '%s'\n", new_entry->target_pathname);
|
||||
return err;
|
||||
}
|
||||
|
||||
inode_target = d_inode(path_target.dentry);
|
||||
if (!inode_target) {
|
||||
SUSFS_LOGE("inode_target is NULL\n");
|
||||
err = 1;
|
||||
goto out_path_put_target;
|
||||
}
|
||||
|
||||
spin_lock(&inode_target->i_lock);
|
||||
inode_target->i_state |= INODE_STATE_OPEN_REDIRECT;
|
||||
spin_unlock(&inode_target->i_lock);
|
||||
|
||||
out_path_put_target:
|
||||
path_put(&path_target);
|
||||
return err;
|
||||
}
|
||||
|
||||
int susfs_add_open_redirect(struct st_susfs_open_redirect* __user user_info) {
|
||||
struct st_susfs_open_redirect info;
|
||||
struct st_susfs_open_redirect_hlist *new_entry, *tmp_entry;
|
||||
struct hlist_node *tmp_node;
|
||||
int bkt;
|
||||
bool update_hlist = false;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(info))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock(&susfs_spin_lock);
|
||||
hash_for_each_safe(OPEN_REDIRECT_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;
|
||||
}
|
||||
}
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
|
||||
new_entry = kmalloc(sizeof(struct st_susfs_open_redirect_hlist), GFP_KERNEL);
|
||||
if (!new_entry) {
|
||||
SUSFS_LOGE("no enough memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
new_entry->target_ino = info.target_ino;
|
||||
strncpy(new_entry->target_pathname, info.target_pathname, SUSFS_MAX_LEN_PATHNAME-1);
|
||||
strncpy(new_entry->redirected_pathname, info.redirected_pathname, SUSFS_MAX_LEN_PATHNAME-1);
|
||||
if (susfs_update_open_redirect_inode(new_entry)) {
|
||||
SUSFS_LOGE("failed adding path '%s' to OPEN_REDIRECT_HLIST\n", new_entry->target_pathname);
|
||||
kfree(new_entry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock(&susfs_spin_lock);
|
||||
hash_add(OPEN_REDIRECT_HLIST, &new_entry->node, info.target_ino);
|
||||
if (update_hlist) {
|
||||
SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s', redirected_pathname: '%s', is successfully updated to OPEN_REDIRECT_HLIST\n",
|
||||
new_entry->target_ino, new_entry->target_pathname, new_entry->redirected_pathname);
|
||||
} else {
|
||||
SUSFS_LOGI("target_ino: '%lu', target_pathname: '%s' redirected_pathname: '%s', is successfully added to OPEN_REDIRECT_HLIST\n",
|
||||
new_entry->target_ino, new_entry->target_pathname, new_entry->redirected_pathname);
|
||||
}
|
||||
spin_unlock(&susfs_spin_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct filename* susfs_get_redirected_path(unsigned long ino) {
|
||||
struct st_susfs_open_redirect_hlist *entry;
|
||||
|
||||
hash_for_each_possible(OPEN_REDIRECT_HLIST, entry, node, ino) {
|
||||
if (entry->target_ino == ino) {
|
||||
SUSFS_LOGI("Redirect for ino: %lu\n", ino);
|
||||
return getname_kernel(entry->redirected_pathname);
|
||||
}
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
|
||||
/* 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 void ksu_susfs_enable_sus_su(void);
|
||||
extern void ksu_susfs_disable_sus_su(void);
|
||||
|
||||
int susfs_get_sus_su_working_mode(void) {
|
||||
return susfs_sus_su_working_mode;
|
||||
}
|
||||
|
||||
int susfs_sus_su(struct st_sus_su* __user user_info) {
|
||||
struct st_sus_su info;
|
||||
int last_working_mode = susfs_sus_su_working_mode;
|
||||
|
||||
if (copy_from_user(&info, user_info, sizeof(struct st_sus_su))) {
|
||||
SUSFS_LOGE("failed copying from userspace\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.mode == SUS_SU_WITH_HOOKS) {
|
||||
if (last_working_mode == SUS_SU_WITH_HOOKS) {
|
||||
SUSFS_LOGE("current sus_su mode is already %d\n", SUS_SU_WITH_HOOKS);
|
||||
return 1;
|
||||
}
|
||||
if (last_working_mode != SUS_SU_DISABLED) {
|
||||
SUSFS_LOGE("please make sure the current sus_su mode is %d first\n", SUS_SU_DISABLED);
|
||||
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);
|
||||
return 0;
|
||||
} else if (info.mode == SUS_SU_DISABLED) {
|
||||
if (last_working_mode == SUS_SU_DISABLED) {
|
||||
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;
|
||||
}
|
||||
out:
|
||||
if (copy_to_user(user_info, &info, sizeof(info)))
|
||||
SUSFS_LOGE("copy_to_user() failed\n");
|
||||
return 0;
|
||||
} else if (info.mode == SUS_SU_WITH_OVERLAY) {
|
||||
SUSFS_LOGE("sus_su mode %d is deprecated\n", SUS_SU_WITH_OVERLAY);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
|
||||
/* susfs_init */
|
||||
void susfs_init(void) {
|
||||
spin_lock_init(&susfs_spin_lock);
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
spin_lock_init(&susfs_uname_spin_lock);
|
||||
susfs_my_uname_init();
|
||||
#endif
|
||||
SUSFS_LOGI("susfs is initialized! version: " SUSFS_VERSION " \n");
|
||||
}
|
||||
|
||||
/* No module exit is needed becuase it should never be a loadable kernel module */
|
||||
//void __init susfs_exit(void)
|
||||
|
|
@ -71,6 +71,9 @@ struct vfsmount {
|
|||
#endif
|
||||
int mnt_flags;
|
||||
void *data;
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
u64 android_kabi_reserved4;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct file; /* forward dec */
|
||||
|
|
|
@ -863,6 +863,10 @@ struct user_struct {
|
|||
#if defined(CONFIG_PERF_EVENTS) || defined(CONFIG_BPF_SYSCALL)
|
||||
atomic_long_t locked_vm;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
u64 android_kabi_reserved2;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int uids_sysfs_init(void);
|
||||
|
@ -2184,6 +2188,11 @@ struct task_struct {
|
|||
/* A live task holds one reference. */
|
||||
atomic_t stack_refcount;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
u64 android_kabi_reserved8;
|
||||
#endif
|
||||
|
||||
/* CPU-specific state of this task */
|
||||
struct thread_struct thread;
|
||||
/*
|
||||
|
|
231
include/linux/susfs.h
Normal file
231
include/linux/susfs.h
Normal file
|
@ -0,0 +1,231 @@
|
|||
#ifndef KSU_SUSFS_H
|
||||
#define KSU_SUSFS_H
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/path.h>
|
||||
|
||||
#define SUSFS_VERSION "v1.5.3"
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
|
||||
#define SUSFS_VARIANT "NON-GKI"
|
||||
#else
|
||||
#define SUSFS_VARIANT "GKI"
|
||||
#endif
|
||||
|
||||
/********/
|
||||
/* ENUM */
|
||||
/********/
|
||||
/* shared with userspace ksu_susfs tool */
|
||||
#define CMD_SUSFS_ADD_SUS_PATH 0x55550
|
||||
#define CMD_SUSFS_ADD_SUS_MOUNT 0x55560
|
||||
#define CMD_SUSFS_ADD_SUS_KSTAT 0x55570
|
||||
#define CMD_SUSFS_UPDATE_SUS_KSTAT 0x55571
|
||||
#define CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY 0x55572
|
||||
#define CMD_SUSFS_ADD_TRY_UMOUNT 0x55580
|
||||
#define CMD_SUSFS_SET_UNAME 0x55590
|
||||
#define CMD_SUSFS_ENABLE_LOG 0x555a0
|
||||
#define CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG 0x555b0
|
||||
#define CMD_SUSFS_ADD_OPEN_REDIRECT 0x555c0
|
||||
#define CMD_SUSFS_RUN_UMOUNT_FOR_CURRENT_MNT_NS 0x555d0
|
||||
#define CMD_SUSFS_SHOW_VERSION 0x555e1
|
||||
#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2
|
||||
#define CMD_SUSFS_SHOW_VARIANT 0x555e3
|
||||
#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4
|
||||
#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0
|
||||
#define CMD_SUSFS_SUS_SU 0x60000
|
||||
|
||||
#define SUSFS_MAX_LEN_PATHNAME 256 // 256 should address many paths already unless you are doing some strange experimental stuff, then set your own desired length
|
||||
#define SUSFS_FAKE_CMDLINE_OR_BOOTCONFIG_SIZE 4096
|
||||
|
||||
#define TRY_UMOUNT_DEFAULT 0
|
||||
#define TRY_UMOUNT_DETACH 1
|
||||
|
||||
#define SUS_SU_DISABLED 0
|
||||
#define SUS_SU_WITH_OVERLAY 1 /* deprecated */
|
||||
#define SUS_SU_WITH_HOOKS 2
|
||||
|
||||
/*
|
||||
* inode->i_state => storing flag 'INODE_STATE_'
|
||||
* mount->mnt.android_kabi_reserved4 => storing original mnt_id
|
||||
* task_struct->android_kabi_reserved8 => storing last valid fake mnt_id
|
||||
* user_struct->android_kabi_reserved2 => storing flag 'USER_STRUCT_KABI2_'
|
||||
*/
|
||||
|
||||
#define INODE_STATE_SUS_PATH 16777216 // 1 << 24
|
||||
#define INODE_STATE_SUS_MOUNT 33554432 // 1 << 25
|
||||
#define INODE_STATE_SUS_KSTAT 67108864 // 1 << 26
|
||||
#define INODE_STATE_OPEN_REDIRECT 134217728 // 1 << 27
|
||||
|
||||
#define USER_STRUCT_KABI2_NON_ROOT_USER_APP_PROFILE 16777216 // 1 << 24, for distinguishing root/no-root granted user app process
|
||||
|
||||
/*********/
|
||||
/* MACRO */
|
||||
/*********/
|
||||
#define getname_safe(name) (name == NULL ? ERR_PTR(-EINVAL) : getname(name))
|
||||
#define putname_safe(name) (IS_ERR(name) ? NULL : putname(name))
|
||||
|
||||
/**********/
|
||||
/* STRUCT */
|
||||
/**********/
|
||||
/* sus_path */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
struct st_susfs_sus_path {
|
||||
unsigned long target_ino;
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
};
|
||||
|
||||
struct st_susfs_sus_path_hlist {
|
||||
unsigned long target_ino;
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
struct hlist_node node;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* sus_mount */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
struct st_susfs_sus_mount {
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
unsigned long target_dev;
|
||||
};
|
||||
|
||||
struct st_susfs_sus_mount_list {
|
||||
struct list_head list;
|
||||
struct st_susfs_sus_mount info;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* sus_kstat */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
struct st_susfs_sus_kstat {
|
||||
int is_statically;
|
||||
unsigned long target_ino; // the ino after bind mounted or overlayed
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
unsigned long spoofed_ino;
|
||||
unsigned long spoofed_dev;
|
||||
unsigned int spoofed_nlink;
|
||||
long long spoofed_size;
|
||||
long spoofed_atime_tv_sec;
|
||||
long spoofed_mtime_tv_sec;
|
||||
long spoofed_ctime_tv_sec;
|
||||
long spoofed_atime_tv_nsec;
|
||||
long spoofed_mtime_tv_nsec;
|
||||
long spoofed_ctime_tv_nsec;
|
||||
unsigned long spoofed_blksize;
|
||||
unsigned long long spoofed_blocks;
|
||||
};
|
||||
|
||||
struct st_susfs_sus_kstat_hlist {
|
||||
unsigned long target_ino;
|
||||
struct st_susfs_sus_kstat info;
|
||||
struct hlist_node node;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* try_umount */
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
struct st_susfs_try_umount {
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
int mnt_mode;
|
||||
};
|
||||
|
||||
struct st_susfs_try_umount_list {
|
||||
struct list_head list;
|
||||
struct st_susfs_try_umount info;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* spoof_uname */
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
struct st_susfs_uname {
|
||||
char release[__NEW_UTS_LEN+1];
|
||||
char version[__NEW_UTS_LEN+1];
|
||||
};
|
||||
#endif
|
||||
|
||||
/* open_redirect */
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
struct st_susfs_open_redirect {
|
||||
unsigned long target_ino;
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
char redirected_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
};
|
||||
|
||||
struct st_susfs_open_redirect_hlist {
|
||||
unsigned long target_ino;
|
||||
char target_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
char redirected_pathname[SUSFS_MAX_LEN_PATHNAME];
|
||||
struct hlist_node node;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* sus_su */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
struct st_sus_su {
|
||||
int mode;
|
||||
};
|
||||
#endif
|
||||
|
||||
/***********************/
|
||||
/* FORWARD DECLARATION */
|
||||
/***********************/
|
||||
/* sus_path */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
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
|
||||
int susfs_add_sus_mount(struct st_susfs_sus_mount* __user user_info);
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
int susfs_auto_add_sus_bind_mount(const char *pathname, struct path *path_target);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
void susfs_auto_add_sus_ksu_default_mount(const char __user *to_pathname);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
|
||||
/* sus_kstat */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
|
||||
int susfs_add_sus_kstat(struct st_susfs_sus_kstat* __user user_info);
|
||||
int susfs_update_sus_kstat(struct st_susfs_sus_kstat* __user user_info);
|
||||
void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
|
||||
void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino);
|
||||
#endif
|
||||
/* try_umount */
|
||||
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
int susfs_add_try_umount(struct st_susfs_try_umount* __user user_info);
|
||||
void susfs_try_umount(uid_t target_uid);
|
||||
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
void susfs_auto_add_try_umount_for_bind_mount(struct path *path);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
|
||||
/* spoof_uname */
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
int susfs_set_uname(struct st_susfs_uname* __user user_info);
|
||||
void susfs_spoof_uname(struct new_utsname* tmp);
|
||||
#endif
|
||||
/* set_log */
|
||||
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
|
||||
void susfs_set_log(bool enabled);
|
||||
#endif
|
||||
/* spoof_cmdline_or_bootconfig */
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
|
||||
int susfs_set_cmdline_or_bootconfig(char* __user user_fake_boot_config);
|
||||
int susfs_spoof_cmdline_or_bootconfig(struct seq_file *m);
|
||||
#endif
|
||||
/* open_redirect */
|
||||
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
|
||||
int susfs_add_open_redirect(struct st_susfs_open_redirect* __user user_info);
|
||||
struct filename* susfs_get_redirected_path(unsigned long ino);
|
||||
#endif
|
||||
/* sus_su */
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
int susfs_get_sus_su_working_mode(void);
|
||||
int susfs_sus_su(struct st_sus_su* __user user_info);
|
||||
#endif
|
||||
/* susfs_init */
|
||||
void susfs_init(void);
|
||||
|
||||
#endif
|
|
@ -678,8 +678,19 @@ static int s_show(struct seq_file *m, void *p)
|
|||
seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
|
||||
type, iter->name, iter->module_name);
|
||||
} else
|
||||
|
||||
#ifndef CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
|
||||
seq_printf(m, "%pK %c %s\n", (void *)iter->value,
|
||||
iter->type, iter->name);
|
||||
#else
|
||||
{
|
||||
if (strstr(iter->name, "ksu_") || !strncmp(iter->name, "susfs_", 6) || !strncmp(iter->name, "ksud", 4)) {
|
||||
return 0;
|
||||
}
|
||||
seq_printf(m, "%pK %c %s\n", (void *)iter->value,
|
||||
iter->type, iter->name);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1340,6 +1340,10 @@ static int override_release(char __user *release, size_t len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
extern void susfs_spoof_uname(struct new_utsname* tmp);
|
||||
#endif
|
||||
|
||||
SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
|
||||
{
|
||||
struct new_utsname tmp;
|
||||
|
@ -1353,6 +1357,9 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
|
|||
pr_debug("fake uname: %s/%d release=%s\n",
|
||||
current->comm, current->pid, tmp.release);
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
|
||||
susfs_spoof_uname(&tmp);
|
||||
#endif
|
||||
up_read(&uts_sem);
|
||||
if (copy_to_user(name, &tmp, sizeof(tmp)))
|
||||
return -EFAULT;
|
||||
|
|
|
@ -4,9 +4,9 @@ exec 9>.kernelsu-fetch-lock
|
|||
flock -n 9 || exit 0
|
||||
[[ $(( $(date +%s) - $(stat -c %Y "drivers/kernelsu/.check" 2>/dev/null || echo 0) )) -gt 86400 ]] || exit 0
|
||||
|
||||
AUTHOR="xxmustafacooTR"
|
||||
REPO="KernelSU"
|
||||
VERSION=`curl -s -I -k "https://api.github.com/repos/$AUTHOR/$REPO/commits?per_page=1" | sed -n '/^[Ll]ink:/ s/.*"next".*page=\([0-9]*\).*"last".*/\1/p'`
|
||||
AUTHOR="rifsxd"
|
||||
REPO="KernelSU-Next"
|
||||
VERSION=`curl -s -I -k "https://api.github.com/repos/$AUTHOR/$REPO/commits?sha=next-susfs-4.9&per_page=1" | sed -n '/^[Ll]ink:/ s/.*"next".*page=\([0-9]*\).*"last".*/\1/p'`
|
||||
|
||||
if [[ -f drivers/kernelsu/.version && *$(cat drivers/kernelsu/.version)* == *$VERSION* ]]; then
|
||||
touch drivers/kernelsu/.check
|
||||
|
@ -17,7 +17,7 @@ fi
|
|||
rm -rf drivers/kernelsu
|
||||
mkdir -p drivers/kernelsu
|
||||
cd drivers/kernelsu
|
||||
wget -q -O - https://github.com/$AUTHOR/$REPO/archive/refs/heads/main.tar.gz | tar -xz --strip=2 "$REPO-main/kernel"
|
||||
wget -q -O - https://github.com/$AUTHOR/$REPO/archive/refs/heads/next-susfs-4.9.tar.gz | tar -xz --strip=2 "$REPO-next-susfs-4.9/kernel"
|
||||
echo $VERSION >> .version
|
||||
touch .check
|
||||
|
||||
|
|
1
susfs4ksu
Submodule
1
susfs4ksu
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit df4332728f0c56842c8c0a1bc1d357f3f3c96a7c
|
31
variables.sh
31
variables.sh
|
@ -1,23 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
export PATH=/home/$USER/Android/Toolchains/clang/bin:/home/$USER/Android/Toolchains/clang/lib:${PATH}
|
||||
export CLANG_TRIPLE=/home/$USER/Android/Toolchains/clang/bin/aarch64-linux-gnu-
|
||||
export CROSS_COMPILE=/home/$USER/Android/Toolchains/clang/bin/aarch64-linux-gnu-
|
||||
export CROSS_COMPILE_ARM32=/home/$USER/Android/Toolchains/clang/bin/arm-linux-gnueabi-
|
||||
export CC=/home/$USER/Android/Toolchains/clang/bin/clang
|
||||
export REAL_CC=/home/$USER/Android/Toolchains/clang/bin/clang
|
||||
export LD=/home/$USER/Android/Toolchains/clang/bin/ld.lld
|
||||
export AR=/home/$USER/Android/Toolchains/clang/bin/llvm-ar
|
||||
export NM=/home/$USER/Android/Toolchains/clang/bin/llvm-nm
|
||||
export OBJCOPY=/home/$USER/Android/Toolchains/clang/bin/llvm-objcopy
|
||||
export OBJDUMP=/home/$USER/Android/Toolchains/clang/bin/llvm-objdump
|
||||
export READELF=/home/$USER/Android/Toolchains/clang/bin/llvm-readelf
|
||||
export STRIP=/home/$USER/Android/Toolchains/clang/bin/llvm-strip
|
||||
export PATH=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin:/home/$USER/galaxybuild-project/Toolchains/clang-r522817/lib:${PATH}
|
||||
export CLANG_TRIPLE=/home/$USER/galaxybuild-project/Toolchains/clang/bin/aarch64-linux-gnu-
|
||||
export CROSS_COMPILE=/home/$USER/galaxybuild-project/Toolchains/clang/bin/aarch64-linux-gnu-
|
||||
export CROSS_COMPILE_ARM32=/home/$USER/galaxybuild-project/Toolchains/clang/bin/arm-linux-gnueabi-
|
||||
export CC=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/clang
|
||||
export REAL_CC=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/clang
|
||||
export LD=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/ld.lld
|
||||
export AR=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/llvm-ar
|
||||
export NM=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/llvm-nm
|
||||
export OBJCOPY=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/llvm-objcopy
|
||||
export OBJDUMP=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/llvm-objdump
|
||||
export READELF=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/llvm-readelf
|
||||
export STRIP=/home/$USER/galaxybuild-project/Toolchains/clang-r522817/bin/llvm-strip
|
||||
export LLVM=1 && export LLVM_IAS=1
|
||||
export KALLSYMS_EXTRA_PASS=1
|
||||
|
||||
export ARCH=arm64 && export SUBARCH=arm64
|
||||
ZIP_DIR="/home/$USER/Android/Kernel/Zip"
|
||||
ZIP_DIR="/home/$USER/galaxybuild-project/xxtr-zip"
|
||||
KERNEL_NAME="Kernel"
|
||||
DTB_NAME="Dtb"
|
||||
CUR_DIR=$PWD
|
||||
|
@ -71,8 +71,9 @@ clean() {
|
|||
}
|
||||
|
||||
patch_kernelsu() {
|
||||
printf "Enabling KernelSU\n"
|
||||
printf "Enabling KernelSU (NEXT)\n"
|
||||
sed -i 's/# CONFIG_KSU is not set/CONFIG_KSU=y/g' "$CUR_DIR"/arch/arm64/configs/exynos9810_temp_defconfig
|
||||
sed -i 's/# CONFIG_KSU_SUSFS is not set/CONFIG_KSU_SUSFS=y/g' "$CUR_DIR"/arch/arm64/configs/exynos9810_temp_defconfig
|
||||
KERNEL_NAME="$KERNEL_NAME-ksu"
|
||||
}
|
||||
|
||||
|
|
2
zip.sh
2
zip.sh
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
printf "Zipping\n"
|
||||
ZIP_DIR="/home/$USER/Android/Kernel/Zip"
|
||||
ZIP_DIR="/home/$USER/galaxybuild-project/xxtr-zip"
|
||||
cd $ZIP_DIR
|
||||
./zip.sh
|
Loading…
Add table
Add a link
Reference in a new issue