Update and fix susfs4ksu
This commit is contained in:
parent
c8b3e5b969
commit
e0a4064163
6 changed files with 234 additions and 12 deletions
|
@ -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
|
||||||
|
|
||||||
#ifdef CONFIG_FSCRYPT_SDP
|
#ifdef CONFIG_FSCRYPT_SDP
|
||||||
#include <linux/fscrypto_sdp_name.h>
|
#include <linux/fscrypto_sdp_name.h>
|
||||||
|
|
102
fs/namespace.c
102
fs/namespace.c
|
@ -197,6 +197,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);
|
||||||
|
@ -238,7 +250,7 @@ static void mnt_free_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
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
// Check if mnt has sus mnt_id
|
// Check if mnt has sus mnt_id
|
||||||
if (mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
|
if (mnt->mnt_id >= DEFAULT_SUS_MNT_ID) {
|
||||||
|
@ -309,13 +321,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
|
||||||
|
@ -1146,8 +1176,18 @@ 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");
|
||||||
if (!mnt)
|
#endif
|
||||||
|
if (!mnt)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
if (fc->sb_flags & SB_KERNMOUNT)
|
if (fc->sb_flags & SB_KERNMOUNT)
|
||||||
|
@ -1169,12 +1209,12 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc)
|
||||||
mnt->mnt_parent = mnt;
|
mnt->mnt_parent = mnt;
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
#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()) {
|
if (susfs_is_current_zygote_domain()) {
|
||||||
mnt->mnt.susfs_orig_mnt_id = mnt->mnt_id;
|
mnt->mnt.susfs_mnt_id_backup = mnt->mnt_id;
|
||||||
mnt->mnt_id = current->susfs_last_fake_mnt_id++;
|
mnt->mnt_id = current->susfs_last_fake_mnt_id++;
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
||||||
|
@ -1257,9 +1297,53 @@ 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);
|
||||||
if (!mnt)
|
#endif
|
||||||
|
if (!mnt)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
|
if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
|
||||||
|
@ -2798,12 +2882,15 @@ static int do_loopback(struct path *path, const char *old_name,
|
||||||
// And we target only process with ksu domain.
|
// And we target only process with ksu domain.
|
||||||
if (susfs_is_current_ksu_domain()) {
|
if (susfs_is_current_ksu_domain()) {
|
||||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
||||||
if (susfs_auto_add_sus_bind_mount(old_name, &old_path)) {
|
if (susfs_is_auto_add_sus_bind_mount_enabled &&
|
||||||
|
susfs_auto_add_sus_bind_mount(old_name, &old_path)) {
|
||||||
goto orig_flow;
|
goto orig_flow;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT)
|
||||||
susfs_auto_add_try_umount_for_bind_mount(path);
|
if (susfs_is_auto_add_try_umount_for_bind_mount_enabled) {
|
||||||
|
susfs_auto_add_try_umount_for_bind_mount(path);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT)
|
||||||
|
@ -3996,6 +4083,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
|
||||||
goto out_data;
|
goto out_data;
|
||||||
|
|
||||||
ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
|
ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
|
||||||
|
|
||||||
#if defined(CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT) && defined(CONFIG_KSU_SUSFS_HAS_MAGIC_MOUNT)
|
#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
|
// Just for the compatibility of Magic Mount KernelSU
|
||||||
if (!ret && susfs_is_auto_add_sus_ksu_default_mount_enabled && susfs_is_current_ksu_domain()) {
|
if (!ret && susfs_is_auto_add_sus_ksu_default_mount_enabled && susfs_is_current_ksu_domain()) {
|
||||||
|
|
|
@ -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"
|
||||||
|
@ -22,17 +25,28 @@
|
||||||
|
|
||||||
#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
|
#if defined(CONFIG_INOTIFY_USER) || defined(CONFIG_FANOTIFY)
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
static void show_fdinfo(struct seq_file *m, struct file *f,
|
||||||
|
void (*show)(struct seq_file *m,
|
||||||
|
struct fsnotify_mark *mark,
|
||||||
|
struct file *file))
|
||||||
|
#else
|
||||||
static void show_fdinfo(struct seq_file *m, struct file *f,
|
static void show_fdinfo(struct seq_file *m, struct file *f,
|
||||||
void (*show)(struct seq_file *m,
|
void (*show)(struct seq_file *m,
|
||||||
struct fsnotify_mark *mark))
|
struct fsnotify_mark *mark))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct fsnotify_group *group = f->private_data;
|
struct fsnotify_group *group = f->private_data;
|
||||||
struct fsnotify_mark *mark;
|
struct fsnotify_mark *mark;
|
||||||
|
|
||||||
fsnotify_group_lock(group);
|
fsnotify_group_lock(group);
|
||||||
list_for_each_entry(mark, &group->marks_list, g_list) {
|
list_for_each_entry(mark, &group->marks_list, g_list) {
|
||||||
show(m, mark);
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
if (seq_has_overflowed(m))
|
show(m, mark, f);
|
||||||
|
#else
|
||||||
|
show(m, mark);
|
||||||
|
#endif
|
||||||
|
if (seq_has_overflowed(m))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fsnotify_group_unlock(group);
|
fsnotify_group_unlock(group);
|
||||||
|
@ -73,7 +87,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 +102,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));
|
||||||
|
|
44
fs/proc/fd.c
44
fs/proc/fd.c
|
@ -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);
|
||||||
|
|
22
fs/stat.c
22
fs/stat.c
|
@ -139,6 +139,7 @@ EXPORT_SYMBOL(vfs_getattr_nosec);
|
||||||
*
|
*
|
||||||
* 0 will be returned on success, and a -ve error code if unsuccessful.
|
* 0 will be returned on success, and a -ve error code if unsuccessful.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int vfs_getattr(const struct path *path, struct kstat *stat,
|
int vfs_getattr(const struct path *path, struct kstat *stat,
|
||||||
u32 request_mask, unsigned int query_flags)
|
u32 request_mask, unsigned int query_flags)
|
||||||
{
|
{
|
||||||
|
@ -201,6 +202,15 @@ static int vfs_statx(int dfd, const char __user *filename, int flags,
|
||||||
struct path path;
|
struct path path;
|
||||||
unsigned lookup_flags = 0;
|
unsigned lookup_flags = 0;
|
||||||
int error;
|
int error;
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
|
struct mount *mnt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||||
|
if (susfs_is_sus_su_hooks_enabled) {
|
||||||
|
ksu_handle_stat(&dfd, &filename, &flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
struct mount *mnt;
|
struct mount *mnt;
|
||||||
|
@ -229,8 +239,16 @@ retry:
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = vfs_getattr(&path, stat, request_mask, flags);
|
error = vfs_getattr(&path, stat, request_mask, flags);
|
||||||
stat->mnt_id = real_mount(path.mnt)->mnt_id;
|
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||||
stat->result_mask |= STATX_MNT_ID;
|
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;
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
|
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
|
||||||
|
|
21
fs/statfs.c
21
fs/statfs.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue