Skip to content

Commit

Permalink
add kstorage list interface, android exclude list interface
Browse files Browse the repository at this point in the history
  • Loading branch information
bmax committed Oct 5, 2024
1 parent 67ab867 commit 124f704
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 36 deletions.
80 changes: 59 additions & 21 deletions kernel/patch/common/kstorage.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@
#define KSTRORAGE_MAX_GROUP_NUM 4

// static atomic64_t used_max_group = ATOMIC_INIT(0);
static int used_max_group = 0;
static int used_max_group = -1;
static struct list_head kstorage_groups[KSTRORAGE_MAX_GROUP_NUM];
static spinlock_t kstorage_glocks[KSTRORAGE_MAX_GROUP_NUM];
static int group_sizes[KSTRORAGE_MAX_GROUP_NUM] = { 0 };
static spinlock_t used_max_group_lock;

// static void reclaim_callback(struct rcu_head *rcu)
// {
// struct kstorage *ks = container_of(rcu, struct kstorage, rcu);
// kvfree(ks);
// }
static void reclaim_callback(struct rcu_head *rcu)
{
struct kstorage *ks = container_of(rcu, struct kstorage, rcu);
kvfree(ks);
}

int try_alloc_kstroage_group()
{
spin_lock(&used_max_group_lock);
used_max_group++;
if (used_max_group >= KSTRORAGE_MAX_GROUP_NUM) return -1;
if (used_max_group < 0 || used_max_group >= KSTRORAGE_MAX_GROUP_NUM) return -1;
spin_unlock(&used_max_group_lock);
return used_max_group;
}
Expand Down Expand Up @@ -96,12 +96,13 @@ int write_kstorage(int gid, long did, void *data, int offset, int len, bool data
rcu_read_unlock();

if (old) {
// if (async) {
// call_rcu(&old->rcu, reclaim_callback);
// } else {
synchronize_rcu();
kvfree(old);
// }
bool async = true;
if (async) {
call_rcu(&old->rcu, reclaim_callback);
} else {
synchronize_rcu();
kvfree(old);
}
}
return 0;
}
Expand All @@ -127,7 +128,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 0;
if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return -ENOENT;

int rc = 0;

Expand Down Expand Up @@ -155,7 +156,10 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_

const struct kstorage *pos = get_kstorage(gid, did);

if (IS_ERR(pos)) return PTR_ERR(pos);
if (IS_ERR(pos)) {
rcu_read_unlock();
return PTR_ERR(pos);
}

int min_len = pos->dlen - offset > len ? len : pos->dlen - offset;

Expand All @@ -176,6 +180,39 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_
}
KP_EXPORT_SYMBOL(read_kstorage);

int list_kstorage_ids(int gid, long *ids, int idslen, bool data_is_user)
{
if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return -ENOENT;

int cnt = 0;

struct list_head *head = &kstorage_groups[gid];
struct kstorage *pos = 0;

rcu_read_lock();

list_for_each_entry(pos, head, list)
{
if (cnt >= idslen) break;

if (data_is_user) {
int cplen = compat_copy_to_user(ids + cnt, &pos->did, sizeof(pos->did));
if (cplen <= 0) {
logkfd("compat_copy_to_user error: %d", cplen);
cnt = cplen;
}
} else {
memcpy(ids + cnt, &pos->did, sizeof(pos->did));
}
cnt++;
}

rcu_read_unlock();

return cnt;
}
KP_EXPORT_SYMBOL(list_kstorage_ids);

int remove_kstorage(int gid, long did)
{
int rc = -ENOENT;
Expand All @@ -197,12 +234,13 @@ int remove_kstorage(int gid, long did)

logkfi("%d %ld\n", gid, did);

// if (async) {
// call_rcu(&pos->rcu, reclaim_callback);
// } else {
synchronize_rcu();
kvfree(pos);
// }
bool async = true;
if (async) {
call_rcu(&pos->rcu, reclaim_callback);
} else {
synchronize_rcu();
kvfree(pos);
}
return 0;
}
}
Expand Down
27 changes: 20 additions & 7 deletions kernel/patch/common/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,32 @@ int get_ap_mod_exclude(uid_t uid)
}
KP_EXPORT_SYMBOL(get_ap_mod_exclude);

int list_ap_mod_exclude(uid_t *uids, int len)
{
long ids[len];
int cnt = list_kstorage_ids(exclude_kstorage_gid, ids, len, false);
for (int i = 0; i < len; i++) {
uids[i] = (uid_t)ids[i];
}
return cnt;
}
KP_EXPORT_SYMBOL(list_ap_mod_exclude);

int su_compat_init()
{
current_su_path = default_su_path;

su_kstorage_gid = try_alloc_kstroage_group();
if (su_kstorage_gid != KSTORAGE_SU_LIST_GROUP) return -ENOMEM;

exclude_kstorage_gid = try_alloc_kstroage_group();
if (exclude_kstorage_gid != KSTORAGE_EXCLUDE_LIST_GROUP) return -ENOMEM;

#ifdef ANDROID
// default shell
if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK);
if (!all_allow_sctx[0]) {
strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK);
}
su_add_allow_uid(2000, 0, all_allow_sctx);
su_add_allow_uid(0, 0, all_allow_sctx);
#endif
Expand All @@ -356,12 +375,6 @@ int su_compat_init()

// if (!enable) return;

su_kstorage_gid = try_alloc_kstroage_group();
if (su_kstorage_gid < 0) return -ENOMEM;

exclude_kstorage_gid = try_alloc_kstroage_group();
if (exclude_kstorage_gid < 0) return -ENOMEM;

rc = hook_syscalln(__NR_execve, 3, before_execve, 0, (void *)0);
log_boot("hook __NR_execve rc: %d\n", rc);

Expand Down
7 changes: 7 additions & 0 deletions kernel/patch/common/supercall.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ static long call_kstorage_write(int gid, long did, void *data, int offset, int d
return write_kstorage(gid, did, data, offset, dlen, true);
}

static long call_list_kstorage_ids(int gid, long *ids, int ids_len)
{
return list_kstorage_ids(gid, ids, ids_len, false);
}

static long call_kstorage_remove(int gid, long did)
{
return remove_kstorage(gid, did);
Expand Down Expand Up @@ -290,6 +295,8 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3
case SUPERCALL_KSTORAGE_WRITE:
return call_kstorage_write((int)arg1, (long)arg2, (void *)arg3, (int)((long)arg4 >> 32),
(long)arg4 << 32 >> 32);
case SUPERCALL_KSTORAGE_LIST_IDS:
return call_list_kstorage_ids((int)arg1, (long *)arg2, (int)arg3);
case SUPERCALL_KSTORAGE_REMOVE:
return call_kstorage_remove((int)arg1, (long)arg2);

Expand Down
24 changes: 22 additions & 2 deletions kernel/patch/common/supercmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ static const char supercmd_help[] =
" profile <UID> Get the profile of the uid configuration.\n"
" path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n"
" sctx [SCONTEXT] Get or Reset current all allowed security context.\n"
#ifdef ANDROID
" exclude_list List all exclude UIDs.\n"
" exclude <UID> [1|0] Get or Reset exclude policy for UID.\n"
#endif
" event <EVENT> Report EVENT.\n"
"\n"
"The command below requires superkey authentication.\n"
Expand Down Expand Up @@ -180,7 +183,9 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char
} else {
cmd_res->msg = all_allow_sctx;
}
} else if (!strcmp(sub_cmd, "exclude")) {
}
#ifdef ANDROID
else if (!strcmp(sub_cmd, "exclude")) {
unsigned long long uid;
if (!carr[2] || kstrtoull(carr[2], 10, &uid)) {
cmd_res->err_msg = "invalid uid";
Expand All @@ -200,7 +205,22 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char
}
}
}
} else {
} else if (!strcmp(sub_cmd, "exclude_list")) {
uid_t uids[128];
int offset = 0;
int cnt = list_ap_mod_exclude(uids, sizeof(uids) / sizeof(uids[0]));
if (cnt < 0) {
cmd_res->rc = cnt;
} else {
for (int i = 0; i < cnt; i++) {
offset += sprintf(buffer + offset, "%d\n", uids[i]);
};
if (offset > 0) buffer[offset - 1] = '\0';
cmd_res->msg = buffer;
}
}
#endif
else {
cmd_res->err_msg = "invalid subcommand";
}
}
Expand Down
4 changes: 3 additions & 1 deletion kernel/patch/include/kstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ int kstorage_group_size(int gid);

int write_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user);

// must within rcu read lock
/// must within rcu read lock
const struct kstorage *get_kstorage(int gid, long did);

typedef int (*on_kstorage_cb)(struct kstorage *kstorage, void *udata);
int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata);

int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user);

int list_kstorage_ids(int gid, long *ids, int idslen, bool data_is_user);

int remove_kstorage(int gid, long did);

#endif
1 change: 1 addition & 0 deletions kernel/patch/include/sucompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ const char *su_get_path();

int get_ap_mod_exclude(uid_t uid);
int set_ap_mod_exclude(uid_t uid, int exclude);
int list_ap_mod_exclude(uid_t *uids, int len);

#endif
5 changes: 3 additions & 2 deletions kernel/patch/include/uapi/scdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ struct kernel_storage
#define SUPERCALL_KSTORAGE_ALLOC_GROUP 0x1040
#define SUPERCALL_KSTORAGE_WRITE 0x1041
#define SUPERCALL_KSTORAGE_READ 0x1042
#define SUPERCALL_KSTORAGE_REMOVE 0x1043
#define SUPERCALL_KSTORAGE_REMOVE_GROUP 0x1044
#define SUPERCALL_KSTORAGE_LIST_IDS 0x1043
#define SUPERCALL_KSTORAGE_REMOVE 0x1044
#define SUPERCALL_KSTORAGE_REMOVE_GROUP 0x1045

#define KSTORAGE_SU_LIST_GROUP 0
#define KSTORAGE_EXCLUDE_LIST_GROUP 1
Expand Down
24 changes: 21 additions & 3 deletions user/supercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *pro
static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int offset, int dlen)
{
if (!key || !key[0]) return -EINVAL;
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, ((offset << 32) | dlen));
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, (((long)offset << 32) | dlen));
return ret;
}

Expand All @@ -151,10 +151,28 @@ static inline long sc_kstorage_write(const char *key, int gid, long did, void *d
static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int offset, int dlen)
{
if (!key || !key[0]) return -EINVAL;
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, ((offset << 32) | dlen));
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, (((long)offset << 32) | dlen));
return ret;
}


/**
* @brief
*
* @param key
* @param gid
* @param ids
* @param ids_len
* @return long numbers of listed ids
*/
static inline long sc_kstorage_list_ids(const char *key, int gid, long *ids, int ids_len)
{
if (!key || !key[0]) return -EINVAL;
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_LIST_IDS), gid, ids, ids_len);
return ret;
}


/**
* @brief
*
Expand All @@ -166,7 +184,7 @@ static inline long sc_kstorage_read(const char *key, int gid, long did, void *ou
static inline long sc_kstorage_remove(const char *key, int gid, long did)
{
if (!key || !key[0]) return -EINVAL;
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_REMOVE), gid, did);
long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_REMOVE), gid);
return ret;
}

Expand Down

0 comments on commit 124f704

Please sign in to comment.