Manual Integrate reference
On this page
Manual hooks
stat hook Required
stat.c
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -353,6 +353,10 @@ SYSCALL_DEFINE2(newlstat, const char __user *, filename,
return cp_new_stat(&stat, statbuf);
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+__attribute__((hot))
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user,
+ int *flags);
+
+extern void ksu_handle_newfstat_ret(unsigned int *fd, struct stat __user **statbuf_ptr);
+#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
+extern void ksu_handle_fstat64_ret(unsigned long *fd, struct stat64 __user **statbuf_ptr); // optional
+#endif
+#endif
+
#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
struct stat __user *, statbuf, int, flag)
@@ -360,6 +364,9 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
struct kstat stat;
int error;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_stat(&dfd, &filename, &flag);
+#endif
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
@@ -504,6 +511,9 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
struct kstat stat;
int error;
+#ifdef CONFIG_KSU_MANUAL_HOOK // 32-bit su
+ ksu_handle_stat(&dfd, &filename, &flag);
+#endif
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
@@ -364,X +364,XX @@
SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
{
struct kstat stat;
int error = vfs_fstat(fd, &stat);
if (!error)
error = cp_new_stat(&stat, statbuf);
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_newfstat_ret(&fd, &statbuf);
+#endif
return error;
@@ -490,X +497,X @@
SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
{
struct kstat stat;
int error = vfs_fstat(fd, &stat);
if (!error)
error = cp_new_stat64(&stat, statbuf);
+#ifdef CONFIG_KSU_MANUAL_HOOK // for 32-bit
+ ksu_handle_fstat64_ret(&fd, &statbuf);
+#endif
return error;
}
In this part, you should find newfstatat and fstatat64 (if 32-bit su is supported) in fs/stat.c and hook them. You also need to hook newfstat and fstat64 (if 32-bit su is supported) for the return value.
execve hook Required
For this hook, different kernel versions are inconsistent, so it is explained separately here
3.14+
diff --git a/exec.c b/exec.c
index 5344364..cc612f0 100644
--- a/exec.c
+++ b/exec.c
@@ -1703,6 +1703,15 @@ static int exec_binprm(struct linux_binprm *bprm)
return ret;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+__attribute__((hot))
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
+__attribute__((hot))
+extern int ksu_handle_post_execveat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags, int *retval);
+#endif
+
/*
* sys_execve() executes a new program.
*/
@@ -1717,6 +1726,10 @@ static int do_execveat_common(int fd, struct filename *filename,
struct files_struct *displaced;
int retval;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags)
+#endif
+
if (IS_ERR(filename))
return PTR_ERR(filename);
@@ -1847,6 +1860,11 @@ out_files:
if (displaced)
reset_files_struct(displaced);
out_ret:
+
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_post_execveat(&fd, &filename, &argv, &envp, &flags, &retval)
+#endif
+
putname(filename);
return retval;
}
3.14-
diff --git a/exec.c b/exec.c
old mode 100755
new mode 100644
index 7ea097f..591dc94
--- a/exec.c
+++ b/exec.c
@@ -1443,6 +1443,15 @@ static int exec_binprm(struct linux_binprm *bprm)
return ret;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+__attribute__((hot))
+extern int ksu_handle_execve(int *fd, const char *filename,
+ void *argv, void *envp, int *flags);
+__attribute__((hot))
+extern int ksu_handle_post_execve(int *fd, const char *filename,
+ void *argv, void *envp, int *flags, int *retval)
+#endif
+
/*
* sys_execve() executes a new program.
*/
@@ -1455,6 +1464,9 @@ static int do_execve_common(const char *filename,
struct files_struct *displaced;
bool clear_in_exec;
int retval;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_execve((int *)AT_FDCWD, filename, &argv, &envp, 0);
+#endif
/*
* We move the actual failure in case of RLIMIT_NPROC excess from
@@ -1569,6 +1581,9 @@ out_files:
if (displaced)
reset_files_struct(displaced);
out_ret:
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_post_execve((int *)AT_FDCWD, &filename, &argv, &envp, 0, &retval);
+#endif
return retval;
}
Deprecated hook (3.14+)
This hook is NOT recommended to use for Android 17 QPR2 and above. Unless you want failed to get root.
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1837,13 +1837,32 @@ static int do_execveat_common(int fd, struct filename *filename,
return retval;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+attribute((hot))
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
+attribute((hot))
+extern int ksu_handle_post_execveat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags, int *retval);
+#endif
+
+
int do_execve(struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{
struct user_arg_ptr argv = { .ptr.native = __argv };
struct user_arg_ptr envp = { .ptr.native = __envp };
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ int retval;
+ ksu_handle_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0);
+ retval = do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
+
+ ksu_handle_post_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0, &retval);
+ return retval;
+#else
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
+#endif
+
}
int do_execveat(int fd, struct filename *filename,
@@ -1870,7 +1888,17 @@ static int compat_do_execve(struct filename *filename,
.is_compat = true,
.ptr.compat = __envp,
};
+#ifdef CONFIG_KSU_MANUAL_HOOK // 32-bit ksud and 32-on-64 support
+ int retval;
+ ksu_handle_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0);
+
+ retval = do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
+
+ ksu_handle_post_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0, &retval);
+ return retval;
+#else
return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
+#endif
}
static int compat_do_execveat(int fd, struct filename *filename,
For 3.14+ kernels, use ksu_handle_execveat and ksu_handle_post_execveat then hook do_execveat_common in fs/exec.c. Notice that ksu_handle_post_execveat is called after do_execveat_common and before retval is returned.
For this deprecated hook, find do_execve in fs/exec.c. For 32-bit su and 32-on-64 support, also hook compat_do_execve in the same file.
For 3.14- kernels, use ksu_handle_execve and ksu_handle_post_execve instead of ksu_handle_execveat and ksu_handle_post_execveat, and hook do_execve and compat_do_execve in fs/exec.c. Notice that ksu_handle_post_execve is called after do_execve/compat_do_execve and before retval is returned.
If kernel's do_execve_common uses struct filename instead of char filename, refer to the 3.14+ hook pattern to that kernel's function signature.
faccessat hook Required
For this hook, different kernel versions are inconsistent, so it is explained separately here
4.19+
--- a/fs/open.c
+++ b/fs/open.c
@@ -450,8 +450,16 @@ long do_faccessat(int dfd, const char __user *filename, int mode)
return res;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+__attribute__((hot))
+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)
{
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
+#endif
return do_faccessat(dfd, filename, mode);
}
4.19-
--- a/fs/open.c
+++ b/fs/open.c
@@ -354,6 +354,11 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
return error;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+__attribute__((hot))
+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
@@ -369,6 +374,10 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
int res;
unsigned int lookup_flags = LOOKUP_FOLLOW;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
+#endif
+
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;
In this part, you should find faccessat in fs/open.c and hook it.
sys_reboot hook Required
For this hook, different kernel versions are inconsistent, so it is explained separately here
3.11+
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -277,6 +277,11 @@ static DEFINE_MUTEX(reboot_mutex);
*
* reboot doesn't sync: do that yourself before calling this.
*/
+
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user **arg);
+#endif
+
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
@@ -284,6 +289,9 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
char buffer[256];
int ret = 0;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_sys_reboot(magic1, magic2, cmd, &arg);
+#endif
/* We only trust the superuser with rebooting the system. */
if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
return -EPERM;
3.11-
diff --git a/kernel/sys.c b/kernel/sys.c
index a3bef5bd..08d196f5 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -455,6 +455,10 @@ EXPORT_SYMBOL_GPL(kernel_power_off);
static DEFINE_MUTEX(reboot_mutex);
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user **arg);
+#endif
+
/*
* Reboot system call: for obvious reasons only root may call it,
* and even root needs to set up some magic numbers in the registers
@@ -470,6 +474,10 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
char buffer[256];
int ret = 0;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ ksu_handle_sys_reboot(magic1, magic2, cmd, &arg);
+#endif
+
/* We only trust the superuser with rebooting the system. */
if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
return -EPERM;
In this part, you should find reboot SYSCALL in kernel/reboot.c and hook it. Note that for 3.11- kernels, you need to hook reboot in kernel/sys.c instead.
input hook Conditionally Required
input.c
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -436,11 +436,22 @@ static void input_handle_event(struct input_dev *dev,
* to 'seed' initial state of a switch or initial position of absolute
* axis, etc.
*/
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern bool ksu_input_hook __read_mostly;
+extern __attribute__((cold)) int ksu_handle_input_handle_event(
+ unsigned int *type, unsigned int *code, int *value);
+#endif
+
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
unsigned long flags;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value);
+#endif
+
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
In this part, you should find input_event in drivers/input/input.c and hook it.
setuid hook 6.8+ Required
4.17+
diff --git a/kernel/sys.c b/kernel/sys.c
index 4a87dc5fa..aac25df8c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -679,6 +679,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+#endif
+
/*
* This function implements a generic ability to update ruid, euid,
* and suid. This allows you to implement the 4.4 compatible seteuid().
@@ -692,6 +696,10 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
kuid_t kruid, keuid, ksuid;
bool ruid_new, euid_new, suid_new;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ (void)ksu_handle_setresuid(ruid, euid, suid);
+#endif
+
kruid = make_kuid(ns, ruid);
keuid = make_kuid(ns, euid);
ksuid = make_kuid(ns, suid);
4.17-
diff --git a/kernel/sys.c b/kernel/sys.c
index a3bef5bd..0b116d7c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -835,6 +843,9 @@ error:
return retval;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+#endif
/*
* This function implements a generic ability to update ruid, euid,
@@ -848,6 +859,10 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
int retval;
kuid_t kruid, keuid, ksuid;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ (void)ksu_handle_setresuid(ruid, euid, suid);
+#endif
+
kruid = make_kuid(ns, ruid);
keuid = make_kuid(ns, euid);
ksuid = make_kuid(ns, suid);
In this part, you should find __sys_setresuid in kernel/sys.c and hook them. Note that for 4.17- kernels, you need to hook setresuid instead.
sys_read hook 6.8+ Required
4.19+
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -586,8 +586,18 @@ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
return ret;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern bool ksu_init_rc_hook __read_mostly;
+extern __attribute__((cold)) int ksu_handle_sys_read(unsigned int fd,
+ char __user **buf_ptr, size_t *count_ptr);
+#endif
+
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ if (unlikely(ksu_init_rc_hook))
+ ksu_handle_sys_read(fd, &buf, &count);
+#endif
return ksys_read(fd, buf, count);
}
4.19-
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -568,11 +568,21 @@ static inline void file_pos_write(struct file *file, loff_t pos)
file->f_pos = pos;
}
+#ifdef CONFIG_KSU_MANUAL_HOOK
+extern bool ksu_init_rc_hook __read_mostly;
+extern __attribute__((cold)) int ksu_handle_sys_read(unsigned int fd,
+ char __user **buf_ptr, size_t *count_ptr);
+#endif
+
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
struct fd f = fdget_pos(fd);
ssize_t ret = -EBADF;
+#ifdef CONFIG_KSU_MANUAL_HOOK
+ if (unlikely(ksu_init_rc_hook))
+ ksu_handle_sys_read(fd, &buf, &count);
+#endif
if (f.file) {
loff_t pos = file_pos_read(f.file);
ret = vfs_read(f.file, buf, count, &pos);
In this part, you should find read in fs/read_write.c and hook it. Note that for 4.19- kernels, you only need to hook read, and you can ignore ksys_read as it is implemented via read in those versions.
Static symbol export
write_op export Required
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -XXXX,X +XXXX,X @@
-static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+ssize_t (*write_op[])(struct file *, char *, size_t) = {
[SEL_ACCESS] = sel_write_access,
[SEL_CREATE] = sel_write_create,
Remove static from the definition of write_op in security/selinux/selinuxfs.c
sel_handle_status_ops export Required
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -XXXX,X +XXXX,X @@
-static const struct file_operations sel_handle_status_ops = {
+const struct file_operations sel_handle_status_ops = {
.open = sel_open_handle_status,
.read = sel_read_handle_status,
.mmap = sel_mmap_handle_status,
Remove static from the definition of sel_handle_status_ops in security/selinux/selinuxfs.c
selinux_status_page & selinux_status_lock export 4.17- Conditionally Required
--- a/security/selinux/ss/status.c
+++ b/security/selinux/ss/status.c
@@ -XXXX,X +XXXX,X @@
* In most cases, application shall confirm the kernel status is not
* changed without any system call invocations.
*/
-static struct page *selinux_status_page;
-static DEFINE_MUTEX(selinux_status_lock);
+struct page *selinux_status_page;
+DEFINE_MUTEX(selinux_status_lock);
Remove static from the definition of selinux_status_page and selinux_status_lock in security/selinux/ss/status.c
If this definition not found,please ignore this part.
security_dump_masked_av Required
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -XXXX,X +XXXX,X @@
-static void security_dump_masked_av(struct policydb *policydb,
+void security_dump_masked_av(struct policydb *policydb,
struct context *scontext,
struct context *tcontext,
u16 tclass,
u32 permissions,
const char *reason)
{
struct common_datum *common_dat;
struct class_datum *tclass_dat;
Remove static from the definition of security_dump_masked_av in security/selinux/ss/services.c
context_struct_compute_av Required
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -XXXX,X +XXXX,X @@
/*
* Compute access vectors and extended permissions based on a context
* structure pair for the permissions in a particular class.
*/
-static void context_struct_compute_av(struct policydb *policydb,
+void context_struct_compute_av(struct policydb *policydb,
struct context *scontext,
struct context *tcontext,
u16 tclass,
struct av_decision *avd,
struct extended_perms *xperms)
{
Remove static from the definition of context_struct_compute_av in security/selinux/ss/services.c
policy_rwlock export 4.17- Conditionally Required
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b818410d2418..ea2f3022744f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -76,7 +76,7 @@ int selinux_policycap_netpeer;
int selinux_policycap_openperm;
int selinux_policycap_alwaysnetwork;
-static DEFINE_RWLOCK(policy_rwlock);
+DEFINE_RWLOCK(policy_rwlock);
static struct sidtab sidtab;
struct policydb policydb;
Remove static from the definition of policy_rwlock in security/selinux/ss/services.c
If this definition not found,please ignore this part.
sel_mutex export 4.17- Conditionally Required
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -41,23 +42,6 @@
#include "objsec.h"
#include "conditional.h
-static DEFINE_MUTEX(sel_mutex);
+DEFINE_MUTEX(sel_mutex);
Remove static from the definition of sel_mutex in security/selinux/selinuxfs.c
If this definition not found,please ignore this part.
selinux_ops export 4.2- Required
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -XXXX,X +XXXX,X @@
-static struct security_operations selinux_ops = {
+struct security_operations selinux_ops = {
.name = "selinux",
Remove static from the definition of selinux_ops in security/selinux/selinuxfs.c