Skip to content

Commit

Permalink
refactor: su command
Browse files Browse the repository at this point in the history
  • Loading branch information
bmax committed Sep 30, 2024
1 parent 325faac commit f4a1aab
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 62 deletions.
7 changes: 4 additions & 3 deletions kernel/patch/common/kstorage.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <kstorage.h>

#include <linux/kernel.h>
#include <linux/rculist.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <ktypes.h>
#include <compiler.h>
#include <stdbool.h>
#include <symbol.h>
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down
83 changes: 42 additions & 41 deletions kernel/patch/common/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -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++;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions kernel/patch/common/supercall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
9 changes: 4 additions & 5 deletions kernel/patch/common/supercmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ static const char supercmd_help[] =
""
"KernelPatch supercmd:\n"
"Usage: truncate <superkey|su> [-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 <UID> Change user id to UID.\n"
" -Z <SCONTEXT> Change security context to SCONTEXT.\n"
Expand Down Expand Up @@ -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")) {
Expand All @@ -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();
Expand Down Expand Up @@ -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;
}
Expand Down
8 changes: 0 additions & 8 deletions kernel/patch/include/accctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
4 changes: 2 additions & 2 deletions kernel/patch/include/kstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#ifndef _KP_KSTORAGE_H_
#define _KP_KSTORAGE_H_

#include <uapi/scdefs.h>
#include <ktypes.h>
#include <uapi/scdefs.h>
#include <stdbool.h>

struct kstorage
Expand All @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion kernel/patch/include/sucompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
7 changes: 7 additions & 0 deletions kernel/patch/include/uapi/scdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit f4a1aab

Please sign in to comment.