diff --git a/kernel/patch/common/kstorage.c b/kernel/patch/common/kstorage.c index 6fe8010..bf50d39 100644 --- a/kernel/patch/common/kstorage.c +++ b/kernel/patch/common/kstorage.c @@ -1,10 +1,10 @@ #include + #include #include #include #include #include -#include #include #include #include @@ -127,7 +127,7 @@ KP_EXPORT_SYMBOL(get_kstorage); int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata) { - if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return; + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return 0; int rc = 0; @@ -153,7 +153,8 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_ int rc = 0; rcu_read_lock(); - struct kstorage *pos = get_kstorage(gid, did); + const struct kstorage *pos = get_kstorage(gid, did); + if (IS_ERR(pos)) return PTR_ERR(pos); int min_len = pos->dlen - offset > len ? len : pos->dlen - offset; diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 54e27de..6a017d3 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -49,13 +49,6 @@ const char apd_path[] = APD_PATH; static const char *current_su_path = 0; -struct su_profile -{ - uid_t uid; - uid_t to_uid; - char scontext[SUPERCALL_SCONTEXT_LEN]; -}; - int is_su_allow_uid(uid_t uid) { rcu_read_lock(); @@ -70,7 +63,11 @@ KP_EXPORT_SYMBOL(is_su_allow_uid); int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext) { if (!scontext) scontext = ""; - struct su_profile profile = { uid, to_uid, scontext }; + struct su_profile profile = { + uid, + to_uid, + }; + memcpy(profile.scontext, scontext, SUPERCALL_SCONTEXT_LEN); int rc = write_kstorage(KSTORAGE_SU_LIST_GROUP, uid, &profile, 0, sizeof(struct su_profile), false); logkfd("uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, scontext, rc); return rc; @@ -98,16 +95,19 @@ static int allow_uids_cb(struct kstorage *kstorage, void *udata) int out_num; } *up = (typeof(up))udata; + struct su_profile *profile = (struct su_profile *)kstorage->data; + + int num = 0; + if (up->is_user) { - int cplen = compat_copy_to_user(up->out_uids + num, &uid, sizeof(uid)); - logkfd("uid: %d\n", uid); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; + int cprc = compat_copy_to_user(up->out_uids + num, &profile->uid, sizeof(uid_t)); + logkfd("uid: %d\n", profile->uid); + if (cprc <= 0) { + logkfd("compat_copy_to_user error: %d", cprc); + return cprc; } } else { - out_uids[num] = uid; + up->out_uids[num] = profile->uid; } num++; @@ -129,28 +129,29 @@ int su_allow_uids(int is_user, uid_t *out_uids, int out_num) } KP_EXPORT_SYMBOL(su_allow_uids); -int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile) +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *out_profile) { - int rc = -ENOENT; + int rc = 0; + rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->profile.uid != uid) continue; - if (is_user) { - int cplen = compat_copy_to_user(profile, &pos->profile, sizeof(struct su_profile)); - logkfd("profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; - } - } else { - memcpy(profile, &pos->profile, sizeof(struct su_profile)); - } - rc = 0; + const struct kstorage *ks = get_kstorage(KSTORAGE_SU_LIST_GROUP, uid); + if (IS_ERR(ks)) { + rc = -ENOENT; goto out; } + struct su_profile *profile = (struct su_profile *)ks->data; + + if (is_user) { + rc = compat_copy_to_user(out_profile, profile, sizeof(struct su_profile)); + if (rc <= 0) { + logkfd("compat_copy_to_user error: %d", rc); + goto out; + } + logkfd("%d %d %s\n", profile->uid, profile->to_uid, profile->scontext); + } else { + memcpy(out_profile, profile, sizeof(struct su_profile)); + } + out: rcu_read_unlock(); return rc; @@ -185,8 +186,8 @@ static void handle_before_execve(char **__user u_filename_p, char **__user uargv if (!strcmp(current_su_path, filename)) { uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - struct su_profile profile = profile_su_allow_uid(uid); + struct su_profile profile; + if (su_allow_uid_profile(0, uid, &profile)) return; uid_t to_uid = profile.to_uid; const char *sctx = profile.scontext; @@ -317,18 +318,18 @@ int su_compat_init() #ifdef ANDROID // default shell if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); - su_add_allow_uid(2000, 0, all_allow_sctx, 1); - su_add_allow_uid(0, 0, all_allow_sctx, 1); + su_add_allow_uid(2000, 0, all_allow_sctx); + su_add_allow_uid(0, 0, all_allow_sctx); #endif hook_err_t rc = HOOK_NO_ERR; uint8_t su_config = patch_config->patch_su_config; - bool enable = su_config & PATCH_CONFIG_SU_ENABLE; - bool wrap = su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP; - log_boot("su config, enable: %d, wrap: %d\n"); + bool enable = !!(su_config & PATCH_CONFIG_SU_ENABLE); + bool wrap = !!(su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP); + log_boot("su config: %x, enable: %d, wrap: %d\n", su_config, enable, wrap); - if (!enable) return; + // if (!enable) return; rc = hook_syscalln(__NR_execve, 3, before_execve, 0, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index f8bf6fb..0b35889 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -166,14 +166,14 @@ static long call_grant_uid(struct su_profile *__user uprofile) { struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); if (!profile || IS_ERR(profile)) return PTR_ERR(profile); - int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, 1); + int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext); kvfree(profile); return rc; } static long call_revoke_uid(uid_t uid) { - return su_remove_allow_uid(uid, 1); + return su_remove_allow_uid(uid); } static long call_su_allow_uid_nums() diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index afcc24e..1d9aa8e 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -58,8 +58,7 @@ static const char supercmd_help[] = "" "KernelPatch supercmd:\n" "Usage: truncate [-uZc] [Command [[SubCommand]...]]\n" - "superkey|su: Authentication. For certain commands, if the current uid is allowed to use su,\n" - " the 'su' string can be used for authentication.\n" + "superkey|su: Authentication.\n" "Options:\n" " -u Change user id to UID.\n" " -Z Change security context to SCONTEXT.\n" @@ -122,7 +121,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } if (carr[3]) kstrtoull(carr[3], 10, &to_uid); if (carr[4]) scontext = carr[4]; - su_add_allow_uid(uid, to_uid, scontext, 1); + su_add_allow_uid(uid, to_uid, scontext); sprintf(buffer, "grant %d, %d, %s", uid, to_uid, scontext); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "revoke")) { @@ -133,7 +132,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char cmd_res->err_msg = buffer; return; } - su_remove_allow_uid(uid, 1); + su_remove_allow_uid(uid); cmd_res->msg = suid; } else if (!strcmp(sub_cmd, "num")) { int num = su_allow_uid_nums(); @@ -298,7 +297,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else if (!strcmp("su", arg1)) { uid_t uid = current_uid(); if (!is_su_allow_uid(uid)) return; - profile = profile_su_allow_uid(uid); + su_allow_uid_profile(0, uid, &profile); } else { return; } diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index dd1f54c..829fe53 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -24,14 +24,6 @@ int commit_common_su(uid_t to_uid, const char *sctx); int commit_su(uid_t uid, const char *sctx); int task_su(pid_t pid, uid_t to_uid, const char *sctx); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext); -int su_remove_allow_uid(uid_t uid); -int su_allow_uid_nums(); -int su_allow_uids(int is_user, uid_t *out_uids, int out_num); -int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); -int su_reset_path(const char *path); -const char *su_get_path(); - /** * @brief Whether to make the current task bypass all selinux permission checks. * diff --git a/kernel/patch/include/kstorage.h b/kernel/patch/include/kstorage.h index 13159d2..8e7c0a2 100644 --- a/kernel/patch/include/kstorage.h +++ b/kernel/patch/include/kstorage.h @@ -6,8 +6,8 @@ #ifndef _KP_KSTORAGE_H_ #define _KP_KSTORAGE_H_ -#include #include +#include #include struct kstorage @@ -30,7 +30,7 @@ int write_kstorage(int gid, long did, void *data, int offset, int len, bool data // must surround with rcu read lock const struct kstorage *get_kstorage(int gid, long did); -typedef int (*on_kstorage_cb)(struct kstroage *kstorage, void *udata); +typedef int (*on_kstorage_cb)(struct kstorage *kstorage, void *udata); int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata); const struct kstorage *get_kstorage(int gid, long did); diff --git a/kernel/patch/include/sucompat.h b/kernel/patch/include/sucompat.h index 03a00bb..d1da7bc 100644 --- a/kernel/patch/include/sucompat.h +++ b/kernel/patch/include/sucompat.h @@ -23,8 +23,14 @@ struct allow_uid struct rcu_head rcu; }; -struct su_profile profile_su_allow_uid(uid_t uid); int is_su_allow_uid(uid_t uid); +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext); +int su_remove_allow_uid(uid_t uid); +int su_allow_uid_nums(); +int su_allow_uids(int is_user, uid_t *out_uids, int out_num); +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); +int su_reset_path(const char *path); +const char *su_get_path(); void handle_supercmd(char **__user u_filename_p, char **__user uargv); diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index ff273b6..19ac252 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -65,6 +65,13 @@ struct kernel_storage #define SUPERCALL_KEY_MAX_LEN 0x40 #define SUPERCALL_SCONTEXT_LEN 0x60 +struct su_profile +{ + uid_t uid; + uid_t to_uid; + char scontext[SUPERCALL_SCONTEXT_LEN]; +}; + #ifdef ANDROID #define SH_PATH "/system/bin/sh" #define SU_PATH "/system/bin/kp"