diff --git a/kernel/Makefile b/kernel/Makefile index 6121ec94..02927cef 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -12,13 +12,9 @@ kernelsu-objs += throne_tracker.o kernelsu-objs += ksud.o kernelsu-objs += embed_ksud.o kernelsu-objs += kernel_compat.o +kernelsu-objs += file_wrapper.o kernelsu-objs += throne_comm.o -ifeq ($(CONFIG_KSU_TRACEPOINT_HOOK), y) -kernelsu-objs += ksu_trace.o -endif - - kernelsu-objs += selinux/selinux.o kernelsu-objs += selinux/sepolicy.o kernelsu-objs += selinux/rules.o @@ -89,12 +85,13 @@ ccflags-y += -DKSU_VERSION=$(KSU_VERSION) ccflags-y += -DKSU_VERSION_FULL=\"$(KSU_VERSION_FULL)\" # Checks hooks state -ifeq ($(CONFIG_KSU_KPROBES_HOOK), y) -$(info -- SukiSU: CONFIG_KSU_KPROBES_HOOK) -else ifeq ($(CONFIG_KSU_TRACEPOINT_HOOK), y) -$(info -- SukiSU: CONFIG_KSU_TRACEPOINT_HOOK) -else ifeq ($(CONFIG_KSU_MANUAL_HOOK), y) -$(info -- SukiSU: CONFIG_KSU_MANUAL_HOOK) +ifeq ($(CONFIG_KSU_MANUAL_HOOK), y) +ccflags-y += -DKSU_MANUAL_HOOK +$(info -- SukiSU: KSU_MANUAL_HOOK) +else +ccflags-y += -DKSU_HAVE_SYSCALL_TRACEPOINTS_HOOK +ccflags-y += -DKSU_KPROBES_HOOK +$(info -- SukiSU: KSU_TRACEPOINT_HOOK) endif # SELinux drivers check diff --git a/kernel/arch.h b/kernel/arch.h index 3222c0a6..761647d8 100644 --- a/kernel/arch.h +++ b/kernel/arch.h @@ -70,7 +70,7 @@ #endif #else -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK #error "Unsupported arch" #endif #endif diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 616689e1..85c68867 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -43,7 +43,7 @@ #include "kernel_compat.h" #include "supercalls.h" -bool ksu_module_mounted = false; +bool ksu_module_mounted __read_mostly = false; #ifndef DEVPTS_SUPER_MAGIC #define DEVPTS_SUPER_MAGIC 0x1cd1 @@ -55,8 +55,6 @@ extern int __ksu_handle_devpts(struct inode *inode); // sucompat.c bool ksu_is_compat __read_mostly = false; #endif -extern int handle_sepolicy(unsigned long arg3, void __user *arg4); - static bool ksu_kernel_umount_enabled = true; static int kernel_umount_feature_get(u64 *value) @@ -360,7 +358,7 @@ static void ksu_do_umount_lists(void) try_umount("/sbin", false, MNT_DETACH); } -#if defined(MODULE) || defined(CONFIG_KSU_KPROBES_HOOK) +#if defined(MODULE) || defined(KSU_KPROBES_HOOK) struct umount_tw { struct callback_head cb; const struct cred *old_cred; @@ -438,7 +436,8 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) spin_unlock_irq(¤t->sighand->siglock); if (ksu_get_manager_uid() == new_uid.val) { - pr_info("install fd for ksu manager(uid=%d)\n", new_uid.val); + pr_info("install fd for ksu manager(uid=%d)\n", + new_uid.val); ksu_install_fd(); } @@ -477,7 +476,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) current->pid); #endif -#if defined(MODULE) || defined(CONFIG_KSU_KPROBES_HOOK) +#if defined(MODULE) || defined(KSU_KPROBES_HOOK) struct umount_tw *tw; tw = kmalloc(sizeof(*tw), GFP_ATOMIC); if (!tw) @@ -568,9 +567,9 @@ int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, } // -- For old kernel compat? -#if !defined(MODULE) && !defined(CONFIG_KSU_KPROBES_HOOK) -static int ksu_task_fix_setuid(struct cred *new, - const struct cred *old, int flags) +#if !defined(MODULE) && !defined(KSU_KPROBE_HOOK) +static int ksu_task_fix_setuid(struct cred *new, const struct cred *old, + int flags) { return ksu_handle_setuid(new, old); } @@ -598,7 +597,7 @@ static int ksu_key_permission(key_ref_t key_ref, const struct cred *cred, static struct security_hook_list ksu_hooks[] = { LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid), LSM_HOOK_INIT(inode_permission, ksu_inode_permission), - #ifndef CONFIG_KSU_KPROBES_HOOK + #ifndef KSU_KPROBES_HOOK LSM_HOOK_INIT(bprm_check_security, ksu_bprm_check), #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ @@ -633,7 +632,7 @@ static void ksu_lsm_hook_init(void) #endif // -- For KPROBE and LKM handler -#if defined(MODULE) || defined(CONFIG_KSU_KPROBES_HOOK) +#if defined(MODULE) || defined(KSU_KPROBES_HOOK) static int reboot_handler_pre(struct kprobe *p, struct pt_regs *regs) { struct pt_regs *real_regs = PT_REAL_REGS(regs); diff --git a/kernel/core_hook.h b/kernel/core_hook.h index 6ed328a0..47405fa9 100644 --- a/kernel/core_hook.h +++ b/kernel/core_hook.h @@ -7,4 +7,10 @@ void __init ksu_core_init(void); void ksu_core_exit(void); +void escape_to_root(void); + +void nuke_ext4_sysfs(void); + +extern bool ksu_module_mounted; + #endif diff --git a/kernel/file_wrapper.c b/kernel/file_wrapper.c new file mode 100644 index 00000000..f7e4b06b --- /dev/null +++ b/kernel/file_wrapper.c @@ -0,0 +1,473 @@ +#include "linux/export.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "allowlist.h" +#include "klog.h" // IWYU pragma: keep +#include "ksu.h" +#include "ksud.h" +#include "manager.h" +#include "selinux/selinux.h" +#include "core_hook.h" +#include "objsec.h" + +#include "file_wrapper.h" + +#ifndef __poll_t +typedef unsigned __bitwise __poll_t; +#endif + +static loff_t mksu_wrapper_llseek(struct file *fp, loff_t off, int flags) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->llseek(data->orig, off, flags); +} + +static ssize_t mksu_wrapper_read(struct file *fp, char __user *ptr, size_t sz, + loff_t *off) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->read(orig, ptr, sz, off); +} + +static ssize_t mksu_wrapper_write(struct file *fp, const char __user *ptr, + size_t sz, loff_t *off) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->write(orig, ptr, sz, off); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static ssize_t mksu_wrapper_read_iter(struct kiocb *iocb, struct iov_iter *iovi) +{ + struct ksu_file_wrapper *data = iocb->ki_filp->private_data; + struct file *orig = data->orig; + iocb->ki_filp = orig; + return orig->f_op->read_iter(iocb, iovi); +} + +static ssize_t mksu_wrapper_write_iter(struct kiocb *iocb, + struct iov_iter *iovi) +{ + struct ksu_file_wrapper *data = iocb->ki_filp->private_data; + struct file *orig = data->orig; + iocb->ki_filp = orig; + return orig->f_op->write_iter(iocb, iovi); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) +static int mksu_wrapper_iopoll(struct kiocb *kiocb, struct io_comp_batch *icb, + unsigned int v) +{ + struct ksu_file_wrapper *data = kiocb->ki_filp->private_data; + struct file *orig = data->orig; + kiocb->ki_filp = orig; + return orig->f_op->iopoll(kiocb, icb, v); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) +static int mksu_wrapper_iopoll(struct kiocb *kiocb, bool spin) +{ + struct ksu_file_wrapper *data = kiocb->ki_filp->private_data; + struct file *orig = data->orig; + kiocb->ki_filp = orig; + return orig->f_op->iopoll(kiocb, spin); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) +static int mksu_wrapper_iterate(struct file *fp, struct dir_context *dc) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->iterate(orig, dc); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) +static int mksu_wrapper_iterate_shared(struct file *fp, struct dir_context *dc) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->iterate_shared(orig, dc); +} +#endif + +static __poll_t mksu_wrapper_poll(struct file *fp, + struct poll_table_struct *pts) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->poll(orig, pts); +} + +static long mksu_wrapper_unlocked_ioctl(struct file *fp, unsigned int cmd, + unsigned long arg) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->unlocked_ioctl(orig, cmd, arg); +} + +static long mksu_wrapper_compat_ioctl(struct file *fp, unsigned int cmd, + unsigned long arg) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->compat_ioctl(orig, cmd, arg); +} + +static int mksu_wrapper_mmap(struct file *fp, struct vm_area_struct *vma) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->mmap(orig, vma); +} + +// static unsigned long mmap_supported_flags {} + +static int mksu_wrapper_open(struct inode *ino, struct file *fp) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + struct inode *orig_ino = file_inode(orig); + return orig->f_op->open(orig_ino, orig); +} + +static int mksu_wrapper_flush(struct file *fp, fl_owner_t id) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->flush(orig, id); +} + +static int mksu_wrapper_fsync(struct file *fp, loff_t off1, loff_t off2, + int datasync) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->fsync(orig, off1, off2, datasync); +} + +static int mksu_wrapper_fasync(int arg, struct file *fp, int arg2) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->fasync(arg, orig, arg2); +} + +static int mksu_wrapper_lock(struct file *fp, int arg1, struct file_lock *fl) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + return orig->f_op->lock(orig, arg1, fl); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) +static ssize_t mksu_wrapper_sendpage(struct file *fp, struct page *pg, int arg1, + size_t sz, loff_t *off, int arg2) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->sendpage) { + return orig->f_op->sendpage(orig, pg, arg1, sz, off, arg2); + } + return -EINVAL; +} +#endif + +static unsigned long mksu_wrapper_get_unmapped_area(struct file *fp, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->get_unmapped_area) { + return orig->f_op->get_unmapped_area(orig, arg1, arg2, arg3, + arg4); + } + return -EINVAL; +} + +// static int mksu_wrapper_check_flags(int arg) {} + +static int mksu_wrapper_flock(struct file *fp, int arg1, struct file_lock *fl) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->flock) { + return orig->f_op->flock(orig, arg1, fl); + } + return -EINVAL; +} + +static ssize_t mksu_wrapper_splice_write(struct pipe_inode_info *pii, + struct file *fp, loff_t *off, + size_t sz, unsigned int arg1) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->splice_write) { + return orig->f_op->splice_write(pii, orig, off, sz, arg1); + } + return -EINVAL; +} + +static ssize_t mksu_wrapper_splice_read(struct file *fp, loff_t *off, + struct pipe_inode_info *pii, size_t sz, + unsigned int arg1) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->splice_read) { + return orig->f_op->splice_read(orig, off, pii, sz, arg1); + } + return -EINVAL; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) +void mksu_wrapper_splice_eof(struct file *fp) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->splice_eof) { + return orig->f_op->splice_eof(orig); + } +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) +static int mksu_wrapper_setlease(struct file *fp, int arg1, + struct file_lease **fl, void **p) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->setlease) { + return orig->f_op->setlease(orig, arg1, fl, p); + } + return -EINVAL; +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) +static int mksu_wrapper_setlease(struct file *fp, int arg1, + struct file_lock **fl, void **p) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->setlease) { + return orig->f_op->setlease(orig, arg1, fl, p); + } + return -EINVAL; +} +#elif LINUX_VERSION_CODE >= \ + KERNEL_VERSION( \ + 3, 18, \ + 0) // int (*setlease)(struct file *, long, struct file_lock **, void **); +static int mksu_wrapper_setlease(struct file *fp, long arg1, + struct file_lock **fl, void **p) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->setlease) { + return orig->f_op->setlease(orig, arg1, fl, p); + } + return -EINVAL; +} +#else // int (*setlease)(struct file *, long, struct file_lock **); +static int mksu_wrapper_setlease(struct file *fp, long arg1, + struct file_lock **fl) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->setlease) { + return orig->f_op->setlease(orig, arg1, fl); + } + return -EINVAL; +} +#endif + +static long mksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset, + loff_t len) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->fallocate) { + return orig->f_op->fallocate(orig, mode, offset, len); + } + return -EINVAL; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) +static void mksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct ksu_file_wrapper *data = m->file->private_data; + struct file *orig = data->orig; + if (orig->f_op->show_fdinfo) { + orig->f_op->show_fdinfo(m, orig); + } +} + +#else +static int mksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) +{ + struct ksu_file_wrapper *data = m->file->private_data; + struct file *orig = data->orig; + if (orig->f_op->show_fdinfo) { + orig->f_op->show_fdinfo(m, orig); + } + return -EINVAL; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) +static ssize_t mksu_wrapper_copy_file_range(struct file *f1, loff_t off1, + struct file *f2, loff_t off2, + size_t sz, unsigned int flags) +{ + // TODO: determine which file to use + struct ksu_file_wrapper *data = f1->private_data; + struct file *orig = data->orig; + if (orig->f_op->copy_file_range) { + return orig->f_op->copy_file_range(orig, off1, f2, off2, sz, + flags); + } + return -EINVAL; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) +static loff_t mksu_wrapper_remap_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, + loff_t pos_out, loff_t len, + unsigned int remap_flags) +{ + // TODO: determine which file to use + struct ksu_file_wrapper *data = file_in->private_data; + struct file *orig = data->orig; + if (orig->f_op->remap_file_range) { + return orig->f_op->remap_file_range(orig, pos_in, file_out, + pos_out, len, remap_flags); + } + return -EINVAL; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) +static int mksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, + int flags) +{ + struct ksu_file_wrapper *data = fp->private_data; + struct file *orig = data->orig; + if (orig->f_op->fadvise) { + return orig->f_op->fadvise(orig, off1, off2, flags); + } + return -EINVAL; +} +#endif + +static int mksu_wrapper_release(struct inode *inode, struct file *filp) +{ + mksu_delete_file_wrapper(filp->private_data); + return 0; +} + +struct ksu_file_wrapper *mksu_create_file_wrapper(struct file *fp) +{ + struct ksu_file_wrapper *p = + kcalloc(sizeof(struct ksu_file_wrapper), 1, GFP_KERNEL); + if (!p) { + return NULL; + } + + get_file(fp); + + p->orig = fp; + p->ops.owner = THIS_MODULE; + p->ops.llseek = fp->f_op->llseek ? mksu_wrapper_llseek : NULL; + p->ops.read = fp->f_op->read ? mksu_wrapper_read : NULL; + p->ops.write = fp->f_op->write ? mksu_wrapper_write : NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + p->ops.read_iter = fp->f_op->read_iter ? mksu_wrapper_read_iter : NULL; + p->ops.write_iter = + fp->f_op->write_iter ? mksu_wrapper_write_iter : NULL; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + p->ops.iopoll = fp->f_op->iopoll ? mksu_wrapper_iopoll : NULL; +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) + p->ops.iterate = fp->f_op->iterate ? mksu_wrapper_iterate : NULL; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + p->ops.iterate_shared = + fp->f_op->iterate_shared ? mksu_wrapper_iterate_shared : NULL; +#endif + p->ops.poll = fp->f_op->poll ? mksu_wrapper_poll : NULL; + p->ops.unlocked_ioctl = + fp->f_op->unlocked_ioctl ? mksu_wrapper_unlocked_ioctl : NULL; + p->ops.compat_ioctl = + fp->f_op->compat_ioctl ? mksu_wrapper_compat_ioctl : NULL; + p->ops.mmap = fp->f_op->mmap ? mksu_wrapper_mmap : NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) + p->ops.fop_flags = fp->f_op->fop_flags; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) + p->ops.mmap_supported_flags = fp->f_op->mmap_supported_flags; +#endif + p->ops.open = fp->f_op->open ? mksu_wrapper_open : NULL; + p->ops.flush = fp->f_op->flush ? mksu_wrapper_flush : NULL; + p->ops.release = mksu_wrapper_release; + p->ops.fsync = fp->f_op->fsync ? mksu_wrapper_fsync : NULL; + p->ops.fasync = fp->f_op->fasync ? mksu_wrapper_fasync : NULL; + p->ops.lock = fp->f_op->lock ? mksu_wrapper_lock : NULL; +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) + p->ops.sendpage = fp->f_op->sendpage ? mksu_wrapper_sendpage : NULL; +#endif + p->ops.get_unmapped_area = fp->f_op->get_unmapped_area ? + mksu_wrapper_get_unmapped_area : + NULL; + p->ops.check_flags = fp->f_op->check_flags; + p->ops.flock = fp->f_op->flock ? mksu_wrapper_flock : NULL; + p->ops.splice_write = + fp->f_op->splice_write ? mksu_wrapper_splice_write : NULL; + p->ops.splice_read = + fp->f_op->splice_read ? mksu_wrapper_splice_read : NULL; + p->ops.setlease = fp->f_op->setlease ? mksu_wrapper_setlease : NULL; + p->ops.fallocate = fp->f_op->fallocate ? mksu_wrapper_fallocate : NULL; + p->ops.show_fdinfo = + fp->f_op->show_fdinfo ? mksu_wrapper_show_fdinfo : NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + p->ops.copy_file_range = + fp->f_op->copy_file_range ? mksu_wrapper_copy_file_range : NULL; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) + p->ops.remap_file_range = fp->f_op->remap_file_range ? + mksu_wrapper_remap_file_range : + NULL; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) + p->ops.fadvise = fp->f_op->fadvise ? mksu_wrapper_fadvise : NULL; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) + p->ops.splice_eof = + fp->f_op->splice_eof ? mksu_wrapper_splice_eof : NULL; +#endif + + return p; +} + +void mksu_delete_file_wrapper(struct ksu_file_wrapper *data) +{ + fput((struct file *)data->orig); + kfree(data); +} diff --git a/kernel/file_wrapper.h b/kernel/file_wrapper.h new file mode 100644 index 00000000..b4737fe2 --- /dev/null +++ b/kernel/file_wrapper.h @@ -0,0 +1,10 @@ +#include +#include + +struct ksu_file_wrapper { + struct file *orig; + struct file_operations ops; +}; + +struct ksu_file_wrapper *mksu_create_file_wrapper(struct file *fp); +void mksu_delete_file_wrapper(struct ksu_file_wrapper *data); diff --git a/kernel/ksu.c b/kernel/ksu.c index 97c6446b..55ca87b9 100644 --- a/kernel/ksu.c +++ b/kernel/ksu.c @@ -14,6 +14,9 @@ #include "klog.h" // IWYU pragma: keep #include "ksu.h" #include "throne_tracker.h" +#include "sucompat.h" +#include "ksud.h" +#include "supercalls.h" static struct workqueue_struct *ksu_workqueue; @@ -22,11 +25,6 @@ bool ksu_queue_work(struct work_struct *work) return queue_work(ksu_workqueue, work); } -extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, - void *argv, void *envp, int *flags); - -extern int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr, - void *argv, void *envp, int *flags); int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, void *envp, int *flags) @@ -36,16 +34,6 @@ int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, flags); } -extern void ksu_sucompat_init(void); -extern void ksu_sucompat_exit(void); -extern void ksu_ksud_init(void); -extern void ksu_ksud_exit(void); -extern void ksu_supercalls_init(void); -#ifdef CONFIG_KSU_TRACEPOINT_HOOK -extern void ksu_trace_register(); -extern void ksu_trace_unregister(); -#endif - int __init kernelsu_init(void) { pr_info("Initialized on: %s (%s) with driver version: %u\n", @@ -75,14 +63,10 @@ int __init kernelsu_init(void) ksu_sucompat_init(); -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK ksu_ksud_init(); #endif -#ifdef CONFIG_KSU_TRACEPOINT_HOOK - ksu_trace_register(); -#endif - #ifdef MODULE #ifndef CONFIG_KSU_DEBUG kobject_del(&THIS_MODULE->mkobj.kobj); @@ -101,14 +85,10 @@ void kernelsu_exit(void) destroy_workqueue(ksu_workqueue); -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK ksu_ksud_exit(); #endif -#ifdef CONFIG_KSU_TRACEPOINT_HOOK - ksu_trace_unregister(); -#endif - ksu_sucompat_exit(); ksu_core_exit(); diff --git a/kernel/ksu_trace.c b/kernel/ksu_trace.c deleted file mode 100644 index a3010e6e..00000000 --- a/kernel/ksu_trace.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "ksu_trace.h" - -// extern kernelsu functions -extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, - void *argv, void *envp, int *flags); -extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, - int *mode, int *flags); -extern bool ksu_vfs_read_hook __read_mostly; -extern int ksu_handle_sys_read(unsigned int fd, char __user **buf_ptr, - size_t *count_ptr); -extern int ksu_handle_stat(int *dfd, const char __user **filename_user, - int *flags); -extern bool ksu_input_hook __read_mostly; -extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, - int *value); -extern int ksu_handle_devpts(struct inode *); -// end kernelsu functions - -// tracepoint callback functions -void ksu_trace_execveat_hook_callback(void *data, int *fd, - struct filename **filename_ptr, - void *argv, void *envp, - int *flags) -{ - ksu_handle_execveat(fd, filename_ptr, argv, envp, - flags); -} - -void ksu_trace_faccessat_hook_callback(void *data, int *dfd, - const char __user **filename_user, - int *mode, int *flags) -{ - ksu_handle_faccessat(dfd, filename_user, mode, flags); -} - -void ksu_trace_sys_read_hook_callback(void *data, unsigned int fd, - char __user **buf_ptr, size_t *count_ptr) -{ - if (unlikely(ksu_vfs_read_hook)) - ksu_handle_sys_read(fd, buf_ptr, count_ptr); -} - -void ksu_trace_stat_hook_callback(void *data, int *dfd, - const char __user **filename_user, int *flags) -{ - ksu_handle_stat(dfd, filename_user, flags); -} - -void ksu_trace_input_hook_callback(void *data, unsigned int *type, - unsigned int *code, int *value) -{ - if (unlikely(ksu_input_hook)) - ksu_handle_input_handle_event(type, code, value); -} - -// end tracepoint callback functions - -// register tracepoint callback functions -void ksu_trace_register(void) -{ - register_trace_ksu_trace_execveat_hook( - ksu_trace_execveat_hook_callback, NULL); - register_trace_ksu_trace_faccessat_hook( - ksu_trace_faccessat_hook_callback, NULL); - register_trace_ksu_trace_sys_read_hook(ksu_trace_sys_read_hook_callback, - NULL); - register_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, NULL); - register_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback, - NULL); -} - -// unregister tracepoint callback functions -void ksu_trace_unregister(void) -{ - unregister_trace_ksu_trace_execveat_hook( - ksu_trace_execveat_hook_callback, NULL); - unregister_trace_ksu_trace_faccessat_hook( - ksu_trace_faccessat_hook_callback, NULL); - unregister_trace_ksu_trace_sys_read_hook( - ksu_trace_sys_read_hook_callback, NULL); - unregister_trace_ksu_trace_stat_hook(ksu_trace_stat_hook_callback, - NULL); - unregister_trace_ksu_trace_input_hook(ksu_trace_input_hook_callback, - NULL); -} diff --git a/kernel/ksu_trace.h b/kernel/ksu_trace.h deleted file mode 100644 index dcda95e4..00000000 --- a/kernel/ksu_trace.h +++ /dev/null @@ -1,41 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM ksu_trace - -#if !defined(_KSU_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define _KSU_TRACE_H - -#include -#include - -DECLARE_TRACE(ksu_trace_execveat_hook, - TP_PROTO(int *fd, struct filename **filename_ptr, void *argv, - void *envp, int *flags), - TP_ARGS(fd, filename_ptr, argv, envp, flags)); - -DECLARE_TRACE(ksu_trace_faccessat_hook, - TP_PROTO(int *dfd, const char __user **filename_user, int *mode, - int *flags), - TP_ARGS(dfd, filename_user, mode, flags)); - -DECLARE_TRACE(ksu_trace_sys_read_hook, - TP_PROTO(unsigned int fd, char __user **buf_ptr, - size_t *count_ptr), - TP_ARGS(fd, buf_ptr, count_ptr)); - -DECLARE_TRACE(ksu_trace_stat_hook, - TP_PROTO(int *dfd, const char __user **filename_user, int *flags), - TP_ARGS(dfd, filename_user, flags)); - -DECLARE_TRACE(ksu_trace_input_hook, - TP_PROTO(unsigned int *type, unsigned int *code, int *value), - TP_ARGS(type, code, value)); - - -#endif /* _KSU_TRACE_H */ - -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE ksu_trace - -#include diff --git a/kernel/ksu_trace_export.c b/kernel/ksu_trace_export.c deleted file mode 100644 index b303cbbd..00000000 --- a/kernel/ksu_trace_export.c +++ /dev/null @@ -1,8 +0,0 @@ -#define CREATE_TRACE_POINTS -#include "ksu_trace.h" - -EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_execveat_hook); -EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_faccessat_hook); -EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_sys_read_hook); -EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_stat_hook); -EXPORT_TRACEPOINT_SYMBOL_GPL(ksu_trace_input_hook); diff --git a/kernel/ksud.c b/kernel/ksud.c index 5b0e5233..e6cf5835 100644 --- a/kernel/ksud.c +++ b/kernel/ksud.c @@ -54,7 +54,7 @@ static void stop_vfs_read_hook(void); static void stop_execve_hook(void); static void stop_input_hook(void); -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK static struct work_struct stop_vfs_read_work; static struct work_struct stop_execve_hook_work; static struct work_struct stop_input_hook_work; @@ -64,7 +64,7 @@ bool ksu_input_hook __read_mostly = true; #endif bool ksu_execveat_hook __read_mostly = true; -u32 ksu_devpts_sid; +u32 ksu_file_sid; // Detect whether it is on or not static bool is_boot_phase = true; @@ -83,11 +83,11 @@ void on_post_fs_data(void) // sanity check, this may influence the performance stop_input_hook(); - ksu_devpts_sid = ksu_get_devpts_sid(); - pr_info("devpts sid: %d\n", ksu_devpts_sid); - - // End of boot state + // End of boot state is_boot_phase = false; + + ksu_file_sid = ksu_get_ksu_file_sid(); + pr_info("devpts sid: %d\n", ksu_file_sid); } struct user_arg_ptr { @@ -294,7 +294,7 @@ static ssize_t read_iter_proxy(struct kiocb *iocb, struct iov_iter *to) int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, size_t *count_ptr, loff_t **pos) { -#ifndef CONFIG_KSU_KPROBES_HOOK +#ifndef KSU_KPROBES_HOOK if (!ksu_vfs_read_hook) { return 0; } @@ -407,7 +407,7 @@ static bool is_volumedown_enough(unsigned int count) int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value) { -#ifndef CONFIG_KSU_KPROBES_HOOK +#ifndef KSU_KPROBES_HOOK if (!ksu_input_hook) { return 0; } @@ -449,7 +449,7 @@ bool ksu_is_safe_mode(void) return false; } -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs) { /* @@ -668,7 +668,7 @@ int __maybe_unused ksu_handle_compat_execve_ksud( static void stop_vfs_read_hook(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK bool ret = schedule_work(&stop_vfs_read_work); pr_info("unregister vfs_read kprobe: %d!\n", ret); #else @@ -679,7 +679,7 @@ static void stop_vfs_read_hook(void) static void stop_execve_hook(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK bool ret = schedule_work(&stop_execve_hook_work); pr_info("unregister execve kprobe: %d!\n", ret); #else @@ -690,7 +690,7 @@ static void stop_execve_hook(void) static void stop_input_hook(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK static bool input_hook_stopped = false; if (input_hook_stopped) { return; @@ -710,7 +710,7 @@ static void stop_input_hook(void) // ksud: module support void ksu_ksud_init(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK int ret; ret = register_kprobe(&execve_kp); @@ -730,7 +730,7 @@ void ksu_ksud_init(void) void ksu_ksud_exit(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK unregister_kprobe(&execve_kp); // this should be done before unregister vfs_read_kp // unregister_kprobe(&vfs_read_kp); diff --git a/kernel/ksud.h b/kernel/ksud.h index 7fff4807..9a184114 100644 --- a/kernel/ksud.h +++ b/kernel/ksud.h @@ -5,11 +5,14 @@ #define KSUD_PATH "/data/adb/ksud" +void ksu_ksud_init(); +void ksu_ksud_exit(); + void on_post_fs_data(void); bool ksu_is_safe_mode(void); -extern u32 ksu_devpts_sid; +extern u32 ksu_file_sid; extern bool ksu_execveat_hook __read_mostly; extern int ksu_handle_pre_ksud(const char *filename); diff --git a/kernel/selinux/rules.c b/kernel/selinux/rules.c index e0de9526..9d84e042 100644 --- a/kernel/selinux/rules.c +++ b/kernel/selinux/rules.c @@ -238,23 +238,26 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) char perm_buf[MAX_SEPOL_LEN]; char *s, *t, *c, *p; - if (get_object(src_buf, (void __user *)data.sepol1, sizeof(src_buf), &s) < 0) { + if (get_object(src_buf, (void __user *)data.sepol1, + sizeof(src_buf), &s) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (get_object(tgt_buf, (void __user *)data.sepol2, sizeof(tgt_buf), &t) < 0) { + if (get_object(tgt_buf, (void __user *)data.sepol2, + sizeof(tgt_buf), &t) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (get_object(cls_buf, (void __user *)data.sepol3, sizeof(cls_buf), &c) < 0) { + if (get_object(cls_buf, (void __user *)data.sepol3, + sizeof(cls_buf), &c) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } - if (get_object(perm_buf, (void __user *)data.sepol4, sizeof(perm_buf), &p) < - 0) { + if (get_object(perm_buf, (void __user *)data.sepol4, + sizeof(perm_buf), &p) < 0) { pr_err("sepol: copy perm failed.\n"); goto exit; } @@ -285,15 +288,18 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) char perm_set[MAX_SEPOL_LEN]; char *s, *t, *c; - if (get_object(src_buf, (void __user *)data.sepol1, sizeof(src_buf), &s) < 0) { + if (get_object(src_buf, (void __user *)data.sepol1, + sizeof(src_buf), &s) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (get_object(tgt_buf, (void __user *)data.sepol2, sizeof(tgt_buf), &t) < 0) { + if (get_object(tgt_buf, (void __user *)data.sepol2, + sizeof(tgt_buf), &t) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (get_object(cls_buf, (void __user *)data.sepol3, sizeof(cls_buf), &c) < 0) { + if (get_object(cls_buf, (void __user *)data.sepol3, + sizeof(cls_buf), &c) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } @@ -302,8 +308,8 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) pr_err("sepol: copy operation failed.\n"); goto exit; } - if (strncpy_from_user(perm_set, (void __user *)data.sepol5, sizeof(perm_set)) < - 0) { + if (strncpy_from_user(perm_set, (void __user *)data.sepol5, + sizeof(perm_set)) < 0) { pr_err("sepol: copy perm_set failed.\n"); goto exit; } @@ -324,7 +330,8 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) case CMD_TYPE_STATE: { char src[MAX_SEPOL_LEN]; - if (strncpy_from_user(src, (void __user *)data.sepol1, sizeof(src)) < 0) { + if (strncpy_from_user(src, (void __user *)data.sepol1, + sizeof(src)) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } @@ -346,11 +353,13 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) char type[MAX_SEPOL_LEN]; char attr[MAX_SEPOL_LEN]; - if (strncpy_from_user(type, (void __user *)data.sepol1, sizeof(type)) < 0) { + if (strncpy_from_user(type, (void __user *)data.sepol1, + sizeof(type)) < 0) { pr_err("sepol: copy type failed.\n"); goto exit; } - if (strncpy_from_user(attr, (void __user *)data.sepol2, sizeof(attr)) < 0) { + if (strncpy_from_user(attr, (void __user *)data.sepol2, + sizeof(attr)) < 0) { pr_err("sepol: copy attr failed.\n"); goto exit; } @@ -371,7 +380,8 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) case CMD_ATTR: { char attr[MAX_SEPOL_LEN]; - if (strncpy_from_user(attr, (void __user *)data.sepol1, sizeof(attr)) < 0) { + if (strncpy_from_user(attr, (void __user *)data.sepol1, + sizeof(attr)) < 0) { pr_err("sepol: copy attr failed.\n"); goto exit; } @@ -389,15 +399,18 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) char default_type[MAX_SEPOL_LEN]; char object[MAX_SEPOL_LEN]; - if (strncpy_from_user(src, (void __user *)data.sepol1, sizeof(src)) < 0) { + if (strncpy_from_user(src, (void __user *)data.sepol1, + sizeof(src)) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (strncpy_from_user(tgt, (void __user *)data.sepol2, sizeof(tgt)) < 0) { + if (strncpy_from_user(tgt, (void __user *)data.sepol2, + sizeof(tgt)) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (strncpy_from_user(cls, (void __user *)data.sepol3, sizeof(cls)) < 0) { + if (strncpy_from_user(cls, (void __user *)data.sepol3, + sizeof(cls)) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } @@ -410,7 +423,8 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) if ((void __user *)data.sepol5 == NULL) { real_object = NULL; } else { - if (strncpy_from_user(object, (void __user *)data.sepol5, + if (strncpy_from_user(object, + (void __user *)data.sepol5, sizeof(object)) < 0) { pr_err("sepol: copy object failed.\n"); goto exit; @@ -430,15 +444,18 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) char cls[MAX_SEPOL_LEN]; char default_type[MAX_SEPOL_LEN]; - if (strncpy_from_user(src, (void __user *)data.sepol1, sizeof(src)) < 0) { + if (strncpy_from_user(src, (void __user *)data.sepol1, + sizeof(src)) < 0) { pr_err("sepol: copy src failed.\n"); goto exit; } - if (strncpy_from_user(tgt, (void __user *)data.sepol2, sizeof(tgt)) < 0) { + if (strncpy_from_user(tgt, (void __user *)data.sepol2, + sizeof(tgt)) < 0) { pr_err("sepol: copy tgt failed.\n"); goto exit; } - if (strncpy_from_user(cls, (void __user *)data.sepol3, sizeof(cls)) < 0) { + if (strncpy_from_user(cls, (void __user *)data.sepol3, + sizeof(cls)) < 0) { pr_err("sepol: copy cls failed.\n"); goto exit; } @@ -465,16 +482,18 @@ int handle_sepolicy(unsigned long arg3, void __user *arg4) char name[MAX_SEPOL_LEN]; char path[MAX_SEPOL_LEN]; char context[MAX_SEPOL_LEN]; - if (strncpy_from_user(name, (void __user *)data.sepol1, sizeof(name)) < 0) { + if (strncpy_from_user(name, (void __user *)data.sepol1, + sizeof(name)) < 0) { pr_err("sepol: copy name failed.\n"); goto exit; } - if (strncpy_from_user(path, (void __user *)data.sepol2, sizeof(path)) < 0) { + if (strncpy_from_user(path, (void __user *)data.sepol2, + sizeof(path)) < 0) { pr_err("sepol: copy path failed.\n"); goto exit; } - if (strncpy_from_user(context, (void __user *)data.sepol3, sizeof(context)) < - 0) { + if (strncpy_from_user(context, (void __user *)data.sepol3, + sizeof(context)) < 0) { pr_err("sepol: copy context failed.\n"); goto exit; } diff --git a/kernel/selinux/selinux.c b/kernel/selinux/selinux.c index 30aad158..a8b70f7c 100644 --- a/kernel/selinux/selinux.c +++ b/kernel/selinux/selinux.c @@ -155,16 +155,15 @@ bool is_zygote(void *sec) return result; } -#define DEVPTS_DOMAIN "u:object_r:ksu_file:s0" +#define KSU_FILE_DOMAIN "u:object_r:ksu_file:s0" -u32 ksu_get_devpts_sid(void) +u32 ksu_get_ksu_file_sid(void) { - u32 devpts_sid = 0; - int err = security_secctx_to_secid(DEVPTS_DOMAIN, strlen(DEVPTS_DOMAIN), - &devpts_sid); - - if (err) - pr_info("get devpts sid err %d\n", err); - - return devpts_sid; + u32 ksu_file_sid = 0; + int err = security_secctx_to_secid( + KSU_FILE_DOMAIN, strlen(KSU_FILE_DOMAIN), &ksu_file_sid); + if (err) { + pr_info("get ksufile sid err %d\n", err); + } + return ksu_file_sid; } diff --git a/kernel/selinux/selinux.h b/kernel/selinux/selinux.h index 462f6402..39592a19 100644 --- a/kernel/selinux/selinux.h +++ b/kernel/selinux/selinux.h @@ -21,6 +21,9 @@ bool is_zygote(void *cred); void apply_kernelsu_rules(void); -u32 ksu_get_devpts_sid(void); + +u32 ksu_get_ksu_file_sid(void); + +int handle_sepolicy(unsigned long arg3, void __user *arg4); #endif diff --git a/kernel/sucompat.c b/kernel/sucompat.c index 42ef876b..f4d41243 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -22,6 +22,8 @@ #include "klog.h" // IWYU pragma: keep #include "ksud.h" #include "kernel_compat.h" +#include "sucompat.h" +#include "core_hook.h" #define SU_PATH "/system/bin/su" #define SH_PATH "/system/bin/sh" @@ -29,10 +31,6 @@ static const char su[] = SU_PATH; static const char ksud_path[] = KSUD_PATH; -extern void escape_to_root(void); -void ksu_sucompat_enable(void); -void ksu_sucompat_disable(void); - static bool ksu_su_compat_enabled __read_mostly = true; static int su_compat_feature_get(u64 *value) @@ -91,7 +89,7 @@ static inline char __user *ksud_user_path(void) static inline bool __is_su_allowed(const void *ptr_to_check) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK if (!ksu_su_compat_enabled) return false; #endif @@ -180,15 +178,9 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, return 0; } -// dummified -int ksu_handle_devpts(struct inode *inode) -{ - return 0; -} - int __ksu_handle_devpts(struct inode *inode) { -#ifndef CONFIG_KSU_KPROBES_HOOK +#ifndef KSU_KPROBES_HOOK if (!ksu_su_compat_enabled) return 0; #endif @@ -212,13 +204,12 @@ int __ksu_handle_devpts(struct inode *inode) struct inode_security_struct *sec = (struct inode_security_struct *)inode->i_security; #endif - if (ksu_devpts_sid && sec) - sec->sid = ksu_devpts_sid; - + if (ksu_file_sid && sec) + sec->sid = ksu_file_sid; return 0; } -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs) { @@ -252,23 +243,10 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) NULL); } -static int pts_unix98_lookup_pre(struct kprobe *p, struct pt_regs *regs) -{ - struct inode *inode; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) - struct file *file = (struct file *)PT_REGS_PARM2(regs); - inode = file->f_path.dentry->d_inode; -#else - inode = (struct inode *)PT_REGS_PARM2(regs); -#endif - - return ksu_handle_devpts(inode); -} - #ifdef CONFIG_COMPAT -static struct kprobe *su_kps[6]; +static struct kprobe *su_kps[5]; #else -static struct kprobe *su_kps[4]; +static struct kprobe *su_kps[3]; #endif static struct kprobe *init_kprobe(const char *name, @@ -304,14 +282,13 @@ static void destroy_kprobe(struct kprobe **kp_ptr) void ksu_sucompat_enable(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK su_kps[0] = init_kprobe(SYS_EXECVE_SYMBOL, execve_handler_pre); su_kps[1] = init_kprobe(SYS_FACCESSAT_SYMBOL, faccessat_handler_pre); su_kps[2] = init_kprobe(SYS_NEWFSTATAT_SYMBOL, newfstatat_handler_pre); - su_kps[3] = init_kprobe("pts_unix98_lookup", pts_unix98_lookup_pre); #ifdef CONFIG_COMPAT - su_kps[4] = init_kprobe(SYS_EXECVE_COMPAT_SYMBOL, execve_handler_pre); - su_kps[5] = init_kprobe(SYS_FSTATAT64_SYMBOL, newfstatat_handler_pre); + su_kps[3] = init_kprobe(SYS_EXECVE_COMPAT_SYMBOL, execve_handler_pre); + su_kps[4] = init_kprobe(SYS_FSTATAT64_SYMBOL, newfstatat_handler_pre); #endif #else ksu_su_compat_enabled = true; @@ -321,7 +298,7 @@ void ksu_sucompat_enable(void) void ksu_sucompat_disable(void) { -#ifdef CONFIG_KSU_KPROBES_HOOK +#ifdef KSU_KPROBES_HOOK int i; for (i = 0; i < ARRAY_SIZE(su_kps); i++) { destroy_kprobe(&su_kps[i]); diff --git a/kernel/sucompat.h b/kernel/sucompat.h new file mode 100644 index 00000000..f967bac8 --- /dev/null +++ b/kernel/sucompat.h @@ -0,0 +1,17 @@ +#ifndef __KSU_H_SUCOMPAT +#define __KSU_H_SUCOMPAT +#include +#include + +void ksu_sucompat_init(void); +void ksu_sucompat_exit(void); + +void ksu_sucompat_enable(void); +void ksu_sucompat_disable(void); + +extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, + void *argv, void *envp, int *flags); + +extern int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr, + void *argv, void *envp, int *flags); +#endif diff --git a/kernel/supercalls.c b/kernel/supercalls.c index 7179d4c4..540b5b81 100644 --- a/kernel/supercalls.c +++ b/kernel/supercalls.c @@ -17,6 +17,9 @@ #include "manager.h" #include "sulog.h" #include "selinux/selinux.h" +#include "core_hook.h" +#include "objsec.h" +#include "file_wrapper.h" #include "kernel_compat.h" #include "throne_comm.h" #include "dynamic_manager.h" @@ -385,7 +388,7 @@ static int do_get_hook_type(void __user *arg) #if defined(CONFIG_KSU_TRACEPOINT_HOOK) type = "Tracepoint"; -#elif defined(CONFIG_KSU_MANUAL_HOOK) +#elif defined(KSU_MANUAL_HOOK) type = "Manual"; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) @@ -516,6 +519,73 @@ static int do_enable_uid_scanner(void __user *arg) return 0; } +static int do_get_wrapper_fd(void __user *arg) +{ + if (!ksu_file_sid) { + return -1; + } + + struct ksu_get_wrapper_fd_cmd cmd; + int ret; + + if (copy_from_user(&cmd, arg, sizeof(cmd))) { + pr_err("get_wrapper_fd: copy_from_user failed\n"); + return -EFAULT; + } + + struct file *f = fget(cmd.fd); + if (!f) { + return -EBADF; + } + + struct ksu_file_wrapper *data = mksu_create_file_wrapper(f); + if (data == NULL) { + ret = -ENOMEM; + goto put_orig_file; + } + + struct file *pf = anon_inode_getfile("[mksu_fdwrapper]", &data->ops, + data, f->f_flags); + if (IS_ERR(pf)) { + ret = PTR_ERR(pf); + pr_err("mksu_fdwrapper: anon_inode_getfile failed: %ld\n", + PTR_ERR(pf)); + goto put_wrapper_data; + } + + struct inode *wrapper_inode = file_inode(pf); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) || \ + defined(KSU_OPTIONAL_SELINUX_INODE) + struct inode_security_struct *sec = selinux_inode(wrapper_inode); +#else + struct inode_security_struct *sec = + (struct inode_security_struct *)wrapper_inode->i_security; +#endif + if (sec) { + sec->sid = ksu_file_sid; + } + + ret = get_unused_fd_flags(cmd.flags); + if (ret < 0) { + pr_err("mksu_fdwrapper: get unused fd failed: %d\n", ret); + goto put_wrapper_file; + } + + // pr_info("mksu_fdwrapper: installed wrapper fd for %p %d (flags=%d, mode=%d) to %p %d (flags=%d, mode=%d)", f, cmd.fd, f->f_flags, f->f_mode, pf, ret, pf->f_flags, pf->f_mode); + // pf->f_mode |= FMODE_READ | FMODE_CAN_READ | FMODE_WRITE | FMODE_CAN_WRITE; + fd_install(ret, pf); + goto put_orig_file; + +put_wrapper_file: + fput(pf); +put_wrapper_data: + mksu_delete_file_wrapper(data); +put_orig_file: + fput(f); + + return ret; +} + // IOCTL handlers mapping table static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = { { .cmd = KSU_IOCTL_GRANT_ROOT, .name = "GRANT_ROOT", .handler = do_grant_root, .perm_check = allowed_for_su }, @@ -532,6 +602,7 @@ static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = { { .cmd = KSU_IOCTL_SET_APP_PROFILE, .name = "SET_APP_PROFILE", .handler = do_set_app_profile, .perm_check = only_manager }, { .cmd = KSU_IOCTL_GET_FEATURE, .name = "GET_FEATURE", .handler = do_get_feature, .perm_check = manager_or_root }, { .cmd = KSU_IOCTL_SET_FEATURE, .name = "SET_FEATURE", .handler = do_set_feature, .perm_check = manager_or_root }, + { .cmd = KSU_IOCTL_GET_WRAPPER_FD, .name = "GET_WRAPPER_FD", .handler = do_get_wrapper_fd, .perm_check = manager_or_root }, { .cmd = KSU_IOCTL_GET_FULL_VERSION,.name = "GET_FULL_VERSION", .handler = do_get_full_version, .perm_check = always_allow}, { .cmd = KSU_IOCTL_HOOK_TYPE,.name = "GET_HOOK_TYPE", .handler = do_get_hook_type, .perm_check = manager_or_root}, { .cmd = KSU_IOCTL_ENABLE_KPM, .name = "GET_ENABLE_KPM", .handler = do_enable_kpm, .perm_check = manager_or_root}, @@ -542,7 +613,7 @@ static const struct ksu_ioctl_cmd_map ksu_ioctl_handlers[] = { { .cmd = KSU_IOCTL_KPM, .name = "KPM_OPERATION", .handler = do_kpm, .perm_check = manager_or_root}, #endif { .cmd = 0, .name = NULL, .handler = NULL, .perm_check = NULL} // Sentine -}; +} void ksu_supercalls_init(void) { diff --git a/kernel/supercalls.h b/kernel/supercalls.h index 8fbbfd5e..95180a67 100644 --- a/kernel/supercalls.h +++ b/kernel/supercalls.h @@ -104,6 +104,11 @@ struct ksu_enable_uid_scanner_cmd { void __user *status_ptr; // Input: pointer to store status (for UID_SCANNER_OP_GET_STATUS) }; +struct ksu_get_wrapper_fd_cmd { + __u32 fd; + __u32 flags; // CLOEXEC +}; + // IOCTL command definitions #define KSU_IOCTL_GRANT_ROOT _IOC(_IOC_NONE, 'K', 1, 0) #define KSU_IOCTL_GET_INFO _IOC(_IOC_READ, 'K', 2, 0) @@ -119,6 +124,7 @@ struct ksu_enable_uid_scanner_cmd { #define KSU_IOCTL_SET_APP_PROFILE _IOC(_IOC_WRITE, 'K', 12, 0) #define KSU_IOCTL_GET_FEATURE _IOC(_IOC_READ|_IOC_WRITE, 'K', 13, 0) #define KSU_IOCTL_SET_FEATURE _IOC(_IOC_WRITE, 'K', 14, 0) +#define KSU_IOCTL_GET_WRAPPER_FD _IOC(_IOC_NONE, 'K', 10000, 0) // Other IOCTL command definitions #define KSU_IOCTL_GET_FULL_VERSION _IOC(_IOC_READ, 'K', 100, 0) #define KSU_IOCTL_HOOK_TYPE _IOC(_IOC_READ, 'K', 101, 0) @@ -142,4 +148,6 @@ struct ksu_ioctl_cmd_map { // Install KSU fd to current process int ksu_install_fd(void); -#endif // __KSU_H_SUPERCALLS \ No newline at end of file +void ksu_supercalls_init(); + +#endif // __KSU_H_SUPERCALLS