diff --git a/kernel/base/start.c b/kernel/base/start.c index 27909e06..7c35c0cb 100644 --- a/kernel/base/start.c +++ b/kernel/base/start.c @@ -78,7 +78,6 @@ uint64_t _kp_rw_end = 0; uint64_t _kp_region_start = 0; uint64_t _kp_region_end = 0; -uint64_t ttbr1_el1 = 0; uint64_t kernel_va = 0; uint64_t kernel_stext_va = 0; uint64_t kernel_pa = 0; @@ -309,8 +308,6 @@ static void restore_map() static void pgtable_init() { - asm volatile("mrs %0, ttbr1_el1" : "=r"(ttbr1_el1)); - uint64_t addr = kallsyms_lookup_name("memstart_addr"); if (addr) memstart_addr = *(int64_t *)addr; diff --git a/kernel/patch/android/sucompat.c b/kernel/patch/android/sucompat.c index 28db7b80..e3474f9b 100644 --- a/kernel/patch/android/sucompat.c +++ b/kernel/patch/android/sucompat.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Modified from KernelSU, GPLv2 @@ -38,14 +39,6 @@ static const char *current_su_path = 0; static const char apd_path[] = APD_PATH; static const char kpatch_path[] = KPATCH_PATH; static const char kpatch_shadow_path[] = KPATCH_SHADOW_PATH; -static const char bypass_via_hook_sctx[] = "bypass_via_hook"; - -struct su_profile -{ - uid_t uid; - uid_t to_uid; - char scontext[SUPERCALL_SCONTEXT_LEN]; -}; struct allow_uid { @@ -97,7 +90,7 @@ static int is_allow_uid(uid_t uid) return 0; } -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *sctx, int async) +int su_add_allow_uid(uid_t uid, struct su_profile *profile, int async) { rcu_read_lock(); struct allow_uid *pos, *old = 0; @@ -109,22 +102,18 @@ int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *sctx, int async) } } struct allow_uid *new = (struct allow_uid *)kmalloc(sizeof(struct allow_uid), GFP_ATOMIC); - memset(new, 0, sizeof(struct allow_uid)); - new->uid = uid; - new->profile.uid = uid; - new->profile.to_uid = to_uid; - memset(new->profile.scontext, 0, sizeof(new->profile.scontext)); - if (sctx && strcmp(sctx, bypass_via_hook_sctx)) { - strlcpy(new->profile.scontext, sctx, sizeof(new->profile.scontext)); - } + new->uid = profile->uid; + memcpy(&new->profile, profile, sizeof(struct su_profile)); + new->profile.scontext[sizeof(new->profile.scontext) - 1] = '\0'; + kvfree(profile); spin_lock(&list_lock); if (old) { // update list_replace_rcu(&old->list, &new->list); - logkfi("update uid: %d, to_uid: %d, sctx: %s\n", uid, to_uid, sctx); + logkfi("update uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); } else { // add new one list_add_rcu(&new->list, &allow_uid_list); - logkfi("new uid: %d, to_uid: %d, sctx: %s\n", uid, to_uid, sctx); + logkfi("new uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); } spin_unlock(&list_lock); @@ -173,42 +162,76 @@ int su_allow_uid_nums() num++; } rcu_read_unlock(); + logkd("allow uid num: %d\n", num); return num; } -int su_list_allow_uids(char *__user ubuf, int ubuf_len) +int su_allow_uids(uid_t *__user uuids, int unum) { - int uoff = 0; - char line[SUPERCALL_SCONTEXT_LEN + 32]; + int rc = 0; + int num = 0; rcu_read_lock(); struct allow_uid *pos; list_for_each_entry(pos, &allow_uid_list, list) { - int lline = snprintf(line, sizeof(line), "%d,%d,%s\n", pos->uid, pos->profile.to_uid, pos->profile.scontext); - int left = ubuf_len - uoff; - if (left < lline) return -ENOMEM; - uoff += seq_copy_to_user(ubuf + uoff, line, lline); + if (num >= unum) { + goto out; + } + uid_t uid = pos->profile.uid; + int cplen = seq_copy_to_user(uuids + num, &uid, sizeof(uid)); + logkd("copy_to_user allow uid: %d\n", uid); + if (cplen <= 0) { + logkfd("seq_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + num++; } + rc = num; +out: rcu_read_unlock(); - return uoff; + return rc; +} + +int su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) +{ + int rc = -ENOENT; + rcu_read_lock(); + struct allow_uid *pos; + list_for_each_entry(pos, &allow_uid_list, list) + { + if (pos->profile.uid != uid) continue; + int cplen = seq_copy_to_user(uprofile, &pos->profile, sizeof(struct su_profile)); + logkd("copy_to_user allow uid profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); + if (cplen <= 0) { + logkfd("seq_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + rc = 0; + goto out; + } +out: + rcu_read_unlock(); + return rc; } -// todo: // no free, no lock int su_reset_path(const char *path) { char *new_su_path = kstrdup(path, GFP_ATOMIC); current_su_path = new_su_path; - dsb(ish); - logkfi("%s\n", current_su_path); + dsb(ishst); + logki(": %s\n", current_su_path); return 0; } int su_get_path(char *__user ubuf, int buf_len) { int len = strnlen(current_su_path, SU_PATH_MAX_LEN); - if (buf_len <= len) return -ENOMEM; - return seq_copy_to_user(ubuf, su_path, len); + if (buf_len < len) return -ENOMEM; + logkfi(": %s\n", current_su_path); + return seq_copy_to_user(ubuf, current_su_path, len + 1); } // todo: rcu_dereference_protected @@ -414,7 +437,11 @@ int su_compat_init() spin_lock_init(&list_lock); // default shell - su_add_allow_uid(2000, 0, 0, 0); + struct su_profile default_shell_profile = { + .uid = 2000, + .to_uid = 0, + }; + su_add_allow_uid(default_shell_profile.uid, &default_shell_profile, 1); // state unsigned long vfs_stat_addr = kallsyms_lookup_name("vfs_statx"); diff --git a/kernel/patch/android/supercall.c b/kernel/patch/android/supercall.c index e700740c..1d17aec5 100644 --- a/kernel/patch/android/supercall.c +++ b/kernel/patch/android/supercall.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -10,17 +11,15 @@ #include #include #include +#include #include -static long call_grant_uid(uid_t uid, uid_t to_uid, const char *__user usctx) +static long call_grant_uid(uid_t uid, struct su_profile *__user uprofile) { - const char *sctx = 0; - if (usctx) { - char buf[SUPERCALL_SCONTEXT_LEN]; - int slen = strncpy_from_user_nofault(buf, usctx, sizeof(buf)); - if (slen > 0) sctx = buf; - } - return su_add_allow_uid(uid, to_uid, sctx, 1); + struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); + if (IS_ERR(profile)) return PTR_ERR(profile); + + return su_add_allow_uid(uid, profile, 1); } static long call_revoke_uid(uid_t uid) @@ -33,9 +32,14 @@ static long call_su_allow_uid_nums() return su_allow_uid_nums(); } -static long call_su_list_allow_uid(char *__user buf, int buf_len) +static long call_su_list_allow_uid(uid_t *__user uids, int num) +{ + return su_allow_uids(uids, num); +} + +static long call_su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) { - return su_list_allow_uids(buf, buf_len); + return su_allow_uid_profile(uid, uprofile); } static long call_reset_su_path(const char *__user upath) @@ -55,13 +59,15 @@ long supercall_android(long cmd, long arg1, long arg2, long arg3) { switch (cmd) { case SUPERCALL_SU_GRANT_UID: - return call_grant_uid((uid_t)arg1, (uid_t)arg2, (const char *__user)arg3); + return call_grant_uid((uid_t)arg1, (struct su_profile * __user) arg2); case SUPERCALL_SU_REVOKE_UID: return call_revoke_uid((uid_t)arg1); - case SUPERCALL_SU_ALLOW_UID_NUM: + case SUPERCALL_SU_NUMS: return call_su_allow_uid_nums(); - case SUPERCALL_SU_LIST_ALLOW_UID: - return call_su_list_allow_uid((char *__user)arg1, (int)arg2); + case SUPERCALL_SU_LIST: + return call_su_list_allow_uid((uid_t *)arg1, (int)arg2); + case SUPERCALL_SU_PROFILE: + return call_su_allow_uid_profile((uid_t)arg1, (struct su_profile * __user) arg2); case SUPERCALL_SU_RESET_PATH: return call_reset_su_path((const char *)arg1); case SUPERCALL_SU_GET_PATH: diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index b8b60003..3c8c4db0 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index 3084361f..e73c5015 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -5,6 +5,7 @@ #include #include #include +#include int set_priv_selinx_allow(struct task_struct *task, int val); int commit_kernel_cred(); @@ -17,10 +18,11 @@ int supercall_install(); #ifdef ANDROID int kpuserd_init(); int su_compat_init(); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *sctx, int async); +int su_add_allow_uid(uid_t uid, struct su_profile *profile, int async); int su_remove_allow_uid(uid_t uid, int async); int su_allow_uid_nums(); -int su_list_allow_uids(char *__user buf, int buf_len); +int su_allow_uids(uid_t *__user uuids, int unum); +int su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile); int su_reset_path(const char *path); int su_get_path(char *__user ubuf, int buf_len); long supercall_android(long cmd, long arg1, long arg2, long arg3); diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 604cd300..344b6804 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -44,12 +44,20 @@ static inline long hash_key(const char *key) #define KPATCH_PATH "/data/adb/kpatch" #define KPATCH_SHADOW_PATH "/system/bin/truncate" +struct su_profile +{ + uid_t uid; + uid_t to_uid; + char scontext[SUPERCALL_SCONTEXT_LEN]; +}; + #define SUPERCALL_SU_GRANT_UID 0x1100 #define SUPERCALL_SU_REVOKE_UID 0x1101 -#define SUPERCALL_SU_ALLOW_UID_NUM 0x1102 -#define SUPERCALL_SU_LIST_ALLOW_UID 0x1103 -#define SUPERCALL_SU_GET_PATH 0x1104 -#define SUPERCALL_SU_RESET_PATH 0x1105 +#define SUPERCALL_SU_NUMS 0x1102 +#define SUPERCALL_SU_LIST 0x1103 +#define SUPERCALL_SU_PROFILE 0x1104 +#define SUPERCALL_SU_GET_PATH 0x1110 +#define SUPERCALL_SU_RESET_PATH 0x1111 #endif diff --git a/user/apjni.cpp b/user/apjni.cpp index 950901db..827adda7 100644 --- a/user/apjni.cpp +++ b/user/apjni.cpp @@ -79,14 +79,52 @@ extern "C" JNIEXPORT jlong JNICALL Java_me_bmax_apatch_Natives_nativeThreadSu(JN return rc; } -extern "C" JNIEXPORT jstring JNICALL Java_me_bmax_apatch_Natives_nativeListSu(JNIEnv *env, jclass clz, jstring superKey) +extern "C" JNIEXPORT jint JNICALL Java_me_bmax_apatch_Natives_nativeSuNums(JNIEnv *env, jclass clz, jstring superKey) { const char *skey = env->GetStringUTFChars(superKey, NULL); - char buf[1024] = { '\0' }; - long rc = sc_su_list_allow_uids(skey, buf, sizeof(buf)); + long rc = sc_su_uid_nums(skey); env->ReleaseStringUTFChars(superKey, skey); - jstring result = env->NewStringUTF(buf); - return result; + return rc; +} + +extern "C" JNIEXPORT jintArray JNICALL Java_me_bmax_apatch_Natives_nativeSuUids(JNIEnv *env, jclass clz, + jstring superKey) +{ + const char *skey = env->GetStringUTFChars(superKey, NULL); + int num = sc_su_uid_nums(skey); + int uids[num]; + long n = sc_su_allow_uids(skey, (uid_t *)uids, num); + if (n > 0) { + jintArray array = env->NewIntArray(num); + env->SetIntArrayRegion(array, 0, n, uids); + return array; + } + env->ReleaseStringUTFChars(superKey, skey); + return env->NewIntArray(0); +} + +extern "C" JNIEXPORT jobject JNICALL Java_me_bmax_apatch_Natives_nativeSuProfile(JNIEnv *env, jclass clz, + jstring superKey, jint uid) +{ + const char *skey = env->GetStringUTFChars(superKey, NULL); + struct su_profile profile = { 0 }; + long rc = sc_su_uid_profile(skey, (uid_t)uid, &profile); + if (rc) { + env->ReleaseStringUTFChars(superKey, skey); + return nullptr; + } + jclass cls = env->FindClass("me/bmax/apatch/Natives$Profile"); + jmethodID constructor = env->GetMethodID(cls, "", "()V"); + jfieldID uidField = env->GetFieldID(cls, "uid", "I"); + jfieldID toUidField = env->GetFieldID(cls, "toUid", "I"); + jfieldID scontextFild = env->GetFieldID(cls, "scontext", "Ljava/lang/String;"); + + jobject obj = env->NewObject(cls, constructor); + env->SetIntField(obj, uidField, profile.uid); + env->SetIntField(obj, toUidField, profile.to_uid); + env->SetObjectField(obj, scontextFild, env->NewStringUTF(profile.scontext)); + + return obj; } extern "C" JNIEXPORT jlong JNICALL Java_me_bmax_apatch_Natives_nativeLoadKernelPatchModule(JNIEnv *env, jclass clz, @@ -123,7 +161,11 @@ extern "C" JNIEXPORT jlong JNICALL Java_me_bmax_apatch_Natives_nativeGrantSu(JNI { const char *skey = env->GetStringUTFChars(superKey, NULL); const char *sctx = env->GetStringUTFChars(scontext, NULL); - long rc = sc_su_grant_uid(skey, (uid_t)uid, (uid_t)to_uid, sctx); + struct su_profile profile = { 0 }; + profile.uid = uid; + profile.to_uid = to_uid; + if (sctx) strncpy(profile.scontext, sctx, sizeof(profile.scontext) - 1); + long rc = sc_su_grant_uid(skey, uid, &profile); env->ReleaseStringUTFChars(superKey, skey); env->ReleaseStringUTFChars(scontext, sctx); return rc; @@ -146,3 +188,14 @@ extern "C" JNIEXPORT jstring JNICALL Java_me_bmax_apatch_Natives_nativeSuPath(JN env->ReleaseStringUTFChars(superKey, skey); return env->NewStringUTF(buf); } + +extern "C" JNIEXPORT jboolean JNICALL Java_me_bmax_apatch_Natives_nativeResetSuPath(JNIEnv *env, jclass clz, + jstring superKey, jstring jpath) +{ + const char *skey = env->GetStringUTFChars(superKey, NULL); + const char *path = env->GetStringUTFChars(jpath, NULL); + long rc = sc_su_reset_path(skey, path); + env->ReleaseStringUTFChars(superKey, skey); + env->ReleaseStringUTFChars(jpath, path); + return rc == 0; +} diff --git a/user/kpatch.c b/user/kpatch.c index 248ba0da..60257b4b 100644 --- a/user/kpatch.c +++ b/user/kpatch.c @@ -108,7 +108,14 @@ int __test(const char *key) int su_grant(const char *key, uid_t uid, uid_t to_uid, const char *scontext) { - int rc = sc_su_grant_uid(key, uid, to_uid, scontext); + struct su_profile profile = { 0 }; + profile.uid = uid; + profile.to_uid = to_uid; + if (scontext) { + strncpy(profile.scontext, scontext, sizeof(profile.scontext) - 1); + } + profile.scontext[sizeof(profile.scontext) - 1] = '\0'; + int rc = sc_su_grant_uid(key, uid, &profile); return rc; } @@ -127,15 +134,27 @@ int su_nums(const char *key) int su_list(const char *key) { - char buf[1024]; - int rc = sc_su_list_allow_uids(key, buf, sizeof(buf)); + int nums = sc_su_uid_nums(key); + uid_t uids[nums]; + int rc = sc_su_allow_uids(key, uids, nums); if (rc > 0) { - fprintf(stdout, "%s", buf); + for (int i = 0; i < rc; i++) { + fprintf(stdout, "%d\n", uids[i]); + } return 0; } return rc; } +int su_profile(const char *key, uid_t uid) +{ + struct su_profile profile = { 0 }; + long rc = sc_su_uid_profile(key, (uid_t)uid, &profile); + if (rc < 0) return rc; + fprintf(stdout, "uid: %d, to_uid: %d, scontext: %s\n", profile.uid, profile.to_uid, profile.scontext); + return 0; +} + int su_reset_path(const char *key, const char *path) { int rc = sc_su_reset_path(key, path); @@ -258,7 +277,12 @@ static void load_config_allow_uids(const char *key) uid_t uid = atol(suid); uid_t to_uid = atol(sto_uid); - sc_su_grant_uid(key, uid, to_uid, sctx); + struct su_profile profile = { 0 }; + profile.uid = uid; + profile.to_uid = to_uid; + if (sctx) strncpy(profile.scontext, sctx, sizeof(profile.scontext) - 1); + + sc_su_grant_uid(key, uid, &profile); if (uid != 2000) should_remove_default = true; } diff --git a/user/kpatch.h b/user/kpatch.h index 515266b1..64a42a10 100644 --- a/user/kpatch.h +++ b/user/kpatch.h @@ -29,6 +29,7 @@ extern "C" int su_revoke(const char *key, uid_t uid); int su_nums(const char *key); int su_list(const char *key); + int su_profile(const char *key, uid_t uid); int su_reset_path(const char *key, const char *path); int su_get_path(const char *key); int android_user_init(const char *key); diff --git a/user/main.c b/user/main.c index c5f65a2d..467281aa 100644 --- a/user/main.c +++ b/user/main.c @@ -71,6 +71,8 @@ static void print_usage(char **argv) " Get the number of uids with the aforementioned permissions. \n" " --su_list \n" " List aforementioned uids. \n" + " --su_profile uid \n" + " Get the profile of the uid configuration. \n" " --su_reset path \n" " Reset '/system/bin/kp' to 'path'. The length of 'path' must be between 15-64, \n" " including the terminating null byte ('\\0'). \n" @@ -130,8 +132,9 @@ int main(int argc, char **argv) #ifdef ANDROID { "su_grant", no_argument, &cmd, SUPERCALL_SU_GRANT_UID }, { "su_revoke", no_argument, &cmd, SUPERCALL_SU_REVOKE_UID }, - { "su_num", no_argument, &cmd, SUPERCALL_SU_ALLOW_UID_NUM }, - { "su_list", no_argument, &cmd, SUPERCALL_SU_LIST_ALLOW_UID }, + { "su_num", no_argument, &cmd, SUPERCALL_SU_NUMS }, + { "su_list", no_argument, &cmd, SUPERCALL_SU_LIST }, + { "su_profile", no_argument, &cmd, SUPERCALL_SU_PROFILE }, { "su_reset", no_argument, &cmd, SUPERCALL_SU_RESET_PATH }, { "su_get", no_argument, &cmd, SUPERCALL_SU_GET_PATH }, { "android_user_init", no_argument, &cmd, ANDROID_USER_INIT_CMD }, @@ -210,17 +213,32 @@ int main(int argc, char **argv) return __test(key); #ifdef ANDROID case SUPERCALL_SU_GRANT_UID: - if (argc >= 4) uid = (uid_t)atoi(argv[3]); + if (argc < 4) { + fprintf(stderr, "Empyt uid!\n"); + return -EINVAL; + } + uid = (uid_t)atoi(argv[3]); if (argc >= 5) to_uid = (uid_t)atoi(argv[4]); if (argc >= 6) sctx = argv[5]; return su_grant(key, uid, to_uid, sctx); case SUPERCALL_SU_REVOKE_UID: - if (argc >= 4) uid = (uid_t)atoi(argv[3]); + if (argc < 4) { + fprintf(stderr, "Empyt uid!\n"); + return -EINVAL; + } + uid = (uid_t)atoi(argv[3]); return su_revoke(key, uid); - case SUPERCALL_SU_ALLOW_UID_NUM: + case SUPERCALL_SU_NUMS: return su_nums(key); - case SUPERCALL_SU_LIST_ALLOW_UID: + case SUPERCALL_SU_LIST: return su_list(key); + case SUPERCALL_SU_PROFILE: + if (argc < 4) { + fprintf(stderr, "Empyt uid!\n"); + return -EINVAL; + } + uid = (uid_t)atoi(argv[3]); + return su_profile(key, uid); case SUPERCALL_SU_RESET_PATH: if (argc < 4) { fprintf(stderr, "Empyt module path!\n"); diff --git a/user/supercall.h b/user/supercall.h index ae824050..6083df5b 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -98,10 +98,10 @@ static inline long __sc_test(const char *key) } #ifdef ANDROID -static inline long sc_su_grant_uid(const char *key, uid_t uid, uid_t to_uid, const char *sctx) +static inline long sc_su_grant_uid(const char *key, uid_t uid, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_GRANT_UID, uid, to_uid, sctx); + long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_GRANT_UID, uid, profile); return ret; } @@ -115,15 +115,22 @@ static inline long sc_su_revoke_uid(const char *key, uid_t uid) static inline long sc_su_uid_nums(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_ALLOW_UID_NUM); + long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_NUMS); return ret; } -static inline long sc_su_list_allow_uids(const char *key, char *buf, int buf_size) +static inline long sc_su_allow_uids(const char *key, uid_t *buf, int num) { if (!key || !key[0]) return -EINVAL; - if (!buf || buf_size <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_LIST_ALLOW_UID, buf, buf_size); + if (!buf || num <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_LIST, buf, num); + return ret; +} + +static inline long sc_su_uid_profile(const char *key, uid_t uid, struct su_profile *out_profile) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, hash_key(key), SUPERCALL_SU_PROFILE, uid, out_profile); return ret; } diff --git a/version b/version index 866a43a8..6f21e614 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ #define MAJOR 0 #define MINOR 6 -#define PATCH 0 \ No newline at end of file +#define PATCH 1 \ No newline at end of file