Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 12 additions & 24 deletions kernel/file_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,30 +260,19 @@ void ksu_wrapper_splice_eof(struct file *fp)
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
static int ksu_wrapper_setlease(struct file *fp, int arg1,
struct file_lease **fl, void **p)
{
struct ksu_file_wrapper *data = fp->private_data;
struct file *orig = data->orig;
if (orig->f_op->setlease) {
return orig->f_op->setlease(orig, arg1, fl, p);
}
return -EINVAL;
}
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
static int ksu_wrapper_setlease(struct file *fp, int arg1,
struct file_lock **fl, void **p)
{
struct ksu_file_wrapper *data = fp->private_data;
struct file *orig = data->orig;
if (orig->f_op->setlease) {
return orig->f_op->setlease(orig, arg1, fl, p);
}
return -EINVAL;
}
#define __ksu_sl_file_lock file_lease
#else
static int ksu_wrapper_setlease(struct file *fp, long arg1,
struct file_lock **fl, void **p)
#define __ksu_sl_file_lock file_lock
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
#define __ksu_sl_arg1 int
#else
#define __ksu_sl_arg1 long
#endif

static int ksu_wrapper_setlease(struct file *fp, __ksu_sl_arg1 arg1,
struct __ksu_sl_file_lock **fl, void **p)
{
struct ksu_file_wrapper *data = fp->private_data;
struct file *orig = data->orig;
Expand All @@ -292,7 +281,6 @@ static int ksu_wrapper_setlease(struct file *fp, long arg1,
}
return -EINVAL;
}
#endif

static long ksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset,
loff_t len)
Expand Down
28 changes: 25 additions & 3 deletions kernel/ksud.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,28 @@ static struct work_struct stop_init_rc_hook_work;
static struct work_struct stop_execve_hook_work;
static struct work_struct stop_input_hook_work;

long __strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
long count)
{
long ret;

if (unlikely(count <= 0))
return 0;

pagefault_disable();
ret = strncpy_from_user(dst, unsafe_addr, count);
pagefault_enable();

if (ret >= count) {
ret = count;
dst[ret - 1] = '\0';
} else if (ret > 0) {
ret++;
}

return ret;
}

void on_post_fs_data(void)
{
static bool done = false;
Expand Down Expand Up @@ -205,7 +227,7 @@ static bool check_argv(struct user_arg_ptr argv, int index,
if (!p || IS_ERR(p))
goto fail;

if (strncpy_from_user_nofault(buf, p, buf_len) <= 0)
if (__strncpy_from_user_nofault(buf, p, buf_len) <= 0)
goto fail;

buf[buf_len - 1] = '\0';
Expand Down Expand Up @@ -515,9 +537,9 @@ static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
fn = (const char __user *)addr;

memset(path, 0, sizeof(path));
ret = strncpy_from_user_nofault(path, fn, 32);
ret = __strncpy_from_user_nofault(path, fn, 32);
if (ret < 0 && try_set_access_flag(addr)) {
ret = strncpy_from_user_nofault(path, fn, 32);
ret = __strncpy_from_user_nofault(path, fn, 32);
}
if (ret < 0) {
pr_err("Access filename failed for execve_handler_pre\n");
Expand Down
2 changes: 2 additions & 0 deletions kernel/ksud.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ bool ksu_is_safe_mode(void);

int nuke_ext4_sysfs(const char *mnt);

long __strncpy_from_user_nofault(char *d, const void __user *a, long c);

extern u32 ksu_file_sid;
extern bool ksu_module_mounted;
extern bool ksu_boot_completed;
Expand Down
2 changes: 1 addition & 1 deletion kernel/pkg_observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ int ksu_observer_init(void)
{
int ret = 0;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 154)
g = fsnotify_alloc_group(&ksu_ops, 0);
#else
g = fsnotify_alloc_group(&ksu_ops);
Expand Down
12 changes: 4 additions & 8 deletions kernel/selinux/selinux.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include "../klog.h" // IWYU pragma: keep
#include "../ksu.h"

#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 18, 0)
#define cred_security_struct task_security_struct
#endif

/*
* Cached SID values for frequently checked contexts.
* These are resolved once at init and used for fast u32 comparison
Expand All @@ -27,11 +31,7 @@ static int transive_to_domain(const char *domain, struct cred *cred)
{
u32 sid;
int error;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 18, 0)
struct task_security_struct *tsec;
#else
struct cred_security_struct *tsec;
#endif
tsec = selinux_cred(cred);
if (!tsec) {
pr_err("tsec == NULL!\n");
Expand Down Expand Up @@ -163,11 +163,7 @@ static bool is_sid_match(const struct cred *cred, u32 cached_sid,
if (!cred) {
return false;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 18, 0)
const struct task_security_struct *tsec = selinux_cred(cred);
#else
const struct cred_security_struct *tsec = selinux_cred(cred);
#endif
if (!tsec) {
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions kernel/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,

char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
strncpy_from_user_nofault(path, *filename_user, sizeof(path));
__strncpy_from_user_nofault(path, *filename_user, sizeof(path));

if (unlikely(!memcmp(path, su, sizeof(su)))) {
pr_info("faccessat su->sh!\n");
Expand All @@ -105,7 +105,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)

char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
strncpy_from_user_nofault(path, *filename_user, sizeof(path));
__strncpy_from_user_nofault(path, *filename_user, sizeof(path));

if (unlikely(!memcmp(path, su, sizeof(su)))) {
pr_info("newfstatat su->sh!\n");
Expand Down Expand Up @@ -134,10 +134,10 @@ int ksu_handle_execve_sucompat(const char __user **filename_user,
addr = untagged_addr((unsigned long)*filename_user);
fn = (const char __user *)addr;
memset(path, 0, sizeof(path));
ret = strncpy_from_user_nofault(path, fn, sizeof(path));
ret = __strncpy_from_user_nofault(path, fn, sizeof(path));

if (ret < 0 && try_set_access_flag(addr)) {
ret = strncpy_from_user_nofault(path, fn, sizeof(path));
ret = __strncpy_from_user_nofault(path, fn, sizeof(path));
}

if (ret < 0 && preempt_count()) {
Expand Down
8 changes: 4 additions & 4 deletions kernel/syscall_hook_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ int ksu_get_task_mark(pid_t pid)
int marked = -ESRCH;

rcu_read_lock();
task = find_task_by_vpid(pid);
task = pid_task(find_vpid(pid), PIDTYPE_PID);
if (task) {
get_task_struct(task);
rcu_read_unlock();
Expand All @@ -138,7 +138,7 @@ int ksu_set_task_mark(pid_t pid, bool mark)
int ret = -ESRCH;

rcu_read_lock();
task = find_task_by_vpid(pid);
task = pid_task(find_vpid(pid), PIDTYPE_PID);
if (task) {
get_task_struct(task);
rcu_read_unlock();
Expand Down Expand Up @@ -260,9 +260,9 @@ int ksu_handle_init_mark_tracker(const char __user **filename_user)
fn = (const char __user *)addr;

memset(path, 0, sizeof(path));
ret = strncpy_from_user_nofault(path, fn, sizeof(path));
ret = __strncpy_from_user_nofault(path, fn, sizeof(path));
if (ret < 0 && try_set_access_flag(addr)) {
ret = strncpy_from_user_nofault(path, fn, sizeof(path));
ret = __strncpy_from_user_nofault(path, fn, sizeof(path));
pr_info("ksu_handle_init_mark_tracker: %ld\n", ret);
}

Expand Down