aboutsummaryrefslogtreecommitdiff
path: root/fs/sdcardfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sdcardfs/inode.c')
-rwxr-xr-x[-rw-r--r--]fs/sdcardfs/inode.c534
1 files changed, 392 insertions, 142 deletions
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 69060ee5..1275cdec 100644..100755
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -1,93 +1,134 @@
/*
* fs/sdcardfs/inode.c
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd
- * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
- * Sunghwan Yun, Sungjong Seo
- *
+ * Copyright (c) 2015 Lenovo Co. Ltd
+ * Authors: liaohs , jixj
+
+ *
* This program has been developed as a stackable file system based on
- * the WrapFS which written by
+ * the WrapFS which written by
*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009 Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ * Copyright (c) 1998-2014 Erez Zadok
+ * Copyright (c) 2009 Shrikar Archak
+ * Copyright (c) 2003-2014 Stony Brook University
+ * Copyright (c) 2003-2014 The Research Foundation of SUNY
*
- * This file is dual licensed. It may be redistributed and/or modified
- * under the terms of the Apache 2.0 License OR version 2 of the GNU
- * General Public License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
#include "sdcardfs.h"
+#include <linux/fsnotify.h>
+#include <linux/fs_struct.h>
+
+#ifdef CONFIG_SECURITY_SELINUX
+static inline void sdcardfs_override_secid(struct sdcardfs_sb_info *sbi,
+ struct cred *creds)
+{
+ struct task_security_struct *tsec = creds->security;
+
+ if (sbi->lower_secid)
+ tsec->sid = sbi->lower_secid;
+
+ SDFS_DBG("sdcardfs_override_secid sec_id=%d", tsec->sid);
+}
+
+#else
+static inline void sdcardfs_override_secid(struct sdcardfs_sb_info *sbi,
+ struct cred *creds) {}
+#endif
/* Do not directly use this function. Use OVERRIDE_CRED() instead. */
const struct cred * override_fsids(struct sdcardfs_sb_info* sbi)
{
- struct cred * cred;
- const struct cred * old_cred;
+ struct cred * cred;
+ const struct cred * old_cred;
- cred = prepare_creds();
- if (!cred)
- return NULL;
+ cred = prepare_creds();
+ if (!cred)
+ return NULL;
- cred->fsuid = make_kuid(&init_user_ns, sbi->options.fs_low_uid);
- cred->fsgid = make_kgid(&init_user_ns, sbi->options.fs_low_gid);
+ cred->fsuid.val = sbi->options.fs_low_uid;
+ cred->fsgid.val = sbi->options.fs_low_gid;
+ sdcardfs_override_secid(sbi, cred);
- old_cred = override_creds(cred);
+ old_cred = override_creds(cred);
- return old_cred;
+ return old_cred;
}
/* Do not directly use this function, use REVERT_CRED() instead. */
void revert_fsids(const struct cred * old_cred)
{
- const struct cred * cur_cred;
+ const struct cred * cur_cred;
- cur_cred = current->cred;
- revert_creds(old_cred);
- put_cred(cur_cred);
+ cur_cred = current->cred;
+ revert_creds(old_cred);
+ put_cred(cur_cred);
}
static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
- umode_t mode, bool want_excl)
+ umode_t mode, bool excl)
{
- int err;
+ int err = 0;
struct dentry *lower_dentry;
struct dentry *lower_parent_dentry = NULL;
struct path lower_path;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
const struct cred *saved_cred = NULL;
+ int mask = 0;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
+ SDFS_DBG("dentry='%s' parent='%s' \n",dentry->d_name.name,dentry->d_parent->d_name.name);
+ if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
err = -EACCES;
goto out_eacces;
}
+ if (sbi->flag && SDCARDFS_MOUNT_ACCESS_DISABLE) {
+ SDFS_DBG("sdcardfs_create access disable\n");
+ err = -ENOENT;
+ goto out_eacces;
+ }
/* save current_cred and override it */
OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+ /* clear the umask so that the lower mode works for create cases */
+ mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
sdcardfs_get_lower_path(dentry, &lower_path);
lower_dentry = lower_path.dentry;
lower_parent_dentry = lock_parent(lower_dentry);
+ err = mnt_want_write(lower_path.mnt);
+ if (err)
+ goto out_unlock;
+
/* set last 16bytes of mode field to 0664 */
- mode = (mode & S_IFMT) | 00664;
- err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, want_excl);
+ mode = (mode & S_IFMT) | 00664;
+ err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, true);
+
if (err)
goto out;
- err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, SDCARDFS_I(dir)->userid);
+ err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
if (err)
goto out;
fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
out:
+ mnt_drop_write(lower_path.mnt);
+out_unlock:
unlock_dir(lower_parent_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
REVERT_CRED(saved_cred);
+ /* restore the old umask */
+ if (mask)
+ mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
out_eacces:
return err;
}
@@ -104,7 +145,7 @@ static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir,
struct path lower_old_path, lower_new_path;
OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb));
-
+
file_size_save = i_size_read(old_dentry->d_inode);
sdcardfs_get_lower_path(old_dentry, &lower_old_path);
sdcardfs_get_lower_path(new_dentry, &lower_new_path);
@@ -112,8 +153,12 @@ static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir,
lower_new_dentry = lower_new_path.dentry;
lower_dir_dentry = lock_parent(lower_new_dentry);
+ err = mnt_want_write(lower_new_path.mnt);
+ if (err)
+ goto out_unlock;
+
err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
- lower_new_dentry, NULL);
+ lower_new_dentry);
if (err || !lower_new_dentry->d_inode)
goto out;
@@ -126,6 +171,8 @@ static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir,
sdcardfs_lower_inode(old_dentry->d_inode)->i_nlink);
i_size_write(new_dentry->d_inode, file_size_save);
out:
+ mnt_drop_write(lower_new_path.mnt);
+out_unlock:
unlock_dir(lower_dir_dentry);
sdcardfs_put_lower_path(old_dentry, &lower_old_path);
sdcardfs_put_lower_path(new_dentry, &lower_new_path);
@@ -141,16 +188,24 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
struct inode *lower_dir_inode = sdcardfs_lower_inode(dir);
struct dentry *lower_dir_dentry;
struct path lower_path;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
const struct cred *saved_cred = NULL;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
+ SDFS_DBG("dentry='%s' parent='%s' \n",dentry->d_name.name,dentry->d_parent->d_name.name);
+ if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
err = -EACCES;
goto out_eacces;
}
+ if (sbi->flag && SDCARDFS_MOUNT_ACCESS_DISABLE) {
+ SDFS_DBG("sdcardfs_unlink access disable\n");
+ err = -ENOENT;
+ goto out_eacces;
+ }
/* save current_cred and override it */
OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
@@ -159,6 +214,11 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
dget(lower_dentry);
lower_dir_dentry = lock_parent(lower_dentry);
+ err = mnt_want_write(lower_path.mnt);
+ if (err)
+ goto out_unlock;
+
+ sdcardfs_drop_shared_icache(dir->i_sb, lower_dentry->d_inode);
err = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
/*
@@ -179,6 +239,8 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_ctime = dir->i_ctime;
d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */
out:
+ mnt_drop_write(lower_path.mnt);
+out_unlock:
unlock_dir(lower_dir_dentry);
dput(lower_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
@@ -187,11 +249,46 @@ out_eacces:
return err;
}
+/* drop all shared dentries from other superblocks */
+void sdcardfs_drop_sb_icache(struct super_block *sb, unsigned long ino)
+{
+ struct inode *inode = ilookup(sb, ino);
+ struct dentry *dentry, *dir_dentry;
+
+ if (!inode)
+ return;
+
+ dentry = d_find_any_alias(inode);
+
+ if (!dentry) {
+ iput(inode);
+ return;
+ }
+
+ dir_dentry = lock_parent(dentry);
+
+ mutex_lock(&inode->i_mutex);
+ set_nlink(inode, sdcardfs_lower_inode(inode)->i_nlink);
+ d_drop(dentry);
+ dont_mount(dentry);
+ mutex_unlock(&inode->i_mutex);
+
+ /* We don't d_delete() NFS sillyrenamed files--they still exist. */
+ if (!(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
+ fsnotify_link_count(inode);
+ d_delete(dentry);
+ }
+
+ unlock_dir(dir_dentry);
+ dput(dentry);
+ iput(inode);
+}
+
#if 0
static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname)
{
- int err;
+ int err = 0;
struct dentry *lower_dentry;
struct dentry *lower_parent_dentry = NULL;
struct path lower_path;
@@ -202,6 +299,9 @@ static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry,
lower_dentry = lower_path.dentry;
lower_parent_dentry = lock_parent(lower_dentry);
+ err = mnt_want_write(lower_path.mnt);
+ if (err)
+ goto out_unlock;
err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
if (err)
goto out;
@@ -212,6 +312,8 @@ static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry,
fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
out:
+ mnt_drop_write(lower_path.mnt);
+out_unlock:
unlock_dir(lower_parent_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
REVERT_CRED();
@@ -221,8 +323,10 @@ out:
static int touch(char *abs_path, mode_t mode) {
struct file *filp = filp_open(abs_path, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, mode);
+ SDFS_DBG("abs_path='%s' \n", abs_path);
if (IS_ERR(filp)) {
if (PTR_ERR(filp) == -EEXIST) {
+ SDFS_DBG("EEXIST, abs_path='%s' \n", abs_path);
return 0;
}
else {
@@ -237,7 +341,7 @@ static int touch(char *abs_path, mode_t mode) {
static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
- int err;
+ int err = 0;
int make_nomedia_in_obb = 0;
struct dentry *lower_dentry;
struct dentry *lower_parent_dentry = NULL;
@@ -250,17 +354,28 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
char *nomedia_fullpath;
int fullpath_namelen;
int touch_err = 0;
+ int mask = 0;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
+ SDFS_DBG("dentry='%s' parent='%s' \n",dentry->d_name.name,dentry->d_parent->d_name.name);
+ if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
err = -EACCES;
goto out_eacces;
}
+ if (sbi->flag && SDCARDFS_MOUNT_ACCESS_DISABLE) {
+ SDFS_DBG("sdcardfs_mkdir access disable\n");
+ err = -ENOENT;
+ goto out_eacces;
+ }
+
/* save current_cred and override it */
OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
+ /* clear the umask so that the lower mode works for create cases */
+ mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
/* check disk space */
if (!check_min_free_space(dentry, 0, 1)) {
@@ -274,42 +389,64 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
lower_dentry = lower_path.dentry;
lower_parent_dentry = lock_parent(lower_dentry);
+ err = mnt_want_write(lower_path.mnt);
+ if (err) {
+ unlock_dir(lower_parent_dentry);
+ goto out_unlock;
+ }
+
/* set last 16bytes of mode field to 0775 */
- mode = (mode & S_IFMT) | 00775;
+ mode = (mode & S_IFMT) | 00775;
err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode);
- if (err)
+ if (err) {
+ unlock_dir(lower_parent_dentry);
goto out;
+ }
/* if it is a local obb dentry, setup it with the base obbpath */
if(need_graft_path(dentry)) {
err = setup_obb_dentry(dentry, &lower_path);
if(err) {
- /* if the sbi->obbpath is not available, the lower_path won't be
- * changed by setup_obb_dentry() but the lower path is saved to
- * its orig_path. this dentry will be revalidated later.
+ /* if the sbi->obbpath is not available, the lower_path won't be
+ * changed by setup_obb_dentry() but the lower path is saved to
+ * its orig_path. this dentry will be revalidated later.
* but now, the lower_path should be NULL */
sdcardfs_put_reset_lower_path(dentry);
/* the newly created lower path which saved to its orig_path or
- * the lower_path is the base obbpath.
- * therefore, an additional path_get is required */
+ * the lower_path is the base obbpath.
+ * therefore, an additional path_get is required */
path_get(&lower_path);
} else
make_nomedia_in_obb = 1;
}
- err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pi->userid);
- if (err)
+ /* Secure Zone panzh2 hack the OpenUserData for Secure zone */
+ if(is_secure_openuserdata_path(dentry)) {
+ err = setup_secure_openuserdata_dentry(dentry, &lower_path);
+
+ if(err) {
+ sdcardfs_put_reset_lower_path(dentry);
+ path_get(&lower_path);
+ }
+ }
+
+ err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
+ if (err) {
+ unlock_dir(lower_parent_dentry);
goto out;
+ }
fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
/* update number of links on parent directory */
set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink);
- if ((!sbi->options.multiuser) && (!strcasecmp(dentry->d_name.name, "obb"))
+ unlock_dir(lower_parent_dentry);
+
+ if ((sbi->options.derive == DERIVE_UNIFIED) && (!strcasecmp(dentry->d_name.name, "obb"))
&& (pi->perm == PERM_ANDROID) && (pi->userid == 0))
make_nomedia_in_obb = 1;
@@ -352,10 +489,14 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
kfree(nomedia_fullpath);
}
out:
- unlock_dir(lower_parent_dentry);
+ mnt_drop_write(lower_path.mnt);
+out_unlock:
sdcardfs_put_lower_path(dentry, &lower_path);
out_revert:
REVERT_CRED(saved_cred);
+ /* restore the old umask */
+ if (mask)
+ mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
out_eacces:
return err;
}
@@ -366,10 +507,14 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
struct dentry *lower_dir_dentry;
int err;
struct path lower_path;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
const struct cred *saved_cred = NULL;
+ //char *path_s = NULL;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
+ SDFS_DBG("dentry='%s' parent='%s' \n",dentry->d_name.name,dentry->d_parent->d_name.name);
+ if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
err = -EACCES;
@@ -379,13 +524,18 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
/* save current_cred and override it */
OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred);
- /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry
+ /* sdcardfs_get_real_lower(): in case of remove an user's obb dentry
* the dentry on the original path should be deleted. */
sdcardfs_get_real_lower(dentry, &lower_path);
lower_dentry = lower_path.dentry;
lower_dir_dentry = lock_parent(lower_dentry);
+ err = mnt_want_write(lower_path.mnt);
+ if (err)
+ goto out_unlock;
+
+ sdcardfs_drop_shared_icache(dir->i_sb, lower_dentry->d_inode);
err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
if (err)
goto out;
@@ -398,6 +548,8 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
out:
+ mnt_drop_write(lower_path.mnt);
+out_unlock:
unlock_dir(lower_dir_dentry);
sdcardfs_put_real_lower(dentry, &lower_path);
REVERT_CRED(saved_cred);
@@ -409,7 +561,7 @@ out_eacces:
static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
dev_t dev)
{
- int err;
+ int err = 0;
struct dentry *lower_dentry;
struct dentry *lower_parent_dentry = NULL;
struct path lower_path;
@@ -420,6 +572,9 @@ static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode
lower_dentry = lower_path.dentry;
lower_parent_dentry = lock_parent(lower_dentry);
+ err = mnt_want_write(lower_path.mnt);
+ if (err)
+ goto out_unlock;
err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
if (err)
goto out;
@@ -431,6 +586,8 @@ static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode
fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
out:
+ mnt_drop_write(lower_path.mnt);
+out_unlock:
unlock_dir(lower_parent_dentry);
sdcardfs_put_lower_path(dentry, &lower_path);
REVERT_CRED();
@@ -453,17 +610,28 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *trap = NULL;
struct dentry *new_parent = NULL;
struct path lower_old_path, lower_new_path;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(old_dentry->d_sb);
const struct cred *saved_cred = NULL;
- if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name) ||
- !check_caller_access_to_name(new_dir, new_dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
+ SDFS_DBG("old_dentry='%s' new_dentry='%s' \n",old_dentry->d_name.name, new_dentry->d_parent->d_name.name);
+ if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name,
+ sbi->options.derive, 1, has_rw) ||
+ !check_caller_access_to_name(new_dir, new_dentry->d_name.name,
+ sbi->options.derive, 1, has_rw)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" new_dentry: %s, task:%s\n",
__func__, new_dentry->d_name.name, current->comm);
err = -EACCES;
goto out_eacces;
}
+ if (sbi->flag && SDCARDFS_MOUNT_ACCESS_DISABLE) {
+ SDFS_DBG("sdcardfs_rename access disable\n");
+ err = -ENOENT;
+ goto out_eacces;
+ }
+
/* save current_cred and override it */
OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred);
@@ -486,38 +654,43 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out;
}
- err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
- lower_new_dir_dentry->d_inode, lower_new_dentry,
- NULL, 0);
+ err = mnt_want_write(lower_old_path.mnt);
if (err)
goto out;
+ err = mnt_want_write(lower_new_path.mnt);
+ if (err)
+ goto out_drop_old_write;
+
+ err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
+ lower_new_dir_dentry->d_inode, lower_new_dentry, NULL, 0);
+ if (err)
+ goto out_err;
/* Copy attrs from lower dir, but i_uid/i_gid */
- sdcardfs_copy_and_fix_attrs(new_dir, lower_new_dir_dentry->d_inode);
+ sdcardfs_copy_inode_attr(new_dir, lower_new_dir_dentry->d_inode);
fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
-
+ fix_derived_permission(new_dir);
if (new_dir != old_dir) {
- sdcardfs_copy_and_fix_attrs(old_dir, lower_old_dir_dentry->d_inode);
+ sdcardfs_copy_inode_attr(old_dir, lower_old_dir_dentry->d_inode);
fsstack_copy_inode_size(old_dir, lower_old_dir_dentry->d_inode);
-
+ fix_derived_permission(old_dir);
/* update the derived permission of the old_dentry
* with its new parent
*/
new_parent = dget_parent(new_dentry);
if(new_parent) {
if(old_dentry->d_inode) {
- update_derived_permission_lock(old_dentry);
+ get_derived_permission(new_parent, old_dentry);
+ fix_derived_permission(old_dentry->d_inode);
}
dput(new_parent);
}
}
- /* At this point, not all dentry information has been moved, so
- * we pass along new_dentry for the name.*/
- mutex_lock(&old_dentry->d_inode->i_mutex);
- get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry);
- fix_derived_permission(old_dentry->d_inode);
- get_derive_permissions_recursive(old_dentry);
- mutex_unlock(&old_dentry->d_inode->i_mutex);
+
+out_err:
+ mnt_drop_write(lower_new_path.mnt);
+out_drop_old_write:
+ mnt_drop_write(lower_old_path.mnt);
out:
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
dput(lower_old_dir_dentry);
@@ -588,30 +761,41 @@ out:
}
#endif
+#if 0
+/* this @nd *IS* still used */
+static void sdcardfs_put_link(struct dentry *dentry, struct nameidata *nd,
+ void *cookie)
+{
+ char *buf = nd_get_link(nd);
+ if (!IS_ERR(buf)) /* free the char* */
+ kfree(buf);
+}
+#endif
+
static int sdcardfs_permission(struct inode *inode, int mask)
{
int err;
/*
* Permission check on sdcardfs inode.
- * Calling process should have AID_SDCARD_RW permission
+ * Calling process should have AID_SDCARD_RW permission
*/
err = generic_permission(inode, mask);
- /* XXX
+ /* XXX
* Original sdcardfs code calls inode_permission(lower_inode,.. )
* for checking inode permission. But doing such things here seems
- * duplicated work, because the functions called after this func,
- * such as vfs_create, vfs_unlink, vfs_rename, and etc,
- * does exactly same thing, i.e., they calls inode_permission().
- * So we just let they do the things.
- * If there are any security hole, just uncomment following if block.
+ * duplicated work, because the functions called after this func,
+ * such as vfs_create, vfs_unlink, vfs_rename, and etc,
+ * does exactly same thing, i.e., they calls inode_permission().
+ * So we just let they do the things.
+ * If there are any security hole, just uncomment following if block.
*/
#if 0
if (!err) {
- /*
- * Permission check on lower_inode(=EXT4).
- * we check it with AID_MEDIA_RW permission
+ /*
+ * Permission check on lower_inode(=EXT4).
+ * we check it with AID_MEDIA_RW permission
*/
struct inode *lower_inode;
OVERRIDE_CRED(SDCARDFS_SB(inode->sb));
@@ -622,19 +806,84 @@ static int sdcardfs_permission(struct inode *inode, int mask)
REVERT_CRED();
}
#endif
- return err;
+ return err;
}
+static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct dentry *lower_dentry;
+ struct inode *inode;
+ struct inode *lower_inode;
+ struct path lower_path;
+ struct dentry *parent;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+ const struct cred *saved_cred;
+
+ if (sbi->flag && SDCARDFS_MOUNT_ACCESS_DISABLE) {
+ SDFS_DBG("sdcardfs_getattr access disable\n");
+ return -ENOENT;
+ }
+
+ OVERRIDE_CRED(sbi, saved_cred);
+
+ SDFS_DBG("dentry='%s' parent='%s' \n",dentry->d_name.name,dentry->d_parent->d_name.name);
+ parent = dget_parent(dentry);
+ if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name,
+ sbi->options.derive, 0, 0)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ " dentry: %s, task:%s\n",
+ __func__, dentry->d_name.name, current->comm);
+ dput(parent);
+ return -EACCES;
+ }
+ dput(parent);
+
+ inode = dentry->d_inode;
+
+ sdcardfs_get_lower_path(dentry, &lower_path);
+ lower_dentry = lower_path.dentry;
+ lower_inode = sdcardfs_lower_inode(inode);
+
+ /* need to get inode->i_mutex */
+ mutex_lock(&inode->i_mutex); //2015.01.04 merge from Nxx50
+ sdcardfs_copy_inode_attr(inode, lower_inode);
+ fsstack_copy_inode_size(inode, lower_inode);
+ /* if the dentry has been moved from other location
+ * so, on this stage, its derived permission must be
+ * rechecked from its private field.
+ */
+ update_derived_permission(dentry);
+ mutex_unlock(&inode->i_mutex); //2015.01.04 merge from Nxx50
+
+ generic_fillattr(inode, stat);
+ sdcardfs_put_lower_path(dentry, &lower_path);
+
+ REVERT_CRED(saved_cred);
+ return 0;
+}
+
static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
{
- int err;
+ int err = 0;
struct dentry *lower_dentry;
struct inode *inode;
struct inode *lower_inode;
struct path lower_path;
struct iattr lower_ia;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
struct dentry *parent;
+ int has_rw;
+ const struct cred *saved_cred;
+
+ SDFS_DBG("dentry='%s' parent='%s' \n",dentry->d_name.name,dentry->d_parent->d_name.name);
+
+ if (sbi->flag && SDCARDFS_MOUNT_ACCESS_DISABLE) {
+ SDFS_DBG("sdcardfs_setattr access disable\n");
+ err = -ENOENT;
+ goto out_err;
+ }
inode = dentry->d_inode;
@@ -648,19 +897,23 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
/* no vfs_XXX operations required, cred overriding will be skipped. wj*/
if (!err) {
/* check the Android group ID */
+ has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
parent = dget_parent(dentry);
- if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
+ if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name,
+ sbi->options.derive, 1, has_rw)) {
+ printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
err = -EACCES;
}
dput(parent);
- }
+ }
if (err)
goto out_err;
+ OVERRIDE_CRED(sbi, saved_cred);
+
sdcardfs_get_lower_path(dentry, &lower_path);
lower_dentry = lower_path.dentry;
lower_inode = sdcardfs_lower_inode(inode);
@@ -680,16 +933,23 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
* afterwards in the other cases: we fsstack_copy_inode_size from
* the lower level.
*/
+ /*lenovo-sw jixj remove begin, confict with binder.c and happen to dead lock*/
+ #if 0
if (current->mm)
down_write(&current->mm->mmap_sem);
+ #endif
if (ia->ia_valid & ATTR_SIZE) {
err = inode_newsize_ok(inode, ia->ia_size);
if (err) {
+ /*lenovo-sw jixj remove begin, confict with binder.c and happen to dead lock*/
+ #if 0
if (current->mm)
up_write(&current->mm->mmap_sem);
+ #endif
goto out;
}
truncate_setsize(inode, ia->ia_size);
+ sdcardfs_truncate_share(inode->i_sb, lower_dentry->d_inode, ia->ia_size);
}
/*
@@ -706,17 +966,21 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
* tries to open(), unlink(), then ftruncate() a file.
*/
mutex_lock(&lower_dentry->d_inode->i_mutex);
- err = notify_change(lower_dentry, &lower_ia, /* note: lower_ia */
- NULL);
+ err = notify_change(lower_dentry, &lower_ia, NULL); /* note: lower_ia */
mutex_unlock(&lower_dentry->d_inode->i_mutex);
+ /*lenovo-sw jixj remove begin, confict with binder.c and happen to dead lock*/
+ #if 0
if (current->mm)
up_write(&current->mm->mmap_sem);
+ #endif
if (err)
goto out;
- /* get attributes from the lower inode and update derived permissions */
- sdcardfs_copy_and_fix_attrs(inode, lower_inode);
-
+ /* get attributes from the lower inode, i_mutex held */
+ sdcardfs_copy_inode_attr(inode, lower_inode);
+ /* update derived permission of the upper inode */
+ fix_derived_permission(inode);
+
/*
* Not running fsstack_copy_inode_size(inode, lower_inode), because
* VFS should update our inode size, and notify_change on
@@ -725,80 +989,66 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
out:
sdcardfs_put_lower_path(dentry, &lower_path);
+
+ REVERT_CRED(saved_cred);
out_err:
return err;
}
-static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
-{
- struct dentry *lower_dentry;
- struct inode *inode;
- struct inode *lower_inode;
- struct path lower_path;
- struct dentry *parent;
-
- parent = dget_parent(dentry);
- if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) {
- printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
- " dentry: %s, task:%s\n",
- __func__, dentry->d_name.name, current->comm);
- dput(parent);
- return -EACCES;
- }
- dput(parent);
-
- inode = dentry->d_inode;
-
- sdcardfs_get_lower_path(dentry, &lower_path);
- lower_dentry = lower_path.dentry;
- lower_inode = sdcardfs_lower_inode(inode);
-
-
- sdcardfs_copy_and_fix_attrs(inode, lower_inode);
- fsstack_copy_inode_size(inode, lower_inode);
-
-
- generic_fillattr(inode, stat);
- sdcardfs_put_lower_path(dentry, &lower_path);
- return 0;
-}
-
const struct inode_operations sdcardfs_symlink_iops = {
.permission = sdcardfs_permission,
.setattr = sdcardfs_setattr,
- /* XXX Following operations are implemented,
+//2015.01.04 merge from latest wrapfs & Nxx50
+#ifdef SDCARD_FS_XATTR
+ .setxattr = sdcardfs_setxattr,
+ .getxattr = sdcardfs_getxattr,
+ .listxattr = sdcardfs_listxattr,
+ .removexattr = sdcardfs_removexattr,
+#endif // SDCARD_FS_XATTR
+ /* XXX Following operations are implemented,
* but FUSE(sdcard) or FAT does not support them
- * These methods are *NOT* perfectly tested.
- .readlink = sdcardfs_readlink,
- .follow_link = sdcardfs_follow_link,
- .put_link = kfree_put_link,
+ * These methods are *NOT* perfectly tested.
+ .readlink = sdcardfs_readlink,
+ .follow_link = sdcardfs_follow_link,
+ .put_link = sdcardfs_put_link,
*/
};
const struct inode_operations sdcardfs_dir_iops = {
.create = sdcardfs_create,
.lookup = sdcardfs_lookup,
-#if 0
.permission = sdcardfs_permission,
-#endif
.unlink = sdcardfs_unlink,
.mkdir = sdcardfs_mkdir,
.rmdir = sdcardfs_rmdir,
.rename = sdcardfs_rename,
.setattr = sdcardfs_setattr,
.getattr = sdcardfs_getattr,
- /* XXX Following operations are implemented,
+//2015.01.04 merge from latest wrapfs & Nxx50
+#ifdef SDCARD_FS_XATTR
+ .setxattr = sdcardfs_setxattr,
+ .getxattr = sdcardfs_getxattr,
+ .listxattr = sdcardfs_listxattr,
+ .removexattr = sdcardfs_removexattr,
+#endif // SDCARD_FS_XATTR
+ /* XXX Following operations are implemented,
* but FUSE(sdcard) or FAT does not support them
- * These methods are *NOT* perfectly tested.
- .symlink = sdcardfs_symlink,
- .link = sdcardfs_link,
- .mknod = sdcardfs_mknod,
+ * These methods are *NOT* perfectly tested.
+ .symlink = sdcardfs_symlink,
+ .link = sdcardfs_link,
+ .mknod = sdcardfs_mknod,
*/
};
const struct inode_operations sdcardfs_main_iops = {
- .permission = sdcardfs_permission,
- .setattr = sdcardfs_setattr,
+ .permission = sdcardfs_permission,
+ .setattr = sdcardfs_setattr,
.getattr = sdcardfs_getattr,
+//2015.01.04 merge from latest wrapfs & Nxx50
+#ifdef SDCARD_FS_XATTR
+ .setxattr = sdcardfs_setxattr,
+ .getxattr = sdcardfs_getxattr,
+ .listxattr = sdcardfs_listxattr,
+ .removexattr = sdcardfs_removexattr,
+#endif // SDCARDFS_XATTR
};