Update susfs4ksu
This commit is contained in:
parent
ceef61157f
commit
85f7fc17fc
17 changed files with 1866 additions and 0 deletions
1495
50_add_susfs_in_gki-android12-5.10.patch
Normal file
1495
50_add_susfs_in_gki-android12-5.10.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
11
fs/exec.c
11
fs/exec.c
|
@ -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);
|
||||||
|
|
46
fs/namei.c
46
fs/namei.c
|
@ -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;
|
||||||
|
|
134
fs/namespace.c
134
fs/namespace.c
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
12
fs/open.c
12
fs/open.c
|
@ -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);
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
12
fs/stat.c
12
fs/stat.c
|
@ -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;
|
||||||
|
|
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