Hook improvements (take 2) (#563)

Hi @tiann.

Thanks for the great project, I had great fun playing around with it.

This PR mainly tries to further minimize the possible delays caused by
KernelSU hooking.

There are 3 major changes:
- Processes with 0 < UID < 2000 are blocked straight-up before going
through the allow_list.
I don't see any need for such processes to be interested in root, and
this allows returning early before going through a more expensive
lookup.
If there's an expected breakage due to this change, I'll remove it. Let
me know.
- A page-sized (4K) bitmap is added.
This allows O(1) lookup for UID <= 32767.
This speeds up `ksu_is_allow_uid()` by about 4.8x by sacrificing a 4K
memory. IMHO, a good trade-off.
Most notably, this reduces the 99.999% result previously from worrying
milliseconds scale to microseconds scale.
For UID > 32767, another page-sized (4K) sequential array is used to
cache allow_list.

Compared to the previous PR #557, this new approach gives another nice
25% performance boost in average, 63-96% boost in worst cases.

Benchmark results are available at
https://docs.google.com/spreadsheets/d/1w_tO1zRLPNMFRer49pL1TQfL6ndEhilRrDU1XFIcWXY/edit?usp=sharing

Thanks!

---------

Signed-off-by: Juhyung Park <qkrwngud825@gmail.com>
This commit is contained in:
Juhyung Park
2023-06-16 20:53:15 +09:00
committed by GitHub
parent c697398893
commit bd8434f4f4
21 changed files with 233 additions and 102 deletions

View File

@@ -29,6 +29,38 @@ static DEFINE_MUTEX(allowlist_mutex);
static struct root_profile default_root_profile; static struct root_profile default_root_profile;
static struct non_root_profile default_non_root_profile; static struct non_root_profile default_non_root_profile;
static int allow_list_arr[PAGE_SIZE / sizeof(int)] __read_mostly __aligned(PAGE_SIZE);
static int allow_list_pointer __read_mostly = 0;
static void remove_uid_from_arr(uid_t uid)
{
int *temp_arr;
int i, j;
if (allow_list_pointer == 0)
return;
temp_arr = kmalloc(sizeof(allow_list_arr), GFP_KERNEL);
if (temp_arr == NULL) {
pr_err("%s: unable to allocate memory\n", __func__);
return;
}
for (i = j = 0; i < allow_list_pointer; i++) {
if (allow_list_arr[i] == uid)
continue;
temp_arr[j++] = allow_list_arr[i];
}
allow_list_pointer = j;
for (; j < ARRAY_SIZE(allow_list_arr); j++)
temp_arr[j] = -1;
memcpy(&allow_list_arr, temp_arr, PAGE_SIZE);
kfree(temp_arr);
}
static void init_default_profiles() static void init_default_profiles()
{ {
default_root_profile.uid = 0; default_root_profile.uid = 0;
@@ -51,6 +83,9 @@ struct perm_data {
static struct list_head allow_list; static struct list_head allow_list;
static uint8_t allow_list_bitmap[PAGE_SIZE] __read_mostly __aligned(PAGE_SIZE);
#define BITMAP_UID_MAX ((sizeof(allow_list_bitmap) * BITS_PER_BYTE) - 1)
#define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist" #define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist"
static struct work_struct ksu_save_work; static struct work_struct ksu_save_work;
@@ -110,6 +145,11 @@ static bool profile_valid(struct app_profile *profile)
return false; return false;
} }
if (profile->current_uid < 2000) {
pr_err("uid lower than 2000 is unsupported: %d\n", profile->current_uid);
return false;
}
if (profile->version < KSU_APP_PROFILE_VER) { if (profile->version < KSU_APP_PROFILE_VER) {
pr_info("Unsupported profile version: %d\n", profile->version); pr_info("Unsupported profile version: %d\n", profile->version);
return false; return false;
@@ -147,7 +187,7 @@ bool ksu_set_app_profile(struct app_profile *profile, bool persist)
// found it, just override it all! // found it, just override it all!
memcpy(&p->profile, profile, sizeof(*profile)); memcpy(&p->profile, profile, sizeof(*profile));
result = true; result = true;
goto exit; goto out;
} }
} }
@@ -170,9 +210,31 @@ bool ksu_set_app_profile(struct app_profile *profile, bool persist)
profile->nrp_config.profile.umount_modules); profile->nrp_config.profile.umount_modules);
} }
list_add_tail(&p->list, &allow_list); list_add_tail(&p->list, &allow_list);
out:
if (profile->current_uid <= BITMAP_UID_MAX) {
if (profile->allow_su)
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] |= 1 << (profile->current_uid % BITS_PER_BYTE);
else
allow_list_bitmap[profile->current_uid / BITS_PER_BYTE] &= ~(1 << (profile->current_uid % BITS_PER_BYTE));
} else {
if (profile->allow_su) {
/*
* 1024 apps with uid higher than BITMAP_UID_MAX
* registered to request superuser?
*/
if (allow_list_pointer >= ARRAY_SIZE(allow_list_arr)) {
pr_err("too many apps registered\n");
WARN_ON(1);
return false;
}
allow_list_arr[allow_list_pointer++] = profile->current_uid;
} else {
remove_uid_from_arr(profile->current_uid);
}
}
result = true; result = true;
exit:
// check if the default profiles is changed, cache it to a single struct to accelerate access. // check if the default profiles is changed, cache it to a single struct to accelerate access.
if (unlikely(!strcmp(profile->key, "$"))) { if (unlikely(!strcmp(profile->key, "$"))) {
// set default non root profile // set default non root profile
@@ -192,21 +254,26 @@ exit:
return result; return result;
} }
bool ksu_is_allow_uid(uid_t uid) bool __ksu_is_allow_uid(uid_t uid)
{ {
struct perm_data *p = NULL; int i;
struct list_head *pos = NULL;
if (uid == 0) { if (unlikely(uid == 0)) {
// already root, but only allow our domain. // already root, but only allow our domain.
return is_ksu_domain(); return is_ksu_domain();
} }
list_for_each (pos, &allow_list) { if (uid < 2000) {
p = list_entry(pos, struct perm_data, list); // do not bother going through the list if it's system
// pr_info("is_allow_uid uid :%d, allow: %d\n", p->uid, p->allow); return false;
if (uid == p->profile.current_uid) { }
return p->profile.allow_su;
if (likely(uid <= BITMAP_UID_MAX)) {
return !!(allow_list_bitmap[uid / BITS_PER_BYTE] & (1 << (uid % BITS_PER_BYTE)));
} else {
for (i = 0; i < allow_list_pointer; i++) {
if (allow_list_arr[i] == uid)
return true;
} }
} }
@@ -386,6 +453,9 @@ void ksu_prune_allowlist(bool (*is_uid_exist)(uid_t, void *), void *data)
modified = true; modified = true;
pr_info("prune uid: %d\n", uid); pr_info("prune uid: %d\n", uid);
list_del(&np->list); list_del(&np->list);
allow_list_bitmap[uid / BITS_PER_BYTE] &= ~(1 << (uid % BITS_PER_BYTE));
remove_uid_from_arr(uid);
smp_mb();
kfree(np); kfree(np);
} }
} }
@@ -409,6 +479,14 @@ bool ksu_load_allow_list(void)
void ksu_allowlist_init(void) void ksu_allowlist_init(void)
{ {
int i;
BUILD_BUG_ON(sizeof(allow_list_bitmap) != PAGE_SIZE);
BUILD_BUG_ON(sizeof(allow_list_arr) != PAGE_SIZE);
for (i = 0; i < ARRAY_SIZE(allow_list_arr); i++)
allow_list_arr[i] = -1;
INIT_LIST_HEAD(&allow_list); INIT_LIST_HEAD(&allow_list);
INIT_WORK(&ksu_save_work, do_save_allow_list); INIT_WORK(&ksu_save_work, do_save_allow_list);

View File

@@ -12,7 +12,8 @@ bool ksu_load_allow_list(void);
void ksu_show_allow_list(void); void ksu_show_allow_list(void);
bool ksu_is_allow_uid(uid_t uid); bool __ksu_is_allow_uid(uid_t uid);
#define ksu_is_allow_uid(uid) unlikely(__ksu_is_allow_uid(uid))
bool ksu_get_allow_list(int *array, int *length, bool allow); bool ksu_get_allow_list(int *array, int *length, bool allow);

View File

@@ -52,9 +52,9 @@ static struct work_struct stop_vfs_read_work;
static struct work_struct stop_execve_hook_work; static struct work_struct stop_execve_hook_work;
static struct work_struct stop_input_hook_work; static struct work_struct stop_input_hook_work;
#else #else
static bool vfs_read_hook = true; bool ksu_vfs_read_hook __read_mostly = true;
static bool execveat_hook = true; bool ksu_execveat_hook __read_mostly = true;
static bool input_hook = true; bool ksu_input_hook __read_mostly = true;
#endif #endif
void on_post_fs_data(void) void on_post_fs_data(void)
@@ -138,7 +138,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
void *argv, void *envp, int *flags) void *argv, void *envp, int *flags)
{ {
#ifndef CONFIG_KPROBES #ifndef CONFIG_KPROBES
if (!execveat_hook) { if (!ksu_execveat_hook) {
return 0; return 0;
} }
#endif #endif
@@ -157,8 +157,8 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
return 0; return 0;
} }
if (!memcmp(filename->name, system_bin_init, if (unlikely(!memcmp(filename->name, system_bin_init,
sizeof(system_bin_init) - 1)) { sizeof(system_bin_init) - 1))) {
#ifdef __aarch64__ #ifdef __aarch64__
// /system/bin/init executed // /system/bin/init executed
struct user_arg_ptr *ptr = (struct user_arg_ptr*) argv; struct user_arg_ptr *ptr = (struct user_arg_ptr*) argv;
@@ -200,8 +200,8 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
#endif #endif
} }
if (first_app_process && if (unlikely(first_app_process &&
!memcmp(filename->name, app_process, sizeof(app_process) - 1)) { !memcmp(filename->name, app_process, sizeof(app_process) - 1))) {
first_app_process = false; first_app_process = false;
pr_info("exec app_process, /data prepared, second_stage: %d\n", init_second_stage_executed); pr_info("exec app_process, /data prepared, second_stage: %d\n", init_second_stage_executed);
on_post_fs_data(); // we keep this for old ksud on_post_fs_data(); // we keep this for old ksud
@@ -244,7 +244,7 @@ int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
size_t *count_ptr, loff_t **pos) size_t *count_ptr, loff_t **pos)
{ {
#ifndef CONFIG_KPROBES #ifndef CONFIG_KPROBES
if (!vfs_read_hook) { if (!ksu_vfs_read_hook) {
return 0; return 0;
} }
#endif #endif
@@ -345,7 +345,7 @@ int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code,
int *value) int *value)
{ {
#ifndef CONFIG_KPROBES #ifndef CONFIG_KPROBES
if (!input_hook) { if (!ksu_input_hook) {
return 0; return 0;
} }
#endif #endif
@@ -463,7 +463,7 @@ static void stop_vfs_read_hook()
bool ret = schedule_work(&stop_vfs_read_work); bool ret = schedule_work(&stop_vfs_read_work);
pr_info("unregister vfs_read kprobe: %d!\n", ret); pr_info("unregister vfs_read kprobe: %d!\n", ret);
#else #else
vfs_read_hook = false; ksu_vfs_read_hook = false;
#endif #endif
} }
@@ -473,7 +473,7 @@ static void stop_execve_hook()
bool ret = schedule_work(&stop_execve_hook_work); bool ret = schedule_work(&stop_execve_hook_work);
pr_info("unregister execve kprobe: %d!\n", ret); pr_info("unregister execve kprobe: %d!\n", ret);
#else #else
execveat_hook = false; ksu_execveat_hook = false;
#endif #endif
} }
@@ -488,7 +488,7 @@ static void stop_input_hook()
bool ret = schedule_work(&stop_input_hook_work); bool ret = schedule_work(&stop_input_hook_work);
pr_info("unregister input kprobe: %d!\n", ret); pr_info("unregister input kprobe: %d!\n", ret);
#else #else
input_hook = false; ksu_input_hook = false;
#endif #endif
} }

View File

@@ -15,7 +15,7 @@ static inline bool ksu_is_manager_uid_valid()
static inline bool is_manager() static inline bool is_manager()
{ {
return ksu_manager_uid == current_uid().val; return unlikely(ksu_manager_uid == current_uid().val);
} }
static inline uid_t ksu_get_manager_uid() static inline uid_t ksu_get_manager_uid()

View File

@@ -53,7 +53,7 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
if (IS_ERR(filename)) { if (IS_ERR(filename)) {
return 0; return 0;
} }
if (!memcmp(filename->name, su, sizeof(su))) { if (unlikely(!memcmp(filename->name, su, sizeof(su)))) {
pr_info("faccessat su->sh!\n"); pr_info("faccessat su->sh!\n");
*filename_user = sh_user_path(); *filename_user = sh_user_path();
} }
@@ -73,7 +73,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
return 0; return 0;
} }
if (!filename_user) { if (unlikely(!filename_user)) {
return 0; return 0;
} }
@@ -82,7 +82,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
if (IS_ERR(filename)) { if (IS_ERR(filename)) {
return 0; return 0;
} }
if (!memcmp(filename->name, su, sizeof(su))) { if (unlikely(!memcmp(filename->name, su, sizeof(su)))) {
pr_info("newfstatat su->sh!\n"); pr_info("newfstatat su->sh!\n");
*filename_user = sh_user_path(); *filename_user = sh_user_path();
} }
@@ -99,7 +99,7 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
const char sh[] = KSUD_PATH; const char sh[] = KSUD_PATH;
const char su[] = SU_PATH; const char su[] = SU_PATH;
if (!filename_ptr) if (unlikely(!filename_ptr))
return 0; return 0;
filename = *filename_ptr; filename = *filename_ptr;
@@ -107,16 +107,16 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
return 0; return 0;
} }
if (!ksu_is_allow_uid(current_uid().val)) { if (likely(memcmp(filename->name, su, sizeof(su))))
return 0;
if (!ksu_is_allow_uid(current_uid().val))
return 0; return 0;
}
if (!memcmp(filename->name, su, sizeof(su))) {
pr_info("do_execveat_common su found\n"); pr_info("do_execveat_common su found\n");
memcpy((void *)filename->name, sh, sizeof(sh)); memcpy((void *)filename->name, sh, sizeof(sh));
escape_to_root(); escape_to_root();
}
return 0; return 0;
} }

View File

@@ -75,14 +75,20 @@ index ac59664eaecf..bdd585e1d2cc 100644
return retval; return retval;
} }
+extern bool ksu_execveat_hook __read_mostly;
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags); + void *envp, int *flags);
+extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
static int do_execveat_common(int fd, struct filename *filename, static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv, struct user_arg_ptr argv,
struct user_arg_ptr envp, struct user_arg_ptr envp,
int flags) int flags)
{ {
+ if (unlikely(ksu_execveat_hook))
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); + ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
+ else
+ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
return __do_execve_file(fd, filename, argv, envp, flags, NULL); return __do_execve_file(fd, filename, argv, envp, flags, NULL);
} }
@@ -115,12 +121,14 @@ index 650fc7e0f3a6..55be193913b6 100644
} }
EXPORT_SYMBOL(kernel_read); EXPORT_SYMBOL(kernel_read);
+extern bool ksu_vfs_read_hook __read_mostly;
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, +extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos); + size_t *count_ptr, loff_t **pos);
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{ {
ssize_t ret; ssize_t ret;
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_vfs_read(&file, &buf, &count, &pos); + ksu_handle_vfs_read(&file, &buf, &count, &pos);
+ +
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
@@ -225,12 +233,15 @@ index 45306f9ef247..815091ebfca4 100755
return disposition; return disposition;
} }
+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_input_handle_event(unsigned int *type, unsigned int *code, int *value);
+ +
static void input_handle_event(struct input_dev *dev, static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
int disposition = input_get_disposition(dev, type, code, &value); int disposition = input_get_disposition(dev, type, code, &value);
+
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value); + ksu_handle_input_handle_event(&type, &code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)

View File

@@ -70,14 +70,20 @@ index ac59664eaecf..bdd585e1d2cc 100644
return retval; return retval;
} }
+extern bool ksu_execveat_hook __read_mostly;
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags); + void *envp, int *flags);
+extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
static int do_execveat_common(int fd, struct filename *filename, static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv, struct user_arg_ptr argv,
struct user_arg_ptr envp, struct user_arg_ptr envp,
int flags) int flags)
{ {
+ if (unlikely(ksu_execveat_hook))
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); + ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
+ else
+ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
return __do_execve_file(fd, filename, argv, envp, flags, NULL); return __do_execve_file(fd, filename, argv, envp, flags, NULL);
} }
@@ -110,12 +116,14 @@ index 650fc7e0f3a6..55be193913b6 100644
} }
EXPORT_SYMBOL(kernel_read); EXPORT_SYMBOL(kernel_read);
+extern bool ksu_vfs_read_hook __read_mostly;
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, +extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos); + size_t *count_ptr, loff_t **pos);
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{ {
ssize_t ret; ssize_t ret;
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_vfs_read(&file, &buf, &count, &pos); + ksu_handle_vfs_read(&file, &buf, &count, &pos);
+ +
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
@@ -220,12 +228,15 @@ index 45306f9ef247..815091ebfca4 100755
return disposition; return disposition;
} }
+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_input_handle_event(unsigned int *type, unsigned int *code, int *value);
+ +
static void input_handle_event(struct input_dev *dev, static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
int disposition = input_get_disposition(dev, type, code, &value); int disposition = input_get_disposition(dev, type, code, &value);
+
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value); + ksu_handle_input_handle_event(&type, &code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)

View File

@@ -71,14 +71,20 @@ index ac59664eaecf..bdd585e1d2cc 100644
return retval; return retval;
} }
+extern bool ksu_execveat_hook __read_mostly;
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags); + void *envp, int *flags);
+extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
static int do_execveat_common(int fd, struct filename *filename, static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv, struct user_arg_ptr argv,
struct user_arg_ptr envp, struct user_arg_ptr envp,
int flags) int flags)
{ {
+ if (unlikely(ksu_execveat_hook))
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); + ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
+ else
+ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
return __do_execve_file(fd, filename, argv, envp, flags, NULL); return __do_execve_file(fd, filename, argv, envp, flags, NULL);
} }
@@ -111,12 +117,14 @@ index 650fc7e0f3a6..55be193913b6 100644
} }
EXPORT_SYMBOL(kernel_read); EXPORT_SYMBOL(kernel_read);
+extern bool ksu_vfs_read_hook __read_mostly;
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, +extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos); + size_t *count_ptr, loff_t **pos);
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{ {
ssize_t ret; ssize_t ret;
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_vfs_read(&file, &buf, &count, &pos); + ksu_handle_vfs_read(&file, &buf, &count, &pos);
+ +
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))

View File

@@ -75,14 +75,20 @@ index ac59664eaecf..bdd585e1d2cc 100644
return retval; return retval;
} }
+extern bool ksu_execveat_hook __read_mostly;
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags); + void *envp, int *flags);
+extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
static int do_execveat_common(int fd, struct filename *filename, static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv, struct user_arg_ptr argv,
struct user_arg_ptr envp, struct user_arg_ptr envp,
int flags) int flags)
{ {
+ if (unlikely(ksu_execveat_hook))
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); + ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
+ else
+ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
return __do_execve_file(fd, filename, argv, envp, flags, NULL); return __do_execve_file(fd, filename, argv, envp, flags, NULL);
} }
@@ -115,12 +121,14 @@ index 650fc7e0f3a6..55be193913b6 100644
} }
EXPORT_SYMBOL(kernel_read); EXPORT_SYMBOL(kernel_read);
+extern bool ksu_vfs_read_hook __read_mostly;
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, +extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos); + size_t *count_ptr, loff_t **pos);
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{ {
ssize_t ret; ssize_t ret;
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_vfs_read(&file, &buf, &count, &pos); + ksu_handle_vfs_read(&file, &buf, &count, &pos);
+ +
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
@@ -225,12 +233,15 @@ index 45306f9ef247..815091ebfca4 100755
return disposition; return disposition;
} }
+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_input_handle_event(unsigned int *type, unsigned int *code, int *value);
+ +
static void input_handle_event(struct input_dev *dev, static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
int disposition = input_get_disposition(dev, type, code, &value); int disposition = input_get_disposition(dev, type, code, &value);
+
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value); + ksu_handle_input_handle_event(&type, &code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)

View File

@@ -75,14 +75,20 @@ index ac59664eaecf..bdd585e1d2cc 100644
return retval; return retval;
} }
+extern bool ksu_execveat_hook __read_mostly;
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv, +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags); + void *envp, int *flags);
+extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
static int do_execveat_common(int fd, struct filename *filename, static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv, struct user_arg_ptr argv,
struct user_arg_ptr envp, struct user_arg_ptr envp,
int flags) int flags)
{ {
+ if (unlikely(ksu_execveat_hook))
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags); + ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
+ else
+ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
return __do_execve_file(fd, filename, argv, envp, flags, NULL); return __do_execve_file(fd, filename, argv, envp, flags, NULL);
} }
@@ -115,12 +121,14 @@ index 650fc7e0f3a6..55be193913b6 100644
} }
EXPORT_SYMBOL(kernel_read); EXPORT_SYMBOL(kernel_read);
+extern bool ksu_vfs_read_hook __read_mostly;
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr, +extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos); + size_t *count_ptr, loff_t **pos);
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{ {
ssize_t ret; ssize_t ret;
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_vfs_read(&file, &buf, &count, &pos); + ksu_handle_vfs_read(&file, &buf, &count, &pos);
+ +
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
@@ -225,12 +233,15 @@ index 45306f9ef247..815091ebfca4 100755
return disposition; return disposition;
} }
+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_input_handle_event(unsigned int *type, unsigned int *code, int *value);
+ +
static void input_handle_event(struct input_dev *dev, static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) unsigned int type, unsigned int code, int value)
{ {
int disposition = input_get_disposition(dev, type, code, &value); int disposition = input_get_disposition(dev, type, code, &value);
+
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value); + ksu_handle_input_handle_event(&type, &code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)