Update susfs4ksu

This commit is contained in:
Ksawlii 2025-01-25 00:03:17 +01:00
parent ceef61157f
commit 85f7fc17fc
17 changed files with 1866 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,9 @@ obj-y := open.o read_write.o file_table.o super.o \
obj-$(CONFIG_KSU_SUSFS) += susfs.o obj-$(CONFIG_KSU_SUSFS) += susfs.o
obj-$(CONFIG_KSU_SUSFS_SUS_SU) += sus_su.o obj-$(CONFIG_KSU_SUSFS_SUS_SU) += sus_su.o
obj-$(CONFIG_KSU_SUSFS) += susfs.o
obj-$(CONFIG_KSU_SUSFS_SUS_SU) += sus_su.o
ifeq ($(CONFIG_BLOCK),y) ifeq ($(CONFIG_BLOCK),y)
obj-y += buffer.o block_dev.o direct-io.o mpage.o obj-y += buffer.o block_dev.o direct-io.o mpage.o
else else

View file

@ -2410,6 +2410,12 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
if (dentry->d_name.hash != hash) if (dentry->d_name.hash != hash)
continue; continue;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
continue;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH #ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { if (dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
continue; continue;

View file

@ -601,6 +601,11 @@ extern bool ksu_devpts_hook;
extern int ksu_handle_devpts(struct inode*); extern int ksu_handle_devpts(struct inode*);
#endif #endif
#if defined(CONFIG_KSU_SUSFS_SUS_SU)
extern bool ksu_devpts_hook;
extern int ksu_handle_devpts(struct inode*);
#endif
/** /**
* devpts_get_priv -- get private data for a slave * devpts_get_priv -- get private data for a slave
* @pts_inode: inode of the slave * @pts_inode: inode of the slave

View file

@ -1882,6 +1882,12 @@ extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
void *envp, int *flags); void *envp, int *flags);
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool susfs_is_sus_su_hooks_enabled __read_mostly;
extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, void *argv,
void *envp, int *flags);
#endif
static int do_execveat_common(int fd, struct filename *filename, static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv, struct user_arg_ptr argv,
struct user_arg_ptr envp, struct user_arg_ptr envp,
@ -1893,6 +1899,11 @@ static int do_execveat_common(int fd, struct filename *filename,
if (IS_ERR(filename)) if (IS_ERR(filename))
return PTR_ERR(filename); return PTR_ERR(filename);
#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (susfs_is_sus_su_hooks_enabled)
ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU #ifdef CONFIG_KSU_SUSFS_SUS_SU
if (susfs_is_sus_su_hooks_enabled) if (susfs_is_sus_su_hooks_enabled)
ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags); ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);

View file

@ -39,6 +39,9 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/init_task.h> #include <linux/init_task.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#if defined(CONFIG_KSU_SUSFS_SUS_PATH) || defined(CONFIG_KSU_SUSFS_OPEN_REDIRECT)
#include <linux/susfs_def.h>
#endif
#if defined(CONFIG_KSU_SUSFS_SUS_PATH) || defined(CONFIG_KSU_SUSFS_OPEN_REDIRECT) #if defined(CONFIG_KSU_SUSFS_SUS_PATH) || defined(CONFIG_KSU_SUSFS_OPEN_REDIRECT)
#include <linux/susfs_def.h> #include <linux/susfs_def.h>
@ -1136,6 +1139,12 @@ int may_linkat(struct path *link)
{ {
struct inode *inode = link->dentry->d_inode; struct inode *inode = link->dentry->d_inode;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (inode && unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH #ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (inode && unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { if (inode && unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT; return -ENOENT;
@ -1561,6 +1570,19 @@ static struct dentry *lookup_dcache(const struct qstr *name,
return ERR_PTR(error); return ERR_PTR(error);
} }
} }
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
if ((flags & (LOOKUP_CREATE | LOOKUP_EXCL))) {
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
if (error) {
dput(dentry);
return ERR_PTR(error);
}
}
dput(dentry);
return ERR_PTR(-ENOENT);
}
#endif
return dentry; return dentry;
} }
@ -1673,6 +1695,12 @@ static struct dentry *lookup_fast(struct nameidata *nd,
dput(dentry); dput(dentry);
return ERR_PTR(status); return ERR_PTR(status);
} }
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (!IS_ERR(dentry) && dentry->d_inode && unlikely(dentry->d_inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
dput(dentry);
return ERR_PTR(-ENOENT);
}
#endif
return dentry; return dentry;
} }
@ -2470,6 +2498,12 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
path_get(&nd->root); path_get(&nd->root);
nd->flags |= LOOKUP_ROOT_GRABBED; nd->flags |= LOOKUP_ROOT_GRABBED;
} }
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
// we deal with sus sub path here
if (nd->inode && unlikely(nd->inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return 0;
}
#endif
} }
return s; return s;
} }
@ -2881,6 +2915,12 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
if (IS_APPEND(dir)) if (IS_APPEND(dir))
return -EPERM; return -EPERM;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH #ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT; return -ENOENT;
@ -3094,6 +3134,12 @@ static int may_open(const struct path *path, int acc_mode, int flag)
if (!inode) if (!inode)
return -ENOENT; return -ENOENT;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_PATH #ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) { if (unlikely(inode->i_state & INODE_STATE_SUS_PATH) && likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
return -ENOENT; return -ENOENT;

View file

@ -190,6 +190,18 @@ static inline struct hlist_head *mp_hash(struct dentry *dentry)
return &mountpoint_hashtable[tmp & mp_hash_mask]; return &mountpoint_hashtable[tmp & mp_hash_mask];
} }
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// Our own mnt_alloc_id() that assigns mnt_id starting from DEFAULT_SUS_MNT_ID
static int susfs_mnt_alloc_id(struct mount *mnt)
{
int res = ida_alloc_min(&susfs_mnt_id_ida, DEFAULT_SUS_MNT_ID, GFP_KERNEL);
if (res < 0)
return res;
mnt->mnt_id = res;
return 0;
}
#endif
static int mnt_alloc_id(struct mount *mnt) static int mnt_alloc_id(struct mount *mnt)
{ {
int res = ida_alloc(&mnt_id_ida, GFP_KERNEL); int res = ida_alloc(&mnt_id_ida, GFP_KERNEL);
@ -226,7 +238,20 @@ static void susfs_mnt_alloc_group_id(struct mount *mnt)
*/ */
static int mnt_alloc_group_id(struct mount *mnt) static int mnt_alloc_group_id(struct mount *mnt)
{ {
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
int res;
// Check if mnt has sus mnt_id
if (mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
// If so, assign a sus mnt_group id DEFAULT_SUS_MNT_GROUP_ID from susfs_mnt_group_ida
res = ida_alloc_min(&susfs_mnt_group_ida, DEFAULT_SUS_MNT_GROUP_ID, GFP_KERNEL);
goto bypass_orig_flow;
}
res = ida_alloc_min(&mnt_group_ida, 1, GFP_KERNEL);
bypass_orig_flow:
#else
int res = ida_alloc_min(&mnt_group_ida, 1, GFP_KERNEL); int res = ida_alloc_min(&mnt_group_ida, 1, GFP_KERNEL);
#endif
if (res < 0) if (res < 0)
return res; return res;
@ -284,13 +309,31 @@ int mnt_get_count(struct mount *mnt)
#endif #endif
} }
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
static struct mount *alloc_vfsmnt(const char *name, bool should_spoof, int custom_mnt_id)
#else
static struct mount *alloc_vfsmnt(const char *name) static struct mount *alloc_vfsmnt(const char *name)
#endif
{ {
struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
if (mnt) { if (mnt) {
int err; int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (should_spoof) {
if (!custom_mnt_id) {
err = susfs_mnt_alloc_id(mnt);
} else {
mnt->mnt_id = custom_mnt_id;
err = 0;
}
goto bypass_orig_flow;
}
#endif
err = mnt_alloc_id(mnt); err = mnt_alloc_id(mnt);
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
bypass_orig_flow:
#endif
if (err) if (err)
goto out_free_cache; goto out_free_cache;
#ifdef CONFIG_KDP_NS #ifdef CONFIG_KDP_NS
@ -1121,7 +1164,17 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc)
if (!fc->root) if (!fc->root)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// For newly created mounts, the only caller process we care is KSU
if (unlikely(susfs_is_current_ksu_domain())) {
mnt = alloc_vfsmnt(fc->source ?: "none", true, 0);
goto bypass_orig_flow;
}
mnt = alloc_vfsmnt(fc->source ?: "none", false, 0);
bypass_orig_flow:
#else
mnt = alloc_vfsmnt(fc->source ?: "none"); mnt = alloc_vfsmnt(fc->source ?: "none");
#endif
if (!mnt) if (!mnt)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -1150,6 +1203,13 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc)
} }
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// If caller process is zygote, then it is a normal mount, so we just reorder the mnt_id
if (susfs_is_current_zygote_domain()) {
mnt->mnt.susfs_mnt_id_backup = mnt->mnt_id;
mnt->mnt_id = current->susfs_last_fake_mnt_id++;
}
#endif
lock_mount_hash(); lock_mount_hash();
#ifdef CONFIG_KDP_NS #ifdef CONFIG_KDP_NS
list_add_tail(&mnt->mnt_instance, &((struct kdp_mount *)mnt)->mnt->mnt_sb->s_mounts); list_add_tail(&mnt->mnt_instance, &((struct kdp_mount *)mnt)->mnt->mnt_sb->s_mounts);
@ -1232,8 +1292,52 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
#endif #endif
struct mount *mnt; struct mount *mnt;
int err; int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
bool is_current_ksu_domain = susfs_is_current_ksu_domain();
bool is_current_zygote_domain = susfs_is_current_zygote_domain();
/* - It is very important that we need to use CL_COPY_MNT_NS to identify whether
* the clone is a copy_tree() or single mount like called by __do_loopback()
* - if caller process is KSU, consider the following situation:
* 1. it is NOT doing unshare => call alloc_vfsmnt() to assign a new sus mnt_id
* 2. it is doing unshare => spoof the new mnt_id with the old mnt_id
* - If caller process is zygote and old mnt_id is sus => call alloc_vfsmnt() to assign a new sus mnt_id
* - For the rest of caller process that doing unshare => call alloc_vfsmnt() to assign a new sus mnt_id only for old sus mount
*/
// Firstly, check if it is KSU process
if (unlikely(is_current_ksu_domain)) {
// if it is doing single clone
if (!(flag & CL_COPY_MNT_NS)) {
mnt = alloc_vfsmnt(old->mnt_devname, true, 0);
goto bypass_orig_flow;
}
// if it is doing unshare
mnt = alloc_vfsmnt(old->mnt_devname, true, old->mnt_id);
if (mnt) {
mnt->mnt.susfs_mnt_id_backup = DEFAULT_SUS_MNT_ID_FOR_KSU_PROC_UNSHARE;
}
goto bypass_orig_flow;
}
// Secondly, check if it is zygote process and no matter it is doing unshare or not
if (likely(is_current_zygote_domain) && (old->mnt_id >= DEFAULT_SUS_MNT_ID)) {
/* Important Note:
* - Here we can't determine whether the unshare is called zygisk or not,
* so we can only patch out the unshare code in zygisk source code for now
* - But at least we can deal with old sus mounts using alloc_vfsmnt()
*/
mnt = alloc_vfsmnt(old->mnt_devname, true, 0);
goto bypass_orig_flow;
}
// Lastly, for other process that is doing unshare operation, but only deal with old sus mount
if ((flag & CL_COPY_MNT_NS) && (old->mnt_id >= DEFAULT_SUS_MNT_ID)) {
mnt = alloc_vfsmnt(old->mnt_devname, true, 0);
goto bypass_orig_flow;
}
mnt = alloc_vfsmnt(old->mnt_devname, false, 0);
bypass_orig_flow:
#else
mnt = alloc_vfsmnt(old->mnt_devname); mnt = alloc_vfsmnt(old->mnt_devname);
#endif
if (!mnt) if (!mnt)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -2610,6 +2714,29 @@ retry:
} }
return mp; return mp;
} }
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// current->susfs_last_fake_mnt_id -> to record last valid fake mnt_id to zygote pid
// q->mnt.susfs_mnt_id_backup -> original mnt_id
// q->mnt_id -> will be modified to the fake mnt_id
// Here We are only interested in processes of which original mnt namespace belongs to zygote
// Also we just make use of existing 'q' mount pointer, no need to delcare extra mount pointer
if (is_zygote_pid) {
last_entry_mnt_id = list_first_entry(&new_ns->list, struct mount, mnt_list)->mnt_id;
list_for_each_entry(q, &new_ns->list, mnt_list) {
if (unlikely(q->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT)) {
continue;
}
q->mnt.susfs_mnt_id_backup = q->mnt_id;
q->mnt_id = last_entry_mnt_id++;
}
}
// Assign the 'last_entry_mnt_id' to 'current->susfs_last_fake_mnt_id' for later use.
// should be fine here assuming zygote is forking/unsharing app in one single thread.
// Or should we put a lock here?
current->susfs_last_fake_mnt_id = last_entry_mnt_id;
#endif
namespace_unlock(); namespace_unlock();
inode_unlock(path->dentry->d_inode); inode_unlock(path->dentry->d_inode);
path_put(path); path_put(path);
@ -3986,6 +4113,13 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
} }
#endif #endif
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT) && defined(CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT)
// Just for the compatibility of Magic Mount KernelSU
if (!ret && susfs_is_auto_add_sus_ksu_default_mount_enabled && susfs_is_current_ksu_domain()) {
susfs_auto_add_sus_ksu_default_mount(dir_name);
}
#endif
kfree(options); kfree(options);
out_data: out_data:
kfree(kernel_dev); kfree(kernel_dev);

View file

@ -12,6 +12,9 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#include <linux/susfs_def.h>
#endif
#include "inotify/inotify.h" #include "inotify/inotify.h"
#include "fanotify/fanotify.h" #include "fanotify/fanotify.h"
@ -73,7 +76,11 @@ static void show_mark_fhandle(struct seq_file *m, struct inode *inode)
#ifdef CONFIG_INOTIFY_USER #ifdef CONFIG_INOTIFY_USER
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark, struct file *file)
#else
static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
#endif
{ {
struct inotify_inode_mark *inode_mark; struct inotify_inode_mark *inode_mark;
struct inode *inode; struct inode *inode;
@ -84,6 +91,36 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark); inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
inode = igrab(fsnotify_conn_inode(mark->connector)); inode = igrab(fsnotify_conn_inode(mark->connector));
if (inode) { if (inode) {
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) &&
unlikely(inode->i_state & INODE_STATE_SUS_KSTAT)) {
struct path path;
char *pathname = kmalloc(PAGE_SIZE, GFP_KERNEL);
char *dpath;
if (!pathname) {
goto out_seq_printf;
}
dpath = d_path(&file->f_path, pathname, PAGE_SIZE);
if (!dpath) {
goto out_free_pathname;
}
if (kern_path(dpath, 0, &path)) {
goto out_free_pathname;
}
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
inode_mark->wd, path.dentry->d_inode->i_ino, path.dentry->d_inode->i_sb->s_dev,
inotify_mark_user_mask(mark));
show_mark_fhandle(m, path.dentry->d_inode);
seq_putc(m, '\n');
iput(inode);
path_put(&path);
kfree(pathname);
return;
out_free_pathname:
kfree(pathname);
}
out_seq_printf:
#endif
seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ", seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:0 ",
inode_mark->wd, inode->i_ino, inode->i_sb->s_dev, inode_mark->wd, inode->i_ino, inode->i_sb->s_dev,
inotify_mark_user_mask(mark)); inotify_mark_user_mask(mark));

View file

@ -401,6 +401,12 @@ extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int
int *flags); int *flags);
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool susfs_is_sus_su_hooks_enabled __read_mostly;
extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *flags);
#endif
static long do_faccessat(int dfd, const char __user *filename, int mode, int flags) static long do_faccessat(int dfd, const char __user *filename, int mode, int flags)
{ {
struct path path; struct path path;
@ -409,6 +415,12 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla
unsigned int lookup_flags = LOOKUP_FOLLOW; unsigned int lookup_flags = LOOKUP_FOLLOW;
const struct cred *old_cred = NULL; const struct cred *old_cred = NULL;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (susfs_is_sus_su_hooks_enabled) {
ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU #ifdef CONFIG_KSU_SUSFS_SUS_SU
if (susfs_is_sus_su_hooks_enabled) { if (susfs_is_sus_su_hooks_enabled) {
ksu_handle_faccessat(&dfd, &filename, &mode, NULL); ksu_handle_faccessat(&dfd, &filename, &mode, NULL);

View file

@ -168,6 +168,15 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
metacopy_blocks = ovl_is_metacopy_dentry(dentry); metacopy_blocks = ovl_is_metacopy_dentry(dentry);
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
ovl_path_lowerdata(dentry, &realpath);
if (likely(realpath.mnt && realpath.dentry)) {
old_cred = ovl_override_creds(dentry->d_sb);
err = vfs_getattr(&realpath, stat, request_mask, flags);
goto out;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS #ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
ovl_path_lowerdata(dentry, &realpath); ovl_path_lowerdata(dentry, &realpath);
if (likely(realpath.mnt && realpath.dentry)) { if (likely(realpath.mnt && realpath.dentry)) {

View file

@ -327,6 +327,18 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
struct path path; struct path path;
int err; int err;
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
ovl_path_lowerdata(root_dentry, &path);
if (likely(path.mnt && path.dentry)) {
err = vfs_statfs(&path, buf);
if (!err) {
buf->f_namelen = 255; // 255 for erofs, ext2/4, f2fs
buf->f_type = path.dentry->d_sb->s_magic;
}
return err;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS #ifdef CONFIG_KSU_SUSFS_SUS_OVERLAYFS
ovl_path_lowerdata(root_dentry, &path); ovl_path_lowerdata(root_dentry, &path);
if (likely(path.mnt && path.dentry)) { if (likely(path.mnt && path.dentry)) {

View file

@ -13,6 +13,9 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#include <linux/susfs_def.h>
#endif
#include "../mount.h" #include "../mount.h"
#include "internal.h" #include "internal.h"
@ -24,6 +27,9 @@ static int seq_show(struct seq_file *m, void *v)
int f_flags = 0, ret = -ENOENT; int f_flags = 0, ret = -ENOENT;
struct file *file = NULL; struct file *file = NULL;
struct task_struct *task; struct task_struct *task;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
struct mount *mnt = NULL;
#endif
task = get_proc_task(m->private); task = get_proc_task(m->private);
if (!task) if (!task)
@ -54,10 +60,48 @@ static int seq_show(struct seq_file *m, void *v)
if (ret) if (ret)
return ret; return ret;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
mnt = real_mount(file->f_path.mnt);
if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) &&
mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
struct path path;
char *pathname = kmalloc(PAGE_SIZE, GFP_KERNEL);
char *dpath;
for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) { }
if (!pathname) {
goto out_seq_printf;
}
dpath = d_path(&file->f_path, pathname, PAGE_SIZE);
if (!dpath) {
goto out_free_pathname;
}
if (kern_path(dpath, 0, &path)) {
goto out_free_pathname;
}
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nino:\t%lu\n",
(long long)file->f_pos, f_flags,
mnt->mnt_id,
path.dentry->d_inode->i_ino);
path_put(&path);
kfree(pathname);
goto bypass_orig_flow;
out_free_pathname:
kfree(pathname);
}
out_seq_printf:
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nino:\t%lu\n",
(long long)file->f_pos, f_flags,
mnt->mnt_id,
file_inode(file)->i_ino);
bypass_orig_flow:
#else
seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nino:\t%lu\n", seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nino:\t%lu\n",
(long long)file->f_pos, f_flags, (long long)file->f_pos, f_flags,
real_mount(file->f_path.mnt)->mnt_id, real_mount(file->f_path.mnt)->mnt_id,
file_inode(file)->i_ino); file_inode(file)->i_ino);
#endif
/* show_fd_locks() never deferences files so a stale value is safe */ /* show_fd_locks() never deferences files so a stale value is safe */
show_fd_locks(m, file, files); show_fd_locks(m, file, files);

View file

@ -324,6 +324,10 @@ static void show_vma_header_prefix(struct seq_file *m,
extern void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino); extern void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino);
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
extern void susfs_sus_ino_for_show_map_vma(unsigned long ino, dev_t *out_dev, unsigned long *out_ino);
#endif
static void static void
show_map_vma(struct seq_file *m, struct vm_area_struct *vma) show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
{ {

View file

@ -110,6 +110,11 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
struct super_block *sb = mnt_path.dentry->d_sb; struct super_block *sb = mnt_path.dentry->d_sb;
int err; int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely((r->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT) && !susfs_is_current_ksu_domain()))
return 0;
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely((r->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT) && !susfs_is_current_ksu_domain())) if (unlikely((r->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT) && !susfs_is_current_ksu_domain()))
return 0; return 0;
@ -215,6 +220,11 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
struct super_block *sb = mnt_path.dentry->d_sb; struct super_block *sb = mnt_path.dentry->d_sb;
int err; int err;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely((r->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT) && !susfs_is_current_ksu_domain()))
return 0;
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely((r->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT) && !susfs_is_current_ksu_domain())) if (unlikely((r->mnt.mnt_root->d_inode->i_state & INODE_STATE_SUS_MOUNT) && !susfs_is_current_ksu_domain()))
return 0; return 0;

View file

@ -498,6 +498,11 @@ static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
namlen + 2, sizeof(compat_long_t)); namlen + 2, sizeof(compat_long_t));
int prev_reclen; int prev_reclen;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC) && susfs_sus_ino_for_filldir64(ino)) {
return 0;
}
#endif
buf->error = verify_dirent_name(name, namlen); buf->error = verify_dirent_name(name, namlen);
if (unlikely(buf->error)) if (unlikely(buf->error))
return buf->error; return buf->error;

View file

@ -31,6 +31,10 @@
extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat); extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
extern void susfs_sus_ino_for_generic_fillattr(unsigned long ino, struct kstat *stat);
#endif
/** /**
* generic_fillattr - Fill in the basic attributes from the inode struct * generic_fillattr - Fill in the basic attributes from the inode struct
* @inode: Inode to use as the source * @inode: Inode to use as the source
@ -224,7 +228,15 @@ retry:
goto out; goto out;
error = vfs_getattr(&path, stat, request_mask, flags); error = vfs_getattr(&path, stat, request_mask, flags);
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
mnt = real_mount(path.mnt);
if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) {}
}
stat->mnt_id = mnt->mnt_id;
#else
stat->mnt_id = real_mount(path.mnt)->mnt_id; stat->mnt_id = real_mount(path.mnt)->mnt_id;
#endif
stat->result_mask |= STATX_MNT_ID; stat->result_mask |= STATX_MNT_ID;
if (path.mnt->mnt_root == path.dentry) if (path.mnt->mnt_root == path.dentry)
stat->attributes |= STATX_ATTR_MOUNT_ROOT; stat->attributes |= STATX_ATTR_MOUNT_ROOT;

View file

@ -9,6 +9,10 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/compat.h> #include <linux/compat.h>
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#include <linux/susfs_def.h>
#include "mount.h"
#endif
#include "internal.h" #include "internal.h"
static int flags_by_mnt(int mnt_flags) static int flags_by_mnt(int mnt_flags)
@ -86,11 +90,23 @@ EXPORT_SYMBOL(vfs_get_fsid);
int vfs_statfs(const struct path *path, struct kstatfs *buf) int vfs_statfs(const struct path *path, struct kstatfs *buf)
{ {
int error; int error;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
struct mount *mnt;
mnt = real_mount(path->mnt);
if (likely(current->susfs_task_state & TASK_STRUCT_NON_ROOT_USER_APP_PROC)) {
for (; mnt->mnt_id >= DEFAULT_SUS_MNT_ID; mnt = mnt->mnt_parent) {}
}
error = statfs_by_dentry(mnt->mnt.mnt_root, buf);
if (!error)
buf->f_flags = calculate_f_flags(&mnt->mnt);
return error;
#else
error = statfs_by_dentry(path->dentry, buf); error = statfs_by_dentry(path->dentry, buf);
if (!error) if (!error)
buf->f_flags = calculate_f_flags(path->mnt); buf->f_flags = calculate_f_flags(path->mnt);
return error; return error;
#endif
} }
EXPORT_SYMBOL(vfs_statfs); EXPORT_SYMBOL(vfs_statfs);
@ -262,6 +278,11 @@ static int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
if (!s) if (!s)
return -EINVAL; return -EINVAL;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (unlikely(s->s_root->d_inode->i_state & INODE_STATE_SUS_MOUNT)) {
return -EINVAL;
}
#endif
err = statfs_by_dentry(s->s_root, sbuf); err = statfs_by_dentry(s->s_root, sbuf);
drop_super(s); drop_super(s);
return err; return err;