Skip to content

Commit 5cd5b54

Browse files
rsuntkaviraxp
andauthored
kernel: add wrapper for creds, refine disable_seccomp, revert some changes (#131)
1. Wrapper for creds: * Some older kernel does not have {.val}, so, for nicer compatibility support and clean code, make some wrapper for credential use. * After this change, do not use current_uid().val, instead, use ksu_current_uid(). For more info, check kernel/include/ksu_creds.h. 2. Refine disable_seccomp (need to add k6.11+ support) tiann#2708 tiann#2706 3. Revert "Handle unmount for isolated process correctly" Reason: tiann#2696 (comment) Co-authored-by: Wang Han <[email protected]>
1 parent 6430723 commit 5cd5b54

File tree

5 files changed

+115
-62
lines changed

5 files changed

+115
-62
lines changed

kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ kernelsu-objs += kernel_compat.o
1111
kernelsu-objs += selinux/selinux.o
1212
kernelsu-objs += selinux/sepolicy.o
1313
kernelsu-objs += selinux/rules.o
14+
1415
ccflags-y += -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
1516
ccflags-y += -I$(objtree)/security/selinux -include $(srctree)/include/uapi/asm-generic/errno.h
17+
ccflags-y += -include $(srctree)/$(src)/include/ksu_creds.h
1618

1719
obj-$(CONFIG_KSU) += kernelsu.o
1820

kernel/core_hook.c

Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ static inline bool is_allow_su()
6262
// we are manager, allow!
6363
return true;
6464
}
65-
return ksu_is_allow_uid(current_uid().val);
65+
return ksu_is_allow_uid(ksu_current_uid());
6666
}
6767

68-
static inline bool is_unsupported_app_uid(uid_t uid)
68+
static inline bool is_unsupported_uid(uid_t uid)
6969
{
7070
#define LAST_APPLICATION_UID 19999
7171
uid_t appid = uid % 100000;
@@ -120,7 +120,12 @@ static void setup_groups(struct root_profile *profile, struct cred *cred)
120120

121121
static void disable_seccomp(void)
122122
{
123-
assert_spin_locked(&current->sighand->siglock);
123+
struct task_struct *tsk = get_current();
124+
125+
pr_info("%s++\n", __func__);
126+
spin_lock_irq(&tsk->sighand->siglock);
127+
assert_spin_locked(&tsk->sighand->siglock);
128+
124129
// disable seccomp
125130
#if defined(CONFIG_GENERIC_ENTRY) && \
126131
LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)
@@ -130,40 +135,56 @@ static void disable_seccomp(void)
130135
#endif
131136

132137
#ifdef CONFIG_SECCOMP
133-
current->seccomp.mode = 0;
134-
current->seccomp.filter = NULL;
138+
tsk->seccomp.mode = 0;
139+
if (tsk->seccomp.filter == NULL) {
140+
pr_warn("tsk->seccomp.filter is NULL already!\n");
141+
goto out;
142+
}
143+
144+
// 5.9+ have filter_count and use seccomp_filter_release
145+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
146+
seccomp_filter_release(tsk);
147+
atomic_set(&tsk->seccomp.filter_count, 0);
135148
#else
149+
put_seccomp_filter(tsk);
150+
tsk->seccomp.filter = NULL;
151+
#endif
136152
#endif
153+
154+
out:
155+
spin_unlock_irq(&tsk->sighand->siglock);
156+
pr_info("%s--\n", __func__);
137157
}
138158

139159
void escape_to_root(void)
140160
{
141-
struct cred *cred;
142-
143-
cred = prepare_creds();
144-
if (!cred) {
161+
struct cred *newcreds = prepare_creds();
162+
if (newcreds == NULL) {
145163
pr_err("%s: failed to allocate new cred.\n", __func__);
146164
return;
147165
}
148166

149-
if (cred->euid.val == 0) {
167+
if (ksu_cred_euid(newcreds) == 0) {
150168
pr_warn("Already root, don't escape!\n");
151-
abort_creds(cred);
169+
abort_creds(newcreds);
152170
return;
153171
}
154172

155-
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
173+
struct root_profile *profile =
174+
ksu_get_root_profile(ksu_cred_uid(newcreds));
175+
176+
ksu_cred_uid(newcreds) = profile->uid;
177+
ksu_cred_suid(newcreds) = profile->uid;
178+
ksu_cred_euid(newcreds) = profile->uid;
179+
ksu_cred_fsuid(newcreds) = profile->uid;
156180

157-
cred->uid.val = profile->uid;
158-
cred->suid.val = profile->uid;
159-
cred->euid.val = profile->uid;
160-
cred->fsuid.val = profile->uid;
181+
ksu_cred_gid(newcreds) = profile->gid;
182+
ksu_cred_fsgid(newcreds) = profile->gid;
183+
ksu_cred_sgid(newcreds) = profile->gid;
184+
ksu_cred_egid(newcreds) = profile->gid;
161185

162-
cred->gid.val = profile->gid;
163-
cred->fsgid.val = profile->gid;
164-
cred->sgid.val = profile->gid;
165-
cred->egid.val = profile->gid;
166-
cred->securebits = 0;
186+
// no wrapper, ignore it.
187+
newcreds->securebits = 0;
167188

168189
BUILD_BUG_ON(sizeof(profile->capabilities.effective) !=
169190
sizeof(kernel_cap_t));
@@ -173,23 +194,17 @@ void escape_to_root(void)
173194
// we add it here but don't add it to cap_inhertiable, it would be dropped automaticly after exec!
174195
u64 cap_for_ksud =
175196
profile->capabilities.effective | CAP_DAC_READ_SEARCH;
176-
memcpy(&cred->cap_effective, &cap_for_ksud,
177-
sizeof(cred->cap_effective));
178-
memcpy(&cred->cap_permitted, &profile->capabilities.effective,
179-
sizeof(cred->cap_permitted));
180-
memcpy(&cred->cap_bset, &profile->capabilities.effective,
181-
sizeof(cred->cap_bset));
182-
183-
setup_groups(profile, cred);
184-
185-
commit_creds(cred);
186-
187-
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
188-
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.
189-
spin_lock_irq(&current->sighand->siglock);
197+
memcpy(&newcreds->cap_effective, &cap_for_ksud,
198+
sizeof(newcreds->cap_effective));
199+
memcpy(&newcreds->cap_permitted, &profile->capabilities.effective,
200+
sizeof(newcreds->cap_permitted));
201+
memcpy(&newcreds->cap_bset, &profile->capabilities.effective,
202+
sizeof(newcreds->cap_bset));
203+
204+
setup_groups(profile, newcreds);
205+
commit_creds(newcreds);
206+
190207
disable_seccomp();
191-
spin_unlock_irq(&current->sighand->siglock);
192-
193208
setup_selinux(profile->selinux_domain);
194209
}
195210

@@ -200,7 +215,7 @@ int ksu_handle_rename(struct dentry *old_dentry, struct dentry *new_dentry)
200215
return 0;
201216
}
202217

203-
if (current_uid().val != 1000) {
218+
if (ksu_current_uid() != 1000) {
204219
// skip non system uid
205220
return 0;
206221
}
@@ -268,14 +283,14 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
268283
}
269284

270285
// TODO: find it in throne tracker!
271-
uid_t current_uid_val = current_uid().val;
286+
uid_t current_uid_val = ksu_current_uid();
272287
uid_t manager_uid = ksu_get_manager_uid();
273288
if (current_uid_val != manager_uid &&
274289
current_uid_val % 100000 == manager_uid) {
275290
ksu_set_manager_uid(current_uid_val);
276291
}
277292

278-
bool from_root = 0 == current_uid().val;
293+
bool from_root = 0 == ksu_current_uid();
279294
bool from_manager = is_manager();
280295

281296
if (!from_root && !from_manager) {
@@ -299,7 +314,7 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
299314

300315
if (arg2 == CMD_GRANT_ROOT) {
301316
if (is_allow_su()) {
302-
pr_info("allow root for: %d\n", current_uid().val);
317+
pr_info("allow root for: %d\n", ksu_current_uid());
303318
escape_to_root();
304319
if (copy_to_user(result, &reply_ok, sizeof(reply_ok))) {
305320
pr_err("grant_root: prctl reply error\n");
@@ -511,13 +526,14 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
511526
return 0;
512527
}
513528

514-
static bool is_non_appuid(kuid_t uid)
529+
static bool is_appuid(kuid_t uid)
515530
{
516531
#define PER_USER_RANGE 100000
517532
#define FIRST_APPLICATION_UID 10000
533+
#define LAST_APPLICATION_UID 19999
518534

519535
uid_t appid = uid.val % PER_USER_RANGE;
520-
return appid < FIRST_APPLICATION_UID;
536+
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
521537
}
522538

523539
static bool should_umount(struct path *path)
@@ -528,7 +544,7 @@ static bool should_umount(struct path *path)
528544

529545
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
530546
pr_info("ignore global mnt namespace process: %d\n",
531-
current_uid().val);
547+
ksu_current_uid());
532548
return false;
533549
}
534550

@@ -614,33 +630,29 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
614630
return 0;
615631
}
616632

617-
if (is_non_appuid(new_uid)) {
618-
#ifdef CONFIG_KSU_DEBUG
619-
pr_info("handle setuid ignore non application uid: %d\n", new_uid.val);
620-
#endif
633+
if (!is_appuid(new_uid) || is_unsupported_uid(new_uid.val)) {
634+
// pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val);
621635
return 0;
622636
}
623637

624-
// isolated process may be directly forked from zygote, always unmount
625-
if (is_unsupported_app_uid(new_uid.val)) {
626-
#ifdef CONFIG_KSU_DEBUG
627-
pr_info("handle umount for unsupported application uid: %d\n", new_uid.val);
628-
#endif
629-
goto do_umount;
638+
if (ksu_is_allow_uid(new_uid.val)) {
639+
// pr_info("handle setuid ignore allowed application: %d\n", new_uid.val);
640+
return 0;
630641
}
631642

632-
if (ksu_is_allow_uid(new_uid.val)) {
643+
if (!ksu_uid_should_umount(new_uid.val)) {
644+
return 0;
645+
} else {
633646
#ifdef CONFIG_KSU_DEBUG
634-
pr_info("handle setuid ignore allowed application: %d\n", new_uid.val);
647+
pr_info("uid: %d should not umount!\n", current_uid().val);
635648
#endif
636-
return 0;
637649
}
638650

639-
do_umount:
640651
// check old process's selinux context, if it is not zygote, ignore it!
641652
// because some su apps may setuid to untrusted_app but they are in global mount namespace
642653
// when we umount for such process, that is a disaster!
643-
if (!is_zygote(old->security)) {
654+
bool is_zygote_child = is_zygote(old->security);
655+
if (!is_zygote_child) {
644656
pr_info("handle umount ignore non zygote child: %d\n",
645657
current->pid);
646658
return 0;

kernel/include/ksu_creds.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* KernelSU creds wrapper
3+
*
4+
* Provide a wrapper for a few credentials use (e.g current_uid().val),
5+
* so it would be easier to maintain
6+
* some older linux versions.
7+
*/
8+
9+
#ifndef __KSU_H_CREDS
10+
#define __KSU_H_CREDS
11+
12+
#include <linux/cred.h>
13+
#include <linux/version.h>
14+
15+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) && \
16+
defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS)) || \
17+
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
18+
#define ksu_cred_uid(x) ((x)->uid.val)
19+
#define ksu_cred_suid(x) ((x)->suid.val)
20+
#define ksu_cred_euid(x) ((x)->euid.val)
21+
#define ksu_cred_fsuid(x) ((x)->fsuid.val)
22+
#define ksu_cred_gid(x) ((x)->gid.val)
23+
#define ksu_cred_fsgid(x) ((x)->fsgid.val)
24+
#define ksu_cred_sgid(x) ((x)->sgid.val)
25+
#define ksu_cred_egid(x) ((x)->egid.val)
26+
#define ksu_current_uid() (current_uid().val)
27+
#else
28+
#define ksu_cred_uid(x) ((x)->uid)
29+
#define ksu_cred_suid(x) ((x)->suid)
30+
#define ksu_cred_euid(x) ((x)->euid)
31+
#define ksu_cred_fsuid(x) ((x)->fsuid)
32+
#define ksu_cred_gid(x) ((x)->gid)
33+
#define ksu_cred_fsgid(x) ((x)->fsgid)
34+
#define ksu_cred_sgid(x) ((x)->sgid)
35+
#define ksu_cred_egid(x) ((x)->egid)
36+
#define ksu_current_uid() (current_uid())
37+
#endif
38+
39+
#endif

kernel/manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ static inline bool ksu_is_manager_uid_valid()
1515

1616
static inline bool is_manager()
1717
{
18-
return unlikely(ksu_manager_uid == current_uid().val);
18+
return unlikely(ksu_manager_uid == ksu_current_uid());
1919
}
2020

2121
static inline uid_t ksu_get_manager_uid()

kernel/sucompat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static inline bool __is_su_allowed(const void *ptr_to_check)
5858
if (!ksu_sucompat_hook_state)
5959
return false;
6060
#endif
61-
if (likely(!ksu_is_allow_uid(current_uid().val)))
61+
if (likely(!ksu_is_allow_uid(ksu_current_uid())))
6262
return false;
6363

6464
if (unlikely(!ptr_to_check))
@@ -149,7 +149,7 @@ static int ksu_inline_handle_devpts(struct inode *inode)
149149
return 0;
150150
}
151151

152-
uid_t uid = current_uid().val;
152+
uid_t uid = ksu_current_uid();
153153
if (uid % 100000 < 10000) {
154154
// not untrusted_app, ignore it
155155
return 0;

0 commit comments

Comments
 (0)