Skip to content

Commit a136049

Browse files
committed
kernel: core_hook: refactor/hack escape_to_root a little
we remove that get_cred_rcu requirement by adding a hacky fallback to get_cred with smp_mb. YES, IT IS HACKY but it works well. Unlock earlier to reduce lock holding time. - !! EDIT this once tiann#2628 is merged Also properly reset refcount as said by cred.h by calling put_cred where the original unlock was. Signed-off-by: backslashxx <[email protected]>
1 parent a5f5adf commit a136049

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

kernel/core_hook.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,24 @@ void escape_to_root(void)
122122
{
123123
struct cred *cred;
124124

125+
if (current_euid().val == 0) {
126+
pr_warn("Already root, don't escape!\n");
127+
return;
128+
}
129+
125130
rcu_read_lock();
126131

127132
do {
128133
cred = (struct cred *)__task_cred((current));
129-
BUG_ON(!cred);
130-
} while (!get_cred_rcu(cred));
134+
if (!cred) {
135+
pr_info("%s: cred is null! bailing out! \n", __func__);
136+
rcu_read_unlock();
137+
return;
138+
}
139+
} while (!ksu_get_cred_rcu(cred));
140+
141+
rcu_read_unlock();
131142

132-
if (cred->euid.val == 0) {
133-
pr_warn("Already root, don't escape!\n");
134-
rcu_read_unlock();
135-
return;
136-
}
137143
struct root_profile *profile = ksu_get_root_profile(cred->uid.val);
138144

139145
cred->uid.val = profile->uid;
@@ -164,7 +170,7 @@ void escape_to_root(void)
164170

165171
setup_groups(profile, cred);
166172

167-
rcu_read_unlock();
173+
put_cred(cred); // release here - include/linux/cred.h
168174

169175
// Refer to kernel/seccomp.c: seccomp_set_mode_strict
170176
// When disabling Seccomp, ensure that current->sighand->siglock is held during the operation.

kernel/kernel_compat.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <linux/version.h>
22
#include <linux/fs.h>
33
#include <linux/nsproxy.h>
4+
#include <linux/cred.h>
45
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
56
#include <linux/sched/task.h>
67
#else
@@ -173,3 +174,15 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
173174
return ret;
174175
}
175176
#endif
177+
178+
const struct cred *ksu_get_cred_rcu(const struct cred *cred)
179+
{
180+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) || defined(KSU_HAS_GET_CRED_RCU)
181+
return get_cred_rcu(cred);
182+
#else
183+
smp_mb(); // sledgehammer!
184+
const struct cred *ret = get_cred(cred);
185+
smp_mb(); // again!
186+
return ret;
187+
#endif
188+
}

kernel/kernel_compat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count,
2121
loff_t *pos);
2222
extern ssize_t ksu_kernel_write_compat(struct file *p, const void *buf,
2323
size_t count, loff_t *pos);
24+
extern const struct cred *ksu_get_cred_rcu(const struct cred *cred);
2425

2526
#endif

0 commit comments

Comments
 (0)