From b21cdd460e54a1076c99b3ccc35b1c537ca05485 Mon Sep 17 00:00:00 2001 From: Rissu <90097027+rsuntk@users.noreply.github.com> Date: Thu, 22 Aug 2024 05:08:46 +0700 Subject: [PATCH] hook_patch: Add diff file --- hook_patch/4.14_hook_patch.diff | 208 ++++++++++++++++++++++++++ hook_patch/4.19_hook_patch.diff | 201 +++++++++++++++++++++++++ hook_patch/4.4_hook_patch.diff | 233 +++++++++++++++++++++++++++++ hook_patch/4.9_hook_patch.diff | 251 ++++++++++++++++++++++++++++++++ 4 files changed, 893 insertions(+) create mode 100644 hook_patch/4.14_hook_patch.diff create mode 100644 hook_patch/4.19_hook_patch.diff create mode 100644 hook_patch/4.4_hook_patch.diff create mode 100644 hook_patch/4.9_hook_patch.diff diff --git a/hook_patch/4.14_hook_patch.diff b/hook_patch/4.14_hook_patch.diff new file mode 100644 index 000000000000..d7e7629aa70f --- /dev/null +++ b/hook_patch/4.14_hook_patch.diff @@ -0,0 +1,208 @@ +4.14 KernelSU Hook Patch +* Make sure to disable CONFIG_KPROBE in your device's defconfig + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1890,11 +1890,14 @@ static int __do_execve_file(int fd, struct filename *filename, + return retval; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_execveat_hook __read_mostly; ++extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, ++ void *envp, int *flags); ++extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, ++ void *argv, void *envp, int *flags); ++#endif + + /* + * sys_execve() executes a new program. + */ + static int do_execveat_common(int fd, struct filename *filename, + struct user_arg_ptr argv, + struct user_arg_ptr envp, + int flags) + { + char *pathbuf = NULL; + struct linux_binprm *bprm; + struct file *file; + struct files_struct *displaced; + int retval; + ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_execveat_hook)) ++ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); ++ else ++ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags); ++#endif + +--- a/fs/open.c ++++ b/fs/open.c +@@ -348,6 +348,8 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + return ksys_fallocate(fd, mode, offset, len); + } + ++#ifdef CONFIG_KSU ++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 +@@ -355,6 +357,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + */ + SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) + { + const struct cred *old_cred; + struct cred *override_cred; + struct path path; + struct inode *inode; + struct vfsmount *mnt; + int res; + unsigned int lookup_flags = LOOKUP_FOLLOW; ++#ifdef CONFIG_KSU ++ ksu_handle_faccessat(&dfd, &filename, &mode, NULL); ++#endif + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; + +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -434,10 +434,14 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos) + } + EXPORT_SYMBOL(kernel_read); + ++#ifdef CONFIG_KSU ++extern bool ksu_vfs_read_hook __read_mostly; ++extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, ++ size_t *count_ptr, loff_t **pos); ++#endif + ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) + { + ssize_t ret; ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_vfs_read_hook)) ++ ksu_handle_vfs_read(&file, &buf, &count, &pos); ++#endif ++ + if (!(file->f_mode & FMODE_READ)) + return -EBADF; + if (!(file->f_mode & FMODE_CAN_READ)) + +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -148,6 +148,8 @@ 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 +@@ -170,6 +172,7 @@ 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); ++#endif + if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | + AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0) + return -EINVAL; + +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -367,10 +367,13 @@ static int input_get_disposition(struct input_dev *dev, + return disposition; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_input_hook __read_mostly; ++extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value); ++#endif ++ + static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) + { + int disposition = input_get_disposition(dev, type, code, &value); ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_input_hook)) ++ ksu_handle_input_handle_event(&type, &code, &value); ++#endif + + if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) + add_input_randomness(type, code, value); + +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + return dentry; + } + ++#ifdef CONFIG_KSU ++extern int ksu_handle_devpts(struct inode*); ++#endif ++ + /** + * devpts_get_priv -- get private data for a slave + * @pts_inode: inode of the slave +@@ -610,6 +612,7 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + */ + void *devpts_get_priv(struct dentry *dentry) + { ++#ifdef CONFIG_KSU ++ ksu_handle_devpts(dentry->d_inode); ++#endif + if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC) + return NULL; + return dentry->d_fsdata; + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1739,6 +1739,39 @@ static inline bool may_mandlock(void) + } + #endif + ++#ifdef CONFIG_KSU ++static int can_umount(const struct path *path, int flags) ++{ ++ struct mount *mnt = real_mount(path->mnt); ++ ++ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) ++ return -EINVAL; ++ 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; ++} ++ ++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; ++} ++#endif ++ + /* + * Now umount can handle mount points as well as block devices. + * This is important for filesystems which use unnamed block devices. diff --git a/hook_patch/4.19_hook_patch.diff b/hook_patch/4.19_hook_patch.diff new file mode 100644 index 000000000000..17b594dd1b12 --- /dev/null +++ b/hook_patch/4.19_hook_patch.diff @@ -0,0 +1,201 @@ +4.19 KernelSU Hook Patch +* Make sure to disable CONFIG_KPROBE in your device's defconfig + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1890,11 +1890,14 @@ static int __do_execve_file(int fd, struct filename *filename, + return retval; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_execveat_hook __read_mostly; ++extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, ++ void *envp, int *flags); ++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, + int flags) + { ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_execveat_hook)) ++ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); ++ else ++ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags); ++#endif + return __do_execve_file(fd, filename, argv, envp, flags, NULL); + } + +--- a/fs/open.c ++++ b/fs/open.c +@@ -348,6 +348,8 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + return ksys_fallocate(fd, mode, offset, len); + } + ++#ifdef CONFIG_KSU ++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 +@@ -355,6 +357,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + */ + long do_faccessat(int dfd, const char __user *filename, int mode) + { + const struct cred *old_cred; + struct cred *override_cred; + struct path path; + struct inode *inode; + struct vfsmount *mnt; + int res; + unsigned int lookup_flags = LOOKUP_FOLLOW; ++#ifdef CONFIG_KSU ++ ksu_handle_faccessat(&dfd, &filename, &mode, NULL); ++#endif + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; + +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -434,10 +434,14 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos) + } + EXPORT_SYMBOL(kernel_read); + ++#ifdef CONFIG_KSU ++extern bool ksu_vfs_read_hook __read_mostly; ++extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, ++ size_t *count_ptr, loff_t **pos); ++#endif + ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) + { + ssize_t ret; ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_vfs_read_hook)) ++ ksu_handle_vfs_read(&file, &buf, &count, &pos); ++#endif ++ + if (!(file->f_mode & FMODE_READ)) + return -EBADF; + if (!(file->f_mode & FMODE_CAN_READ)) + +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -148,6 +148,8 @@ 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 +@@ -170,6 +172,7 @@ 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); ++#endif + if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | + AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0) + return -EINVAL; + + +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -367,10 +367,13 @@ static int input_get_disposition(struct input_dev *dev, + return disposition; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_input_hook __read_mostly; ++extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value); ++#endif ++ + static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) + { + int disposition = input_get_disposition(dev, type, code, &value); ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_input_hook)) ++ ksu_handle_input_handle_event(&type, &code, &value); ++#endif + + if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) + add_input_randomness(type, code, value); + +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + return dentry; + } + ++#ifdef CONFIG_KSU ++extern int ksu_handle_devpts(struct inode*); ++#endif ++ + /** + * devpts_get_priv -- get private data for a slave + * @pts_inode: inode of the slave +@@ -610,6 +612,7 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + */ + void *devpts_get_priv(struct dentry *dentry) + { ++ #ifdef CONFIG_KSU ++ ksu_handle_devpts(dentry->d_inode); ++ #endif + if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC) + return NULL; + return dentry->d_fsdata; + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1739,6 +1739,39 @@ static inline bool may_mandlock(void) + } + #endif + ++#ifdef CONFIG_KSU ++static int can_umount(const struct path *path, int flags) ++{ ++ struct mount *mnt = real_mount(path->mnt); ++ ++ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) ++ return -EINVAL; ++ 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; ++} ++ ++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; ++} ++#endif ++ + /* + * Now umount can handle mount points as well as block devices. + * This is important for filesystems which use unnamed block devices. diff --git a/hook_patch/4.4_hook_patch.diff b/hook_patch/4.4_hook_patch.diff new file mode 100644 index 000000000000..b0ab35a90cb1 --- /dev/null +++ b/hook_patch/4.4_hook_patch.diff @@ -0,0 +1,233 @@ +4.4 KernelSU Hook Patch +* Make sure to disable CONFIG_KPROBE in your device's defconfig + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1890,11 +1890,14 @@ static int __do_execve_file(int fd, struct filename *filename, + return retval; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_execveat_hook __read_mostly; ++extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, ++ void *envp, int *flags); ++extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, ++ void *argv, void *envp, int *flags); ++#endif + /* + * sys_execve() executes a new program. + */ + static int do_execveat_common(int fd, struct filename *filename, + struct user_arg_ptr argv, + struct user_arg_ptr envp, + int flags) + { + char *pathbuf = NULL; + struct linux_binprm *bprm; + struct file *file; + struct files_struct *displaced; + int retval; + ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_execveat_hook)) ++ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); ++ else ++ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags); ++#endif + + if (IS_ERR(filename)) + return PTR_ERR(filename); + } + +--- a/fs/open.c ++++ b/fs/open.c +@@ -348,6 +348,8 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + return ksys_fallocate(fd, mode, offset, len); + } + ++#ifdef CONFIG_KSU ++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 +@@ -355,6 +357,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + */ + SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) + { + const struct cred *old_cred; + struct cred *override_cred; + struct path path; + struct inode *inode; + int res; + unsigned int lookup_flags = LOOKUP_FOLLOW; ++#ifdef CONFIG_KSU ++ ksu_handle_faccessat(&dfd, &filename, &mode, NULL); ++#endif + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; + +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -434,10 +434,14 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos) + } + EXPORT_SYMBOL(__vfs_read); + ++#ifdef CONFIG_KSU ++extern bool ksu_vfs_read_hook __read_mostly; ++extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, ++ size_t *count_ptr, loff_t **pos); ++#endif + ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) + { + ssize_t ret; ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_vfs_read_hook)) ++ ksu_handle_vfs_read(&file, &buf, &count, &pos); ++#endif ++ + if (!(file->f_mode & FMODE_READ)) + return -EBADF; + if (!(file->f_mode & FMODE_CAN_READ)) + return -EINVAL; + +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -148,6 +148,8 @@ 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 ++ + int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, + int flag) + { + struct path path; + int error = -EINVAL; + unsigned int lookup_flags = 0; + ++#ifdef CONFIG_KSU ++ ksu_handle_stat(&dfd, &filename, &flag); ++#endif + + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | + AT_EMPTY_PATH)) != 0) + goto out; + +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -367,10 +367,13 @@ static int input_get_disposition(struct input_dev *dev, + return disposition; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_input_hook __read_mostly; ++extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value); ++#endif ++ + static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) + { + int disposition = input_get_disposition(dev, type, code, &value); + ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_input_hook)) ++ ksu_handle_input_handle_event(&type, &code, &value); ++#endif + + if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) + add_input_randomness(type, code, value); + +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + return dentry; + } + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1739,6 +1739,39 @@ static inline bool may_mandlock(void) + } + #endif + ++#ifdef CONFIG_KSU ++static int can_umount(const struct path *path, int flags) ++{ ++ struct mount *mnt = real_mount(path->mnt); ++ ++ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) ++ return -EINVAL; ++ 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; ++} ++ ++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; ++} ++#endif ++ + /* + * Now umount can handle mount points as well as block devices. + * This is important for filesystems which use unnamed block devices. + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -2238,9 +2238,12 @@ + const struct task_security_struct *old_tsec, + const struct task_security_struct *new_tsec) + { ++ static u32 ksu_sid; ++ char *secdata; + int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS); + int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID); +- int rc; ++ int rc, error; ++ u32 seclen; + + if (!nnp && !nosuid) + return 0; /* neither NNP nor nosuid */ +@@ -2248,6 +2251,19 @@ + if (new_tsec->sid == old_tsec->sid) + return 0; /* No change in credentials */ + ++ ++ if (!ksu_sid) { ++ security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid); ++ } ++ ++ error = security_secid_to_secctx(old_tsec->sid, &secdata, &seclen); ++ if (!error) { ++ rc = strcmp("u:r:init:s0", secdata); ++ security_release_secctx(secdata, seclen); ++ if (rc == 0 && new_tsec->sid == ksu_sid) { ++ return 0; ++ } ++ } ++ + /* + * The only transitions we permit under NNP or nosuid + * are transitions to bounded SIDs, i.e. SIDs that are diff --git a/hook_patch/4.9_hook_patch.diff b/hook_patch/4.9_hook_patch.diff new file mode 100644 index 000000000000..c953f17234c4 --- /dev/null +++ b/hook_patch/4.9_hook_patch.diff @@ -0,0 +1,251 @@ +4.9 KernelSU Hook Patch +* Make sure to disable CONFIG_KPROBE in your device's defconfig + +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1890,11 +1890,14 @@ static int __do_execve_file(int fd, struct filename *filename, + return retval; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_execveat_hook __read_mostly; ++extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, ++ void *envp, int *flags); ++extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, ++ void *argv, void *envp, int *flags); ++#endif + /* + * sys_execve() executes a new program. + */ + static int do_execveat_common(int fd, struct filename *filename, + struct user_arg_ptr argv, + struct user_arg_ptr envp, + int flags) + { + char *pathbuf = NULL; + struct linux_binprm *bprm; + struct file *file; + struct files_struct *displaced; + int retval; + ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_execveat_hook)) ++ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); ++ else ++ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags); ++#endif + + if (IS_ERR(filename)) + return PTR_ERR(filename); + } + +--- a/fs/open.c ++++ b/fs/open.c +@@ -348,6 +348,8 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + return ksys_fallocate(fd, mode, offset, len); + } + ++#ifdef CONFIG_KSU ++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 +@@ -355,6 +357,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) + */ + SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) + { + const struct cred *old_cred; + struct cred *override_cred; + struct path path; + struct inode *inode; + int res; + unsigned int lookup_flags = LOOKUP_FOLLOW; ++#ifdef CONFIG_KSU ++ ksu_handle_faccessat(&dfd, &filename, &mode, NULL); ++#endif + + if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ + return -EINVAL; + +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -434,10 +434,14 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos) + } + EXPORT_SYMBOL(__vfs_read); + ++#ifdef CONFIG_KSU ++extern bool ksu_vfs_read_hook __read_mostly; ++extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, ++ size_t *count_ptr, loff_t **pos); ++#endif + ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) + { + ssize_t ret; ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_vfs_read_hook)) ++ ksu_handle_vfs_read(&file, &buf, &count, &pos); ++#endif ++ + if (!(file->f_mode & FMODE_READ)) + return -EBADF; + if (!(file->f_mode & FMODE_CAN_READ)) + return -EINVAL; + +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -148,6 +148,8 @@ 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 ++ + int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, + int flag) + { + struct path path; + int error = -EINVAL; + unsigned int lookup_flags = 0; + ++#ifdef CONFIG_KSU ++ ksu_handle_stat(&dfd, &filename, &flag); ++#endif + + if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | + AT_EMPTY_PATH)) != 0) + goto out; + +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -367,10 +367,13 @@ static int input_get_disposition(struct input_dev *dev, + return disposition; + } + ++#ifdef CONFIG_KSU ++extern bool ksu_input_hook __read_mostly; ++extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value); ++#endif ++ + static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) + { + int disposition = input_get_disposition(dev, type, code, &value); + ++#ifdef CONFIG_KSU ++ if (unlikely(ksu_input_hook)) ++ ksu_handle_input_handle_event(&type, &code, &value); ++#endif + + if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) + add_input_randomness(type, code, value); + +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + return dentry; + } + ++#ifdef CONFIG_KSU ++extern int ksu_handle_devpts(struct inode*); ++#endif ++ + /** + * devpts_get_priv -- get private data for a slave + * @pts_inode: inode of the slave +@@ -610,6 +612,7 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv) + */ + void *devpts_get_priv(struct dentry *dentry) + { ++#ifdef CONFIG_KSU ++ ksu_handle_devpts(dentry->d_inode); ++#endif + if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC) + return NULL; + return dentry->d_fsdata; + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1739,6 +1739,39 @@ static inline bool may_mandlock(void) + } + #endif + ++#ifdef CONFIG_KSU ++static int can_umount(const struct path *path, int flags) ++{ ++ struct mount *mnt = real_mount(path->mnt); ++ ++ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) ++ return -EINVAL; ++ 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; ++} ++ ++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; ++} ++#endif ++ + /* + * Now umount can handle mount points as well as block devices. + * This is important for filesystems which use unnamed block devices. + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -2238,9 +2238,12 @@ + const struct task_security_struct *old_tsec, + const struct task_security_struct *new_tsec) + { ++ static u32 ksu_sid; ++ char *secdata; + int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS); + int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID); +- int rc; ++ int rc, error; ++ u32 seclen; + + if (!nnp && !nosuid) + return 0; /* neither NNP nor nosuid */ +@@ -2248,6 +2251,19 @@ + if (new_tsec->sid == old_tsec->sid) + return 0; /* No change in credentials */ + ++ ++ if (!ksu_sid) { ++ security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid); ++ } ++ ++ error = security_secid_to_secctx(old_tsec->sid, &secdata, &seclen); ++ if (!error) { ++ rc = strcmp("u:r:init:s0", secdata); ++ security_release_secctx(secdata, seclen); ++ if (rc == 0 && new_tsec->sid == ksu_sid) { ++ return 0; ++ } ++ } ++ + /* + * The only transitions we permit under NNP or nosuid + * are transitions to bounded SIDs, i.e. SIDs that are