Signed-off-by: Ookiineko <chiisaineko@protonmail.com> Co-authored-by: f19 <58457605+F-19-F@users.noreply.github.com> Co-authored-by: Scirese <nuclearlight91@gmail.com>
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
#ifndef __KSU_H_KERNEL_COMPAT
|
||||
#define __KSU_H_KERNEL_COMPAT
|
||||
|
||||
#include "linux/fs.h"
|
||||
|
||||
extern ssize_t kernel_read_compat(struct file *p, void* buf, size_t count, loff_t *pos);
|
||||
extern ssize_t kernel_write_compat(struct file *p, const void *buf, size_t count, loff_t *pos);
|
||||
#endif
|
||||
|
||||
@@ -212,11 +212,9 @@ static int read_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
static struct kprobe execve_kp = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||
.symbol_name = "do_execveat_common",
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
.symbol_name = "__do_execve_file",
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
|
||||
.symbol_name = "do_execveat_common",
|
||||
#endif
|
||||
.pre_handler = execve_handler_pre,
|
||||
|
||||
@@ -53,35 +53,50 @@ if (!is_domain_permissive) {
|
||||
|
||||
void setenforce(bool enforce)
|
||||
{
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
|
||||
selinux_state.enforcing = enforce;
|
||||
#endif
|
||||
#else
|
||||
selinux_enabled = enforce;
|
||||
selinux_enabled = enforce;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool getenforce()
|
||||
{
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
|
||||
if (selinux_state.disabled) {
|
||||
#else
|
||||
if (selinux_disabled) {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
|
||||
return selinux_state.enforcing;
|
||||
#else
|
||||
return false;
|
||||
return selinux_enabled;
|
||||
#endif
|
||||
#else
|
||||
return selinux_enabled;
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
|
||||
/*
|
||||
* get the subjective security ID of the current task
|
||||
*/
|
||||
static inline u32 current_sid(void)
|
||||
{
|
||||
const struct task_security_struct *tsec = current_security();
|
||||
|
||||
return tsec->sid;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_ksu_domain()
|
||||
{
|
||||
return ksu_sid && current_sid() == ksu_sid;
|
||||
|
||||
@@ -134,17 +134,16 @@ static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
|
||||
static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
// static int vfs_statx(int dfd, const char __user *filename, int flags,struct kstat *stat, u32 request_mask)
|
||||
int *dfd = (int *)&PT_REGS_PARM1(regs);
|
||||
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
// static int vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask)
|
||||
int *flags = (int *)&PT_REGS_PARM3(regs);
|
||||
#else
|
||||
// int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,int flag)
|
||||
int *flags = (int *)&PT_REGS_PARM4(regs);
|
||||
#endif
|
||||
|
||||
|
||||
return ksu_handle_stat(dfd, filename_user, flags);
|
||||
}
|
||||
|
||||
@@ -172,10 +171,10 @@ static struct kprobe faccessat_kp = {
|
||||
};
|
||||
|
||||
static struct kprobe newfstatat_kp = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
|
||||
.symbol_name = "vfs_statx",
|
||||
#else
|
||||
.symbol_name = "vfs_fstatat",
|
||||
.symbol_name = "vfs_fstatat",
|
||||
#endif
|
||||
.pre_handler = newfstatat_handler_pre,
|
||||
};
|
||||
@@ -183,14 +182,9 @@ static struct kprobe newfstatat_kp = {
|
||||
static struct kprobe execve_kp = {
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
|
||||
.symbol_name = "do_execveat_common",
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
.symbol_name = "__do_execve_file",
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
.symbol_name = "do_execveat_common",
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
|
||||
.symbol_name = "do_execveat_common",
|
||||
#endif
|
||||
.pre_handler = execve_handler_pre,
|
||||
|
||||
@@ -142,4 +142,31 @@ You should found the four functions in kernel source:
|
||||
3. vfs_read, usually in `fs/read_write.c`
|
||||
4. vfs_statx, usually in `fs/stat.c`
|
||||
|
||||
If your kernel does not have the `vfs_statx`, use `vfs_fstatat` instead:
|
||||
|
||||
```diff
|
||||
diff --git a/fs/stat.c b/fs/stat.c
|
||||
index 068fdbcc9e26..5348b7bb9db2 100644
|
||||
--- a/fs/stat.c
|
||||
+++ b/fs/stat.c
|
||||
@@ -87,6 +87,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
|
||||
}
|
||||
EXPORT_SYMBOL(vfs_fstat);
|
||||
|
||||
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
|
||||
+
|
||||
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
|
||||
int flag)
|
||||
{
|
||||
@@ -94,6 +96,8 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
|
||||
int error = -EINVAL;
|
||||
unsigned int lookup_flags = 0;
|
||||
|
||||
+ ksu_handle_stat(&dfd, &filename, &flag);
|
||||
+
|
||||
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
|
||||
AT_EMPTY_PATH)) != 0)
|
||||
goto out;
|
||||
```
|
||||
|
||||
Finally, build your kernel again, KernelSU should works well.
|
||||
|
||||
@@ -142,4 +142,31 @@ index 376543199b5a..82adcef03ecc 100644
|
||||
3. vfs_read,通常位于 `fs/read_write.c`
|
||||
4. vfs_statx,通常位于 `fs/stat.c`
|
||||
|
||||
如果你的内核没有 `vfs_statx`, 使用 `vfs_fstatat` 来代替它:
|
||||
|
||||
```diff
|
||||
diff --git a/fs/stat.c b/fs/stat.c
|
||||
index 068fdbcc9e26..5348b7bb9db2 100644
|
||||
--- a/fs/stat.c
|
||||
+++ b/fs/stat.c
|
||||
@@ -87,6 +87,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
|
||||
}
|
||||
EXPORT_SYMBOL(vfs_fstat);
|
||||
|
||||
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
|
||||
+
|
||||
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
|
||||
int flag)
|
||||
{
|
||||
@@ -94,6 +96,8 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
|
||||
int error = -EINVAL;
|
||||
unsigned int lookup_flags = 0;
|
||||
|
||||
+ ksu_handle_stat(&dfd, &filename, &flag);
|
||||
+
|
||||
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
|
||||
AT_EMPTY_PATH)) != 0)
|
||||
goto out;
|
||||
```
|
||||
|
||||
改完之后重新编译内核即可。
|
||||
|
||||
Reference in New Issue
Block a user