diff --git a/fs/Kconfig b/fs/Kconfig index fbdf8fde8164..0199590b8a84 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -17,7 +17,6 @@ if BLOCK source "fs/ext2/Kconfig" source "fs/ext3/Kconfig" source "fs/ext4/Kconfig" -source "fs/sdcardfs/Kconfig" config FS_XIP # execute in place diff --git a/fs/Makefile b/fs/Makefile index 27dbd361640d..a47599a09f6a 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -69,7 +69,6 @@ obj-$(CONFIG_EXT2_FS) += ext2/ # We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 # unless explicitly requested by rootfstype obj-$(CONFIG_EXT4_FS) += ext4/ -obj-$(CONFIG_SDCARD_FS) += sdcardfs/ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_CRAMFS) += cramfs/ diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 766694d6b6f8..7ec6f170445b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2215,12 +2215,7 @@ extern int search_dir(struct buffer_head *bh, struct inode *dir, const struct qstr *d_name, unsigned int offset, -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - struct ext4_dir_entry_2 **res_dir, - char *ci_name_buf); -#else struct ext4_dir_entry_2 **res_dir); -#endif extern int ext4_generic_delete_entry(handle_t *handle, struct inode *dir, struct ext4_dir_entry_2 *de_del, diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 2cdd59a02c30..e350be6c7ac6 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1640,13 +1640,8 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, inline_start = (void *)ext4_raw_inode(&iloc)->i_block + EXT4_INLINE_DOTDOT_SIZE; inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - ret = search_dir(iloc.bh, inline_start, inline_size, - dir, d_name, 0, res_dir, NULL); -#else ret = search_dir(iloc.bh, inline_start, inline_size, dir, d_name, 0, res_dir); -#endif if (ret == 1) goto out_find; if (ret < 0) @@ -1658,13 +1653,8 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir, inline_start = ext4_get_inline_xattr_pos(dir, &iloc); inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - ret = search_dir(iloc.bh, inline_start, inline_size, - dir, d_name, 0, res_dir, NULL); -#else ret = search_dir(iloc.bh, inline_start, inline_size, dir, d_name, 0, res_dir); -#endif if (ret == 1) goto out_find; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 877afc4ff9f2..4c1e100c56c3 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -30,10 +30,6 @@ #include #include #include -#ifdef CONFIG_SDCARD_FS_CI_SEARCH -#include -#include -#endif #include #include #include @@ -1049,20 +1045,11 @@ static inline int search_dirblock(struct buffer_head *bh, struct inode *dir, const struct qstr *d_name, unsigned int offset, -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - struct ext4_dir_entry_2 ** res_dir, - char *ci_name_buf) -{ - return search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir, - d_name, offset, res_dir, ci_name_buf); -} -#else struct ext4_dir_entry_2 ** res_dir) { return search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir, d_name, offset, res_dir); } -#endif /* * Directory block splitting, compacting @@ -1153,18 +1140,6 @@ static inline int ext4_match (int len, const char * const name, return !memcmp(name, de->name, len); } -#ifdef CONFIG_SDCARD_FS_CI_SEARCH -static inline int ext4_ci_match (int len, const char * const name, - struct ext4_dir_entry_2 * de) -{ - if (len != de->name_len) - return 0; - if (!de->inode) - return 0; - return !strncasecmp(name, de->name, len); -} -#endif - /* * Returns 0 if not found, -1 on failure, and 1 on success */ @@ -1174,12 +1149,7 @@ int search_dir(struct buffer_head *bh, struct inode *dir, const struct qstr *d_name, unsigned int offset, -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - struct ext4_dir_entry_2 **res_dir, - char *ci_name_buf) -#else struct ext4_dir_entry_2 **res_dir) -#endif { struct ext4_dir_entry_2 * de; char * dlimit; @@ -1193,31 +1163,6 @@ int search_dir(struct buffer_head *bh, /* this code is executed quadratically often */ /* do minimal checking `by hand' */ -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - if ((char *) de + namelen <= dlimit) { - if (ci_name_buf) { - if (ext4_ci_match (namelen, name, de)) { - /* found a match - just to be sure, do a full check */ - if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, - bh->b_size, offset)) - return -1; - *res_dir = de; - memcpy(ci_name_buf, de->name, namelen); - ci_name_buf[namelen] = '\0'; - return 1; - } - } else { - if (ext4_match (namelen, name, de)) { - /* found a match - just to be sure, do a full check */ - if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data, - bh->b_size, offset)) - return -1; - *res_dir = de; - return 1; - } - } - } -#else if ((char *) de + namelen <= dlimit && ext4_match (namelen, name, de)) { /* found a match - just to be sure, do a full check */ @@ -1227,7 +1172,7 @@ int search_dir(struct buffer_head *bh, *res_dir = de; return 1; } -#endif + /* prevent looping on a bad block */ de_len = ext4_rec_len_from_disk(de->rec_len, dir->i_sb->s_blocksize); @@ -1269,12 +1214,7 @@ static int is_dx_internal_node(struct inode *dir, ext4_lblk_t block, static struct buffer_head * ext4_find_entry (struct inode *dir, const struct qstr *d_name, struct ext4_dir_entry_2 **res_dir, -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - int *inlined, - char *ci_name_buf) -#else int *inlined) -#endif { struct super_block *sb; struct buffer_head *bh_use[NAMEI_RA_SIZE]; @@ -1382,14 +1322,8 @@ restart: goto next; } set_buffer_verified(bh); -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - i = search_dirblock(bh, dir, d_name, - block << EXT4_BLOCK_SIZE_BITS(sb), res_dir, - ci_name_buf); -#else i = search_dirblock(bh, dir, d_name, block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); -#endif if (i == 1) { EXT4_I(dir)->i_dir_start_lookup = block; ret = bh; @@ -1441,15 +1375,9 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q *err = PTR_ERR(bh); goto errout; } -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - retval = search_dirblock(bh, dir, d_name, - block << EXT4_BLOCK_SIZE_BITS(sb), - res_dir, NULL); -#else retval = search_dirblock(bh, dir, d_name, block << EXT4_BLOCK_SIZE_BITS(sb), res_dir); -#endif if (retval == 1) { /* Success! */ dx_release(frames); return bh; @@ -1484,23 +1412,11 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi struct inode *inode; struct ext4_dir_entry_2 *de; struct buffer_head *bh; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - struct qstr ci_name; - char ci_name_buf[EXT4_NAME_LEN+1]; -#endif if (dentry->d_name.len > EXT4_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - ci_name_buf[0] = '\0'; - if (flags & LOOKUP_CASE_INSENSITIVE) - bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, ci_name_buf); - else - bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, NULL); -#else bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); -#endif inode = NULL; if (bh) { __u32 ino = le32_to_cpu(de->inode); @@ -1530,16 +1446,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi return ERR_PTR(-EIO); } } -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - if (ci_name_buf[0] != '\0') { - ci_name.name = ci_name_buf; - ci_name.len = dentry->d_name.len; - return d_add_ci(dentry, inode, &ci_name); - } else - return d_splice_alias(inode, dentry); -#else return d_splice_alias(inode, dentry); -#endif } @@ -1550,11 +1457,7 @@ struct dentry *ext4_get_parent(struct dentry *child) struct ext4_dir_entry_2 * de; struct buffer_head *bh; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL, NULL); -#else bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL); -#endif if (!bh) return ERR_PTR(-ENOENT); ino = le32_to_cpu(de->inode); @@ -2776,11 +2679,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) dquot_initialize(dentry->d_inode); retval = -ENOENT; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, NULL); -#else bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); -#endif if (!bh) goto end_rmdir; @@ -2847,11 +2746,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) dquot_initialize(dentry->d_inode); retval = -ENOENT; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL, NULL); -#else bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL); -#endif if (!bh) goto end_unlink; @@ -3116,11 +3011,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir)) ext4_handle_sync(handle); -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL, NULL); -#else old_bh = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de, NULL); -#endif /* * Check for inode number is _not_ due to possible IO errors. * We might rmdir the source, keep it as pwd of some process @@ -3133,13 +3024,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, goto end_rename; new_inode = new_dentry->d_inode; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - new_bh = ext4_find_entry(new_dir, &new_dentry->d_name, - &new_de, &new_inlined, NULL); -#else new_bh = ext4_find_entry(new_dir, &new_dentry->d_name, &new_de, &new_inlined); -#endif if (new_bh) { if (!new_inode) { brelse(new_bh); @@ -3221,13 +3107,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, struct buffer_head *old_bh2; struct ext4_dir_entry_2 *old_de2; -#ifdef CONFIG_SDCARD_FS_CI_SEARCH - old_bh2 = ext4_find_entry(old_dir, &old_dentry->d_name, - &old_de2, NULL, NULL); -#else old_bh2 = ext4_find_entry(old_dir, &old_dentry->d_name, &old_de2, NULL); -#endif if (old_bh2) { retval = ext4_delete_entry(handle, old_dir, old_de2, old_bh2); diff --git a/fs/namei.c b/fs/namei.c index ae466b4d1ac5..ef8aa5021db1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -473,24 +473,6 @@ void path_put(const struct path *path) } EXPORT_SYMBOL(path_put); -/** - * path_connected - Verify that a path->dentry is below path->mnt.mnt_root - * @path: nameidate to verify - * - * Rename can sometimes move a file or directory outside of a bind - * mount, path_connected allows those cases to be detected. - */ -static bool path_connected(const struct path *path) -{ - struct vfsmount *mnt = path->mnt; - - /* Only bind mounts can have disconnected paths */ - if (mnt->mnt_root == mnt->mnt_sb->s_root) - return true; - - return is_subdir(path->dentry, mnt->mnt_root); -} - /* * Path walking has 2 modes, rcu-walk and ref-walk (see * Documentation/filesystems/path-lookup.txt). In situations when we can't @@ -1166,8 +1148,6 @@ static int follow_dotdot_rcu(struct nameidata *nd) goto failed; nd->path.dentry = parent; nd->seq = seq; - if (unlikely(!path_connected(&nd->path))) - goto failed; break; } if (!follow_up_rcu(&nd->path)) @@ -1251,7 +1231,7 @@ static void follow_mount(struct path *path) } } -static int follow_dotdot(struct nameidata *nd) +static void follow_dotdot(struct nameidata *nd) { set_root(nd); @@ -1266,10 +1246,6 @@ static int follow_dotdot(struct nameidata *nd) /* rare case of legitimate dget_parent()... */ nd->path.dentry = dget_parent(nd->path.dentry); dput(old); - if (unlikely(!path_connected(&nd->path))) { - path_put(&nd->path); - return -ENOENT; - } break; } if (!follow_up(&nd->path)) @@ -1277,7 +1253,6 @@ static int follow_dotdot(struct nameidata *nd) } follow_mount(&nd->path); nd->inode = nd->path.dentry->d_inode; - return 0; } /* @@ -1501,7 +1476,7 @@ static inline int handle_dots(struct nameidata *nd, int type) if (follow_dotdot_rcu(nd)) return -ECHILD; } else - return follow_dotdot(nd); + follow_dotdot(nd); } return 0; } @@ -2932,10 +2907,6 @@ opened: goto exit_fput; } out: - if (unlikely(error > 0)) { - WARN_ON(1); - error = -EINVAL; - } if (got_write) mnt_drop_write(nd->path.mnt); path_put(&save_parent); @@ -3384,8 +3355,6 @@ static long do_rmdir(int dfd, const char __user *pathname) struct dentry *dentry; struct nameidata nd; unsigned int lookup_flags = 0; - char *path_buf = NULL; - char *propagate_path = NULL; retry: name = user_path_parent(dfd, pathname, &nd, lookup_flags); if (IS_ERR(name)) @@ -3420,23 +3389,11 @@ retry: error = security_path_rmdir(&nd.path, dentry); if (error) goto exit3; - if (nd.path.dentry->d_sb->s_op->unlink_callback) { - path_buf = kmalloc(PATH_MAX, GFP_KERNEL); - propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX); - } error = vfs_rmdir(nd.path.dentry->d_inode, dentry); exit3: dput(dentry); exit2: mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - if (path_buf && !error) { - nd.path.dentry->d_sb->s_op->unlink_callback(nd.path.dentry->d_sb, - propagate_path); - } - if (path_buf) { - kfree(path_buf); - path_buf = NULL; - } mnt_drop_write(nd.path.mnt); exit1: path_put(&nd.path); @@ -3499,8 +3456,6 @@ static long do_unlinkat(int dfd, const char __user *pathname) struct nameidata nd; struct inode *inode = NULL; unsigned int lookup_flags = 0; - char *path_buf = NULL; - char *propagate_path = NULL; retry: name = user_path_parent(dfd, pathname, &nd, lookup_flags); if (IS_ERR(name)) @@ -3525,10 +3480,6 @@ retry: inode = dentry->d_inode; if (!inode) goto slashes; - if (inode->i_sb->s_op->unlink_callback) { - path_buf = kmalloc(PATH_MAX, GFP_KERNEL); - propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX); - } ihold(inode); error = security_path_unlink(&nd.path, dentry); if (error) @@ -3538,13 +3489,6 @@ exit2: dput(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - if (path_buf && !error) { - inode->i_sb->s_op->unlink_callback(inode->i_sb, propagate_path); - } - if (path_buf) { - kfree(path_buf); - path_buf = NULL; - } if (inode) iput(inode); /* truncate the inode here */ mnt_drop_write(nd.path.mnt); diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index fce2b8502237..959815c1e017 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -738,8 +738,6 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, struct fsnotify_group *group; struct inode *inode; struct path path; - struct path alteredpath; - struct path *canonical_path = &path; struct fd f; int ret; unsigned flags = 0; @@ -767,22 +765,13 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, if (ret) goto fput_and_out; - /* support stacked filesystems */ - if(path.dentry && path.dentry->d_op) { - if (path.dentry->d_op->d_canonical_path) { - path.dentry->d_op->d_canonical_path(&path, &alteredpath); - canonical_path = &alteredpath; - path_put(&path); - } - } - /* inode held in place by reference to path; group by fget on fd */ - inode = canonical_path->dentry->d_inode; + inode = path.dentry->d_inode; group = f.file->private_data; /* create/update an inode mark */ ret = inotify_update_watch(group, inode, mask); - path_put(canonical_path); + path_put(&path); fput_and_out: fdput(f); return ret; diff --git a/fs/sdcardfs/Kconfig b/fs/sdcardfs/Kconfig deleted file mode 100644 index d1b1af1562e2..000000000000 --- a/fs/sdcardfs/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -config SDCARD_FS - tristate "sdcard file system" - default y - help - Sdcardfs is based on Wrapfs file system. - -config SDCARD_FS_FADV_NOACTIVE - bool "sdcardfs fadvise noactive support" - depends on FADV_NOACTIVE - default y - help - Sdcardfs supports fadvise noactive mode. - -config SDCARD_FS_CI_SEARCH - tristate "sdcardfs case-insensitive search support" - depends on SDCARD_FS - default y - -config SDCARD_FS_XATTR - bool "Sdcardfs extended attribute" - default y - depends on SDCARD_FS - help - Modification of sdcard file system for xattr diff --git a/fs/sdcardfs/Makefile b/fs/sdcardfs/Makefile deleted file mode 100644 index 8f6ac296f8bd..000000000000 --- a/fs/sdcardfs/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -ifeq ($(CONFIG_SDCARD_FS_XATTR),y) -EXTRA_CFLAGS += -DSDCARD_FS_XATTR -endif - -obj-$(CONFIG_SDCARD_FS) += sdcardfs.o - -sdcardfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o packagelist.o derived_perm.o -sdcardfs-$(CONFIG_SDCARD_FS_XATTR) += xattr.o diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c deleted file mode 100644 index 9460f62b3121..000000000000 --- a/fs/sdcardfs/dentry.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * fs/sdcardfs/dentry.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" -#include "linux/ctype.h" - -/* - * returns: -ERRNO if error (returned to user) - * 0: tell VFS to invalidate dentry - * 1: dentry is valid - */ -static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) -{ - int err = 1; - struct path parent_lower_path, lower_path; - struct dentry *parent_dentry = NULL; - struct dentry *parent_lower_dentry = NULL; - struct dentry *lower_cur_parent_dentry = NULL; - struct dentry *lower_dentry = NULL; - - if (flags & LOOKUP_RCU) - return -ECHILD; - - spin_lock(&dentry->d_lock); - if (IS_ROOT(dentry)) { - spin_unlock(&dentry->d_lock); - return 1; - } - if (dentry->d_flags & DCACHE_WILL_INVALIDATE) { - dentry->d_flags &= ~DCACHE_WILL_INVALIDATE; - __d_drop(dentry); - spin_unlock(&dentry->d_lock); - return 0; - } - spin_unlock(&dentry->d_lock); - - /* check uninitialized obb_dentry and - * whether the base obbpath has been changed or not */ - if (is_obbpath_invalid(dentry)) { - d_drop(dentry); - return 0; - } - - parent_dentry = dget_parent(dentry); - sdcardfs_get_lower_path(parent_dentry, &parent_lower_path); - sdcardfs_get_real_lower(dentry, &lower_path); - parent_lower_dentry = parent_lower_path.dentry; - lower_dentry = lower_path.dentry; - lower_cur_parent_dentry = dget_parent(lower_dentry); - - spin_lock(&lower_dentry->d_lock); - if (d_unhashed(lower_dentry)) { - spin_unlock(&lower_dentry->d_lock); - d_drop(dentry); - err = 0; - goto out; - } - spin_unlock(&lower_dentry->d_lock); - - if (parent_lower_dentry != lower_cur_parent_dentry) { - d_drop(dentry); - err = 0; - goto out; - } - - if (dentry == lower_dentry) { - err = 0; - panic("sdcardfs: dentry is equal to lower_dentry\n"); - goto out; - } - - if (dentry < lower_dentry) { - spin_lock(&dentry->d_lock); - spin_lock(&lower_dentry->d_lock); - } else { - spin_lock(&lower_dentry->d_lock); - spin_lock(&dentry->d_lock); - } - - if (dentry->d_name.len != lower_dentry->d_name.len) { - __d_drop(dentry); - err = 0; - } else if (strncasecmp(dentry->d_name.name, lower_dentry->d_name.name, - dentry->d_name.len) != 0) { - __d_drop(dentry); - err = 0; - } - - if (dentry < lower_dentry) { - spin_unlock(&lower_dentry->d_lock); - spin_unlock(&dentry->d_lock); - } else { - spin_unlock(&dentry->d_lock); - spin_unlock(&lower_dentry->d_lock); - } - -out: - dput(parent_dentry); - dput(lower_cur_parent_dentry); - sdcardfs_put_lower_path(parent_dentry, &parent_lower_path); - sdcardfs_put_real_lower(dentry, &lower_path); - return err; -} - -static void sdcardfs_d_release(struct dentry *dentry) -{ - /* release and reset the lower paths */ - if(has_graft_path(dentry)) { - sdcardfs_put_reset_orig_path(dentry); - } - sdcardfs_put_reset_lower_path(dentry); - free_dentry_private_data(dentry); - return; -} - -static int sdcardfs_hash_ci(const struct dentry *dentry, - const struct inode *inode, struct qstr *qstr) -{ - /* - * This function is copy of vfat_hashi. - * FIXME Should we support national language? - * Refer to vfat_hashi() - * struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; - */ - const unsigned char *name; - unsigned int len; - unsigned long hash; - - name = qstr->name; - //len = vfat_striptail_len(qstr); - len = qstr->len; - - hash = init_name_hash(); - while (len--) - //hash = partial_name_hash(nls_tolower(t, *name++), hash); - hash = partial_name_hash(tolower(*name++), hash); - qstr->hash = end_name_hash(hash); - - return 0; -} - -/* - * Case insensitive compare of two vfat names. - */ -static int sdcardfs_cmp_ci(const struct dentry *parent, - const struct inode *pinode, - const struct dentry *dentry, const struct inode *inode, - unsigned int len, const char *str, const struct qstr *name) -{ - /* This function is copy of vfat_cmpi */ - // FIXME Should we support national language? - //struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io; - //unsigned int alen, blen; - - /* A filename cannot end in '.' or we treat it like it has none */ - /* - alen = vfat_striptail_len(name); - blen = __vfat_striptail_len(len, str); - if (alen == blen) { - if (nls_strnicmp(t, name->name, str, alen) == 0) - return 0; - } - */ - if (name->len == len) { - if (strncasecmp(name->name, str, len) == 0) - return 0; - } - return 1; -} - -static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) { - sdcardfs_get_real_lower(path->dentry, actual_path); -} - -const struct dentry_operations sdcardfs_ci_dops = { - .d_revalidate = sdcardfs_d_revalidate, - .d_release = sdcardfs_d_release, - .d_hash = sdcardfs_hash_ci, - .d_compare = sdcardfs_cmp_ci, - .d_canonical_path = sdcardfs_canonical_path, -}; - diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c deleted file mode 100644 index 1ad5b17f29e3..000000000000 --- a/fs/sdcardfs/derived_perm.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * fs/sdcardfs/derived_perm.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" - -/* copy derived state from parent inode */ -static void inherit_derived_state(struct inode *parent, struct inode *child) -{ - struct sdcardfs_inode_info *pi = SDCARDFS_I(parent); - struct sdcardfs_inode_info *ci = SDCARDFS_I(child); - - ci->perm = PERM_INHERIT; - ci->userid = pi->userid; - ci->d_uid = pi->d_uid; - ci->d_gid = pi->d_gid; - ci->under_android = pi->under_android; -} - -/* helper function for derived state */ -void setup_derived_state(struct inode *inode, perm_t perm, - userid_t userid, uid_t uid, gid_t gid, bool under_android) -{ - struct sdcardfs_inode_info *info = SDCARDFS_I(inode); - - info->perm = perm; - info->userid = userid; - info->d_uid = uid; - info->d_gid = gid; - info->under_android = under_android; -} - -void get_derived_permission(struct dentry *parent, struct dentry *dentry) -{ - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode); - struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode); -#ifdef CONFIG_SDP - struct sdcardfs_dentry_info *parent_dinfo = SDCARDFS_D(parent); -#endif - appid_t appid; - - /* By default, each inode inherits from its parent. - * the properties are maintained on its private fields - * because the inode attributes will be modified with that of - * its lower inode. - * The derived state will be updated on the last - * stage of each system call by fix_derived_permission(inode). - */ - - inherit_derived_state(parent->d_inode, dentry->d_inode); - - //printk(KERN_INFO "sdcardfs: derived: %s, %s, %d\n", parent->d_name.name, - // dentry->d_name.name, parent_info->perm); - - /* Derive custom permissions based on parent and current node */ - switch (parent_info->perm) { - case PERM_INHERIT: - /* Already inherited above */ - break; - case PERM_PRE_ROOT: - /* Legacy internal layout places users at top level */ - info->perm = PERM_ROOT; - info->userid = simple_strtoul(dentry->d_name.name, NULL, 10); - break; - case PERM_ROOT: - /* Assume masked off by default. */ - if (!strcasecmp(dentry->d_name.name, "Android")) { - /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID; - info->under_android = true; - } else if (!strcasecmp(dentry->d_name.name, "knox")) { - info->perm = PERM_ANDROID_KNOX; - info->d_gid = AID_SDCARD_R; - info->under_android = false; - } - break; - case PERM_ANDROID: - if (!strcasecmp(dentry->d_name.name, "data")) { - /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID_DATA; - } else if (!strcasecmp(dentry->d_name.name, "obb")) { - /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID_OBB; - // FIXME : this feature will be implemented later. - /* Single OBB directory is always shared */ - } else if (!strcasecmp(dentry->d_name.name, "media")) { - /* App-specific directories inside; let anyone traverse */ - info->perm = PERM_ANDROID_MEDIA; - } - break; - /* same policy will be applied on PERM_ANDROID_DATA - * and PERM_ANDROID_OBB */ - case PERM_ANDROID_DATA: - case PERM_ANDROID_OBB: - case PERM_ANDROID_MEDIA: - appid = get_appid(sbi->pkgl_id, dentry->d_name.name); - if (appid != 0) { - info->d_uid = multiuser_get_uid(parent_info->userid, appid); - } - break; - /** KNOX permission */ - case PERM_ANDROID_KNOX: - info->perm = PERM_ANDROID_KNOX_USER; - info->userid = simple_strtoul(dentry->d_name.name, NULL, 10); - info->d_gid = AID_SDCARD_R; - info->under_android = false; - break; - - case PERM_ANDROID_KNOX_USER: - if (!strcasecmp(dentry->d_name.name, "Android")) { - info->perm = PERM_ANDROID_KNOX_ANDROID; - info->under_android = false; - } - break; - case PERM_ANDROID_KNOX_ANDROID: - if (!strcasecmp(dentry->d_name.name, "data")) { - info->perm = PERM_ANDROID_KNOX_DATA; - info->under_android = false; - } else if (!strcasecmp(dentry->d_name.name, "shared")) { - info->perm = PERM_ANDROID_KNOX_SHARED; - info->d_gid = AID_SDCARD_RW; - info->d_uid = multiuser_get_uid(parent_info->userid, 0); - info->under_android = false; - } - break; - - case PERM_ANDROID_KNOX_SHARED: - break; - - case PERM_ANDROID_KNOX_DATA: - appid = get_appid(sbi->pkgl_id, dentry->d_name.name); - info->perm = PERM_ANDROID_KNOX_PACKAGE_DATA; - if (appid != 0) { - info->d_uid = multiuser_get_uid(parent_info->userid, appid); - } else { - info->d_uid = multiuser_get_uid(parent_info->userid, 0); - } - info->under_android = false; - break; - case PERM_ANDROID_KNOX_PACKAGE_DATA: - break; - } -#ifdef CONFIG_SDP - if((parent_info->perm == PERM_PRE_ROOT) && (parent_dinfo->under_knox) && (parent_dinfo->userid >= 0)) { - info->userid = parent_dinfo->userid; - } - - if(parent_dinfo->under_knox) { - if(parent_dinfo->permission == PERMISSION_UNDER_ANDROID) { - if (parent_dinfo->appid != 0){ - info->d_uid = multiuser_get_uid(parent_info->userid, parent_dinfo->appid); - } - } - } -#endif -} - -/* set vfs_inode from sdcardfs_inode */ -void fix_derived_permission(struct inode *inode) { - struct sdcardfs_inode_info *info = SDCARDFS_I(inode); - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(inode->i_sb); - struct sdcardfs_mount_options *opts = &sbi->options; - mode_t visible_mode; - mode_t owner_mode; - mode_t filtered_mode; - - inode->i_uid = info->d_uid; - - if (info->d_gid == AID_SDCARD_RW) { - /* As an optimization, certain trusted system components only run - * as owner but operate across all users. Since we're now handing - * out the sdcard_rw GID only to trusted apps, we're okay relaxing - * the user boundary enforcement for the default view. The UIDs - * assigned to app directories are still multiuser aware. */ - inode->i_gid = AID_SDCARD_RW; - } else { - inode->i_gid = multiuser_get_uid(info->userid, info->d_gid); - } - - visible_mode = 00775 & ~opts->mask; - if (info->perm == PERM_PRE_ROOT) { - /* Top of multi-user view should always be visible to ensure - * secondary users can traverse inside. */ - visible_mode = 00711; - } else if (info->perm == PERM_ANDROID_KNOX_PACKAGE_DATA - && !info->under_android) { - visible_mode = visible_mode & ~00006; - } else if (info->under_android) { - if (info->d_gid == AID_SDCARD_RW) { - visible_mode = visible_mode & ~00006; - } else { - visible_mode = visible_mode & ~00007; - } - } - - owner_mode = inode->i_mode & 0700; - filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6)); - inode->i_mode = ((inode->i_mode & S_IFMT) | filtered_mode); -} - -/* main function for updating derived permission */ -inline void update_derived_permission(struct dentry *dentry) -{ - struct dentry *parent; - - if(!dentry || !dentry->d_inode) { - printk(KERN_ERR "sdcardfs: %s: invalid dentry\n", __func__); - return; - } - /* FIXME: - * 1. need to check whether the dentry is updated or not - * 2. remove the root dentry update - */ - if(IS_ROOT(dentry)) { - //setup_default_pre_root_state(dentry->d_inode); - } else { - parent = dget_parent(dentry); - if(parent) { - get_derived_permission(parent, dentry); - dput(parent); - } - } - fix_derived_permission(dentry->d_inode); -} - -int need_graft_path(struct dentry *dentry) -{ - int ret = 0; - struct dentry *parent = dget_parent(dentry); - struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode); - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - - if(parent_info->perm == PERM_ANDROID && - !strcasecmp(dentry->d_name.name, "obb") && - sbi->options.multi_user) { - ret = 1; - } - dput(parent); - return ret; -} - -int is_obbpath_invalid(struct dentry *dent) -{ - int ret = 0; - struct sdcardfs_dentry_info *di = SDCARDFS_D(dent); - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dent->d_sb); - char *path_buf, *obbpath_s; - - /* check the base obbpath has been changed. - * this routine can check an uninitialized obb dentry as well. - * regarding the uninitialized obb, refer to the sdcardfs_mkdir() */ - spin_lock(&di->lock); - if(di->orig_path.dentry) { - if(!di->lower_path.dentry) { - ret = 1; - } else { - path_get(&di->lower_path); - //lower_parent = lock_parent(lower_path->dentry); - - path_buf = kmalloc(PATH_MAX, GFP_ATOMIC); - if(!path_buf) { - ret = 1; - printk(KERN_ERR "sdcardfs: " - "fail to allocate path_buf in %s.\n", __func__); - } else { - obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX); - if (d_unhashed(di->lower_path.dentry) || - strcasecmp(sbi->obbpath_s, obbpath_s)) { - ret = 1; - } - kfree(path_buf); - } - - //unlock_dir(lower_parent); - path_put(&di->lower_path); - } - } - spin_unlock(&di->lock); - return ret; -} - -int is_base_obbpath(struct dentry *dentry) -{ - int ret = 0; - struct dentry *parent = dget_parent(dentry); - struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode); - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - - spin_lock(&SDCARDFS_D(dentry)->lock); - /* if multi_user is true */ - if(sbi->options.multi_user && parent_info->perm == PERM_PRE_ROOT && - !strcasecmp(dentry->d_name.name, "obb")) { - ret = 1; - } - /* if multi_user is false, /Android/obb is the base obbpath */ - else if (!sbi->options.multi_user && parent_info->perm == PERM_ANDROID && - !strcasecmp(dentry->d_name.name, "obb")) { - ret = 1; - } - spin_unlock(&SDCARDFS_D(dentry)->lock); - dput(parent); - return ret; -} - -/* The lower_path will be stored to the dentry's orig_path - * and the base obbpath will be copyed to the lower_path variable. - * if an error returned, there's no change in the lower_path - * returns: -ERRNO if error (0: no error) */ -int setup_obb_dentry(struct dentry *dentry, struct path *lower_path) -{ - int err = 0; - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - struct path obbpath; - - /* A local obb dentry must have its own orig_path to support rmdir - * and mkdir of itself. Usually, we expect that the sbi->obbpath - * is avaiable on this stage. */ - sdcardfs_set_orig_path(dentry, lower_path); - - err = kern_path(sbi->obbpath_s, - LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath); - - if(!err) { - /* the obbpath base has been found */ - printk(KERN_INFO "sdcardfs: " - "the sbi->obbpath is found\n"); - pathcpy(lower_path, &obbpath); - } else { - /* if the sbi->obbpath is not available, we can optionally - * setup the lower_path with its orig_path. - * but, the current implementation just returns an error - * because the sdcard daemon also regards this case as - * a lookup fail. */ - printk(KERN_INFO "sdcardfs: " - "the sbi->obbpath is not available\n"); - } - return err; -} diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c deleted file mode 100644 index ff9e5a42d464..000000000000 --- a/fs/sdcardfs/file.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * fs/sdcardfs/file.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" -#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE -#include -#endif - -static ssize_t sdcardfs_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - int err; - struct file *lower_file; - struct dentry *dentry = file->f_path.dentry; -#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE - struct backing_dev_info *bdi; -#endif - - lower_file = sdcardfs_lower_file(file); - -#ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE - if (file->f_mode & FMODE_NOACTIVE) { - if (!(lower_file->f_mode & FMODE_NOACTIVE)) { - bdi = lower_file->f_mapping->backing_dev_info; - lower_file->f_ra.ra_pages = bdi->ra_pages * 2; - spin_lock(&lower_file->f_lock); - lower_file->f_mode |= FMODE_NOACTIVE; - spin_unlock(&lower_file->f_lock); - } - } -#endif - - err = vfs_read(lower_file, buf, count, ppos); - /* update our inode atime upon a successful lower read */ - if (err >= 0) - fsstack_copy_attr_atime(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - - return err; -} - -static ssize_t sdcardfs_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int err = 0; - struct file *lower_file; - struct dentry *dentry = file->f_path.dentry; - - /* check disk space */ - if (!check_min_free_space(dentry, count, 0)) { - printk(KERN_INFO "No minimum free space.\n"); - return -ENOSPC; - } - - lower_file = sdcardfs_lower_file(file); - err = vfs_write(lower_file, buf, count, ppos); - /* update our inode times+sizes upon a successful lower write */ - if (err >= 0) { - fsstack_copy_inode_size(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - fsstack_copy_attr_times(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - } - - return err; -} - -static int sdcardfs_readdir(struct file *file, struct dir_context *ctx) -{ - int err = 0; - struct file *lower_file = NULL; - struct dentry *dentry = file->f_path.dentry; - - lower_file = sdcardfs_lower_file(file); - - lower_file->f_pos = file->f_pos; - err = iterate_dir(lower_file, ctx); - file->f_pos = lower_file->f_pos; - if (err >= 0) /* copy the atime */ - fsstack_copy_attr_atime(dentry->d_inode, - lower_file->f_path.dentry->d_inode); - return err; -} - -static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - long err = -ENOTTY; - struct file *lower_file; - - lower_file = sdcardfs_lower_file(file); - - /* XXX: use vfs_ioctl if/when VFS exports it */ - if (!lower_file || !lower_file->f_op) - goto out; - if (lower_file->f_op->unlocked_ioctl) - err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); - -out: - return err; -} - -#ifdef CONFIG_COMPAT -static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - long err = -ENOTTY; - struct file *lower_file; - - lower_file = sdcardfs_lower_file(file); - - /* XXX: use vfs_ioctl if/when VFS exports it */ - if (!lower_file || !lower_file->f_op) - goto out; - if (lower_file->f_op->compat_ioctl) - err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); - -out: - return err; -} -#endif - -static int sdcardfs_mmap(struct file *file, struct vm_area_struct *vma) -{ - int err = 0; - bool willwrite; - struct file *lower_file; - const struct vm_operations_struct *saved_vm_ops = NULL; - /* this might be deferred to mmap's writepage */ - willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags); - - /* - * File systems which do not implement ->writepage may use - * generic_file_readonly_mmap as their ->mmap op. If you call - * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL. - * But we cannot call the lower ->mmap op, so we can't tell that - * writeable mappings won't work. Therefore, our only choice is to - * check if the lower file system supports the ->writepage, and if - * not, return EINVAL (the same error that - * generic_file_readonly_mmap returns in that case). - */ - lower_file = sdcardfs_lower_file(file); - if (willwrite && !lower_file->f_mapping->a_ops->writepage) { - err = -EINVAL; - printk(KERN_ERR "sdcardfs: lower file system does not " - "support writeable mmap\n"); - goto out; - } - - /* - * find and save lower vm_ops. - * - * XXX: the VFS should have a cleaner way of finding the lower vm_ops - */ - if (!SDCARDFS_F(file)->lower_vm_ops) { - err = lower_file->f_op->mmap(lower_file, vma); - if (err) { - printk(KERN_ERR "sdcardfs: lower mmap failed %d\n", err); - goto out; - } - saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */ - err = do_munmap(current->mm, vma->vm_start, - vma->vm_end - vma->vm_start); - if (err) { - printk(KERN_ERR "sdcardfs: do_munmap failed %d\n", err); - goto out; - } - } - - /* - * Next 3 lines are all I need from generic_file_mmap. I definitely - * don't want its test for ->readpage which returns -ENOEXEC. - */ - file_accessed(file); - vma->vm_ops = &sdcardfs_vm_ops; - - file->f_mapping->a_ops = &sdcardfs_aops; /* set our aops */ - if (!SDCARDFS_F(file)->lower_vm_ops) /* save for our ->fault */ - SDCARDFS_F(file)->lower_vm_ops = saved_vm_ops; - -out: - return err; -} - -static int sdcardfs_open(struct inode *inode, struct file *file) -{ - int err = 0; - struct file *lower_file = NULL; - struct path lower_path; - struct dentry *dentry = file->f_path.dentry; - struct dentry *parent = dget_parent(dentry); - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - const struct cred *saved_cred = NULL; - - /* don't open unhashed/deleted files */ - if (d_unhashed(dentry)) { - err = -ENOENT; - goto out_err; - } - - 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); - err = -EACCES; - goto out_err; - } - - /* save current_cred and override it */ - OVERRIDE_CRED(sbi, saved_cred); - - file->f_mode |= FMODE_NONMAPPABLE; - file->private_data = - kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); - if (!SDCARDFS_F(file)) { - err = -ENOMEM; - goto out_revert_cred; - } - - /* open lower object and link sdcardfs's file struct to lower's */ - sdcardfs_copy_lower_path(file->f_path.dentry, &lower_path); - lower_file = dentry_open(&lower_path, file->f_flags, current_cred()); - if (IS_ERR(lower_file)) { - err = PTR_ERR(lower_file); - lower_file = sdcardfs_lower_file(file); - if (lower_file) { - sdcardfs_set_lower_file(file, NULL); - fput(lower_file); /* fput calls dput for lower_dentry */ - } - } else { - sdcardfs_set_lower_file(file, lower_file); - } - - if (err) - kfree(SDCARDFS_F(file)); - else { - mutex_lock(&inode->i_mutex); - sdcardfs_copy_inode_attr(inode, sdcardfs_lower_inode(inode)); - fix_derived_permission(inode); - mutex_unlock(&inode->i_mutex); - } - -out_revert_cred: - REVERT_CRED(saved_cred); -out_err: - dput(parent); - return err; -} - -static int sdcardfs_flush(struct file *file, fl_owner_t id) -{ - int err = 0; - struct file *lower_file = NULL; - - lower_file = sdcardfs_lower_file(file); - if (lower_file && lower_file->f_op && lower_file->f_op->flush) - err = lower_file->f_op->flush(lower_file, id); - - return err; -} - -/* release all lower object references & free the file info structure */ -static int sdcardfs_file_release(struct inode *inode, struct file *file) -{ - struct file *lower_file; - - lower_file = sdcardfs_lower_file(file); - if (lower_file) { - sdcardfs_set_lower_file(file, NULL); - fput(lower_file); - } - - kfree(SDCARDFS_F(file)); - return 0; -} - -static int -sdcardfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) -{ - int err; - struct file *lower_file; - struct path lower_path; - struct dentry *dentry = file->f_path.dentry; - - lower_file = sdcardfs_lower_file(file); - sdcardfs_get_lower_path(dentry, &lower_path); - err = vfs_fsync_range(lower_file, start, end, datasync); - sdcardfs_put_lower_path(dentry, &lower_path); - - return err; -} - -static int sdcardfs_fasync(int fd, struct file *file, int flag) -{ - int err = 0; - struct file *lower_file = NULL; - - lower_file = sdcardfs_lower_file(file); - if (lower_file->f_op && lower_file->f_op->fasync) - err = lower_file->f_op->fasync(fd, lower_file, flag); - - return err; -} - -static struct file *sdcardfs_get_lower_file(struct file *f) -{ - return sdcardfs_lower_file(f); -} - -const struct file_operations sdcardfs_main_fops = { - .llseek = generic_file_llseek, - .read = sdcardfs_read, - .write = sdcardfs_write, - .unlocked_ioctl = sdcardfs_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = sdcardfs_compat_ioctl, -#endif - .mmap = sdcardfs_mmap, - .open = sdcardfs_open, - .flush = sdcardfs_flush, - .release = sdcardfs_file_release, - .fsync = sdcardfs_fsync, - .fasync = sdcardfs_fasync, - .get_lower_file = sdcardfs_get_lower_file, -}; - -/* trimmed directory options */ -const struct file_operations sdcardfs_dir_fops = { - .llseek = generic_file_llseek, - .read = generic_read_dir, - .iterate = sdcardfs_readdir, - .unlocked_ioctl = sdcardfs_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = sdcardfs_compat_ioctl, -#endif - .open = sdcardfs_open, - .release = sdcardfs_file_release, - .flush = sdcardfs_flush, - .fsync = sdcardfs_fsync, - .fasync = sdcardfs_fasync, - .get_lower_file = sdcardfs_get_lower_file, -}; diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c deleted file mode 100644 index c6444b2f0bf8..000000000000 --- a/fs/sdcardfs/inode.c +++ /dev/null @@ -1,894 +0,0 @@ -/* - * fs/sdcardfs/inode.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" - -/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ -const struct cred * override_fsids(uid_t fsuid, gid_t fsgid) -{ - struct cred * cred; - const struct cred * old_cred; - - cred = prepare_creds(); - if (!cred) - return NULL; - - cred->fsuid = fsuid; - cred->fsgid = fsgid; - - old_cred = override_creds(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; - - 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 excl) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - 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" - " dentry: %s, task:%s\n", - __func__, dentry->d_name.name, current->comm); - err = -EACCES; - goto out_eacces; - } - - /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); - - 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, true); - - if (err) - goto out; - - 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); -out_eacces: - return err; -} - -#if 0 -static int sdcardfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) -{ - struct dentry *lower_old_dentry; - struct dentry *lower_new_dentry; - struct dentry *lower_dir_dentry; - u64 file_size_save; - int err; - 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); - lower_old_dentry = lower_old_path.dentry; - 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); - if (err || !lower_new_dentry->d_inode) - goto out; - - err = sdcardfs_interpose(new_dentry, dir->i_sb, &lower_new_path); - if (err) - goto out; - fsstack_copy_attr_times(dir, lower_new_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_new_dentry->d_inode); - set_nlink(old_dentry->d_inode, - 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); - REVERT_CRED(); - return err; -} -#endif - -static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry) -{ - int err; - struct dentry *lower_dentry; - struct inode *lower_dir_inode = sdcardfs_lower_inode(dir); - struct dentry *lower_dir_dentry; - struct path lower_path; - 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" - " dentry: %s, task:%s\n", - __func__, dentry->d_name.name, current->comm); - err = -EACCES; - goto out_eacces; - } - - /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - dget(lower_dentry); - lower_dir_dentry = lock_parent(lower_dentry); - - err = mnt_want_write(lower_path.mnt); - if (err) - goto out_unlock; - err = vfs_unlink(lower_dir_inode, lower_dentry); - - /* - * Note: unlinking on top of NFS can cause silly-renamed files. - * Trying to delete such files results in EBUSY from NFS - * below. Silly-renamed files will get deleted by NFS later on, so - * we just need to detect them here and treat such EBUSY errors as - * if the upper file was successfully deleted. - */ - if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED) - err = 0; - if (err) - goto out; - fsstack_copy_attr_times(dir, lower_dir_inode); - fsstack_copy_inode_size(dir, lower_dir_inode); - set_nlink(dentry->d_inode, - sdcardfs_lower_inode(dentry->d_inode)->i_nlink); - 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); - REVERT_CRED(saved_cred); -out_eacces: - return err; -} - -#if 0 -static int sdcardfs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - 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; - err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname); - if (err) - goto out; - 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(); - return err; -} -#endif - -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); - if (IS_ERR(filp)) { - if (PTR_ERR(filp) == -EEXIST) { - return 0; - } - else { - printk(KERN_ERR "sdcardfs: failed to open(%s): %ld\n", - abs_path, PTR_ERR(filp)); - return PTR_ERR(filp); - } - } - filp_close(filp, current->files); - return 0; -} - -static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int err = 0; - int make_nomedia_in_obb = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - const struct cred *saved_cred = NULL; - struct sdcardfs_inode_info *pi = SDCARDFS_I(dir); - char *page_buf; - char *nomedia_dir_name; - char *nomedia_fullpath; - int fullpath_namelen; - int touch_err = 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" - " dentry: %s, task:%s\n", - __func__, dentry->d_name.name, current->comm); - err = -EACCES; - goto out_eacces; - } - - /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred); - - /* check disk space */ - if (!check_min_free_space(dentry, 0, 1)) { - printk(KERN_INFO "sdcardfs: No minimum free space.\n"); - err = -ENOSPC; - goto out_revert; - } - - /* the lower_dentry is negative here */ - 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) { - unlock_dir(lower_parent_dentry); - goto out_unlock; - } - - /* set last 16bytes of mode field to 0775 */ - mode = (mode & S_IFMT) | 00775; - err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode); - - 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. - * 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 */ - path_get(&lower_path); - } else - make_nomedia_in_obb = 1; - } - - 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); - - unlock_dir(lower_parent_dentry); - - if (!strcasecmp(dentry->d_name.name, "obb") && (pi->perm == PERM_ANDROID)) - make_nomedia_in_obb = 1; - - /* When creating /Android/data and /Android/obb, mark them as .nomedia */ - if (make_nomedia_in_obb || - ((pi->perm == PERM_ANDROID) && (!strcasecmp(dentry->d_name.name, "data")))) { - - page_buf = (char *)__get_free_page(GFP_KERNEL); - if (!page_buf) { - printk(KERN_ERR "sdcardfs: failed to allocate page buf\n"); - goto out; - } - - nomedia_dir_name = d_absolute_path(&lower_path, page_buf, PAGE_SIZE); - if (IS_ERR(nomedia_dir_name)) { - free_page((unsigned long)page_buf); - printk(KERN_ERR "sdcardfs: failed to get .nomedia dir name\n"); - goto out; - } - - fullpath_namelen = page_buf + PAGE_SIZE - nomedia_dir_name - 1; - fullpath_namelen += strlen("/.nomedia"); - nomedia_fullpath = kzalloc(fullpath_namelen + 1, GFP_KERNEL); - if (!nomedia_fullpath) { - free_page((unsigned long)page_buf); - printk(KERN_ERR "sdcardfs: failed to allocate .nomedia fullpath buf\n"); - goto out; - } - - strcpy(nomedia_fullpath, nomedia_dir_name); - free_page((unsigned long)page_buf); - strcat(nomedia_fullpath, "/.nomedia"); - touch_err = touch(nomedia_fullpath, 0664); - if (touch_err) { - printk(KERN_ERR "sdcardfs: failed to touch(%s): %d\n", - nomedia_fullpath, touch_err); - kfree(nomedia_fullpath); - goto out; - } - kfree(nomedia_fullpath); - } -out: - mnt_drop_write(lower_path.mnt); -out_unlock: - sdcardfs_put_lower_path(dentry, &lower_path); -out_revert: - REVERT_CRED(saved_cred); -out_eacces: - return err; -} - -static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry) -{ - struct dentry *lower_dentry; - struct dentry *lower_dir_dentry; - int err; - struct path lower_path; - 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" - " dentry: %s, task:%s\n", - __func__, dentry->d_name.name, current->comm); - err = -EACCES; - goto out_eacces; - } - - /* 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 - * 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; - err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - if (err) - goto out; - - d_drop(dentry); /* drop our dentry on success (why not VFS's job?) */ - if (dentry->d_inode) - clear_nlink(dentry->d_inode); - fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); - fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode); - 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); -out_eacces: - return err; -} - -#if 0 -static int sdcardfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t dev) -{ - int err = 0; - struct dentry *lower_dentry; - struct dentry *lower_parent_dentry = NULL; - struct path lower_path; - - OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb)); - - 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; - err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev); - if (err) - goto out; - - 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(); - return err; -} -#endif - -/* - * The locking rules in sdcardfs_rename are complex. We could use a simpler - * superblock-level name-space lock for renames and copy-ups. - */ -static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - int err = 0; - struct dentry *lower_old_dentry = NULL; - struct dentry *lower_new_dentry = NULL; - struct dentry *lower_old_dir_dentry = NULL; - struct dentry *lower_new_dir_dentry = NULL; - struct dentry *trap = NULL; - struct dentry *new_parent = NULL; - struct path lower_old_path, lower_new_path; - 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" - " new_dentry: %s, task:%s\n", - __func__, new_dentry->d_name.name, current->comm); - err = -EACCES; - goto out_eacces; - } - - /* save current_cred and override it */ - OVERRIDE_CRED(SDCARDFS_SB(old_dir->i_sb), saved_cred); - - sdcardfs_get_real_lower(old_dentry, &lower_old_path); - sdcardfs_get_lower_path(new_dentry, &lower_new_path); - lower_old_dentry = lower_old_path.dentry; - lower_new_dentry = lower_new_path.dentry; - lower_old_dir_dentry = dget_parent(lower_old_dentry); - lower_new_dir_dentry = dget_parent(lower_new_dentry); - - trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); - /* source should not be ancestor of target */ - if (trap == lower_old_dentry) { - err = -EINVAL; - goto out; - } - /* target should not be ancestor of source */ - if (trap == lower_new_dentry) { - err = -ENOTEMPTY; - goto out; - } - - 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); - if (err) - goto out_err; - - /* Copy attrs from lower dir, but i_uid/i_gid */ - 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_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) { - get_derived_permission(new_parent, old_dentry); - fix_derived_permission(old_dentry->d_inode); - } - dput(new_parent); - } - } - spin_lock(&old_dentry->d_lock); - old_dentry->d_flags |= DCACHE_WILL_INVALIDATE; - spin_unlock(&old_dentry->d_lock); - -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); - dput(lower_new_dir_dentry); - sdcardfs_put_real_lower(old_dentry, &lower_old_path); - sdcardfs_put_lower_path(new_dentry, &lower_new_path); - REVERT_CRED(saved_cred); -out_eacces: - return err; -} - -#if 0 -static int sdcardfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) -{ - int err; - struct dentry *lower_dentry; - struct path lower_path; - /* XXX readlink does not requires overriding credential */ - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - if (!lower_dentry->d_inode->i_op || - !lower_dentry->d_inode->i_op->readlink) { - err = -EINVAL; - goto out; - } - - err = lower_dentry->d_inode->i_op->readlink(lower_dentry, - buf, bufsiz); - if (err < 0) - goto out; - fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode); - -out: - sdcardfs_put_lower_path(dentry, &lower_path); - return err; -} -#endif - -#if 0 -static void *sdcardfs_follow_link(struct dentry *dentry, struct nameidata *nd) -{ - char *buf; - int len = PAGE_SIZE, err; - mm_segment_t old_fs; - - /* This is freed by the put_link method assuming a successful call. */ - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - buf = ERR_PTR(-ENOMEM); - goto out; - } - - /* read the symlink, and then we will follow it */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sdcardfs_readlink(dentry, buf, len); - set_fs(old_fs); - if (err < 0) { - kfree(buf); - buf = ERR_PTR(err); - } else { - buf[err] = '\0'; - } -out: - nd_set_link(nd, buf); - return NULL; -} -#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 - */ - err = generic_permission(inode, mask); - - /* 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. - */ -#if 0 - if (!err) { - /* - * Permission check on lower_inode(=EXT4). - * we check it with AID_MEDIA_RW permission - */ - struct inode *lower_inode; - OVERRIDE_CRED(SDCARDFS_SB(inode->sb)); - - lower_inode = sdcardfs_lower_inode(inode); - err = inode_permission(lower_inode, mask); - - REVERT_CRED(); - } -#endif - 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); - - /* need to get inode->i_mutex */ - mutex_lock(&inode->i_mutex); - 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. - */ - fix_derived_permission(inode); - mutex_unlock(&inode->i_mutex); - - generic_fillattr(inode, stat); - sdcardfs_put_lower_path(dentry, &lower_path); - return 0; -} - -static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia) -{ - int err = 0; - struct dentry *lower_dentry; - struct inode *inode; - struct inode *lower_inode; - struct path lower_path; - struct iattr lower_ia; - struct dentry *parent; - - inode = dentry->d_inode; - - /* - * Check if user has permission to change inode. We don't check if - * this user can change the lower inode: that should happen when - * calling notify_change on the lower inode. - */ - err = inode_change_ok(inode, ia); - - /* no vfs_XXX operations required, cred overriding will be skipped. wj*/ - if (!err) { - /* check the Android group ID */ - 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); - err = -EACCES; - } - dput(parent); - } - - if (err) - goto out_err; - - sdcardfs_get_lower_path(dentry, &lower_path); - lower_dentry = lower_path.dentry; - lower_inode = sdcardfs_lower_inode(inode); - - /* prepare our own lower struct iattr (with the lower file) */ - memcpy(&lower_ia, ia, sizeof(lower_ia)); - if (ia->ia_valid & ATTR_FILE) - lower_ia.ia_file = sdcardfs_lower_file(ia->ia_file); - - lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE); - - /* - * If shrinking, first truncate upper level to cancel writing dirty - * pages beyond the new eof; and also if its' maxbytes is more - * limiting (fail with -EFBIG before making any change to the lower - * level). There is no need to vmtruncate the upper level - * afterwards in the other cases: we fsstack_copy_inode_size from - * the lower level. - */ - if (ia->ia_valid & ATTR_SIZE) { - loff_t oldsize; - err = inode_newsize_ok(inode, ia->ia_size); - if (err) - goto out; - /* This code from truncate_setsize(). We need to add spin_lock - * to avoid race condition with fsstack_copy_inode_size() */ - oldsize = i_size_read(inode); - if (sizeof(ia->ia_size) > sizeof(long)) - spin_lock(&inode->i_lock); - i_size_write(inode, ia->ia_size); - if (sizeof(ia->ia_size) > sizeof(long)) - spin_unlock(&inode->i_lock); - if (ia->ia_size > oldsize) - pagecache_isize_extended(inode, oldsize, ia->ia_size); - truncate_pagecache(inode, oldsize, ia->ia_size); - } - - /* - * mode change is for clearing setuid/setgid bits. Allow lower fs - * to interpret this in its own way. - */ - if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) - lower_ia.ia_valid &= ~ATTR_MODE; - - /* notify the (possibly copied-up) lower inode */ - /* - * Note: we use lower_dentry->d_inode, because lower_inode may be - * unlinked (no inode->i_sb and i_ino==0. This happens if someone - * 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 */ - mutex_unlock(&lower_dentry->d_inode->i_mutex); - if (err) - goto out; - - /* 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 - * lower_inode should update its size. - */ - -out: - sdcardfs_put_lower_path(dentry, &lower_path); -out_err: - return err; -} - -const struct inode_operations sdcardfs_symlink_iops = { - .permission = sdcardfs_permission, - .setattr = sdcardfs_setattr, -#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 = sdcardfs_put_link, - */ -}; - -const struct inode_operations sdcardfs_dir_iops = { - .create = sdcardfs_create, - .lookup = sdcardfs_lookup, - .permission = sdcardfs_permission, - .unlink = sdcardfs_unlink, - .mkdir = sdcardfs_mkdir, - .rmdir = sdcardfs_rmdir, - .rename = sdcardfs_rename, - .setattr = sdcardfs_setattr, - .getattr = sdcardfs_getattr, -#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, - */ -}; - -const struct inode_operations sdcardfs_main_iops = { - .permission = sdcardfs_permission, - .setattr = sdcardfs_setattr, - .getattr = sdcardfs_getattr, -#ifdef SDCARD_FS_XATTR - .setxattr = sdcardfs_setxattr, - .getxattr = sdcardfs_getxattr, - .listxattr = sdcardfs_listxattr, - .removexattr = sdcardfs_removexattr, -#endif // SDCARDFS_XATTR -}; diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c deleted file mode 100644 index e5b2cfc628fc..000000000000 --- a/fs/sdcardfs/lookup.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * fs/sdcardfs/lookup.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" -#include "linux/delay.h" - -/* The dentry cache is just so we have properly sized dentries */ -static struct kmem_cache *sdcardfs_dentry_cachep; - -int sdcardfs_init_dentry_cache(void) -{ - sdcardfs_dentry_cachep = - kmem_cache_create("sdcardfs_dentry", - sizeof(struct sdcardfs_dentry_info), - 0, SLAB_RECLAIM_ACCOUNT, NULL); - - return sdcardfs_dentry_cachep ? 0 : -ENOMEM; -} - -void sdcardfs_destroy_dentry_cache(void) -{ - if (sdcardfs_dentry_cachep) - kmem_cache_destroy(sdcardfs_dentry_cachep); -} - -void free_dentry_private_data(struct dentry *dentry) -{ - if (!dentry || !dentry->d_fsdata) - return; - kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata); - dentry->d_fsdata = NULL; -} - -/* allocate new dentry private data */ -int new_dentry_private_data(struct dentry *dentry) -{ - struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry); - - /* use zalloc to init dentry_info.lower_path */ - info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC); - if (!info) - return -ENOMEM; - - spin_lock_init(&info->lock); - dentry->d_fsdata = info; - - return 0; -} - -static int sdcardfs_inode_test(struct inode *inode, void *candidate_lower_inode) -{ - /* if a lower_inode should have many upper inodes, (like obb) - sdcardfs_iget() will offer many inodes - because test func always will return fail although they have same hash */ - return 0; -} - -static int sdcardfs_inode_set(struct inode *inode, void *lower_inode) -{ - /* we do actual inode initialization in sdcardfs_iget */ - return 0; -} - -static struct inode *sdcardfs_iget(struct super_block *sb, - struct inode *lower_inode) -{ - struct sdcardfs_inode_info *info; - struct inode *inode; /* the new inode to return */ - int err; - - inode = iget5_locked(sb, /* our superblock */ - /* - * hashval: we use inode number, but we can - * also use "(unsigned long)lower_inode" - * instead. - */ - lower_inode->i_ino, /* hashval */ - sdcardfs_inode_test, /* inode comparison function */ - sdcardfs_inode_set, /* inode init function */ - lower_inode); /* data passed to test+set fxns */ - if (!inode) { - err = -EACCES; - iput(lower_inode); - return ERR_PTR(err); - } - /* if found a cached inode, then just return it */ - if (!(inode->i_state & I_NEW)) - return inode; - - /* initialize new inode */ - info = SDCARDFS_I(inode); - - inode->i_ino = lower_inode->i_ino; - if (!igrab(lower_inode)) { - err = -ESTALE; - return ERR_PTR(err); - } - sdcardfs_set_lower_inode(inode, lower_inode); - - inode->i_version++; - - /* use different set of inode ops for symlinks & directories */ - if (S_ISDIR(lower_inode->i_mode)) - inode->i_op = &sdcardfs_dir_iops; - else if (S_ISLNK(lower_inode->i_mode)) - inode->i_op = &sdcardfs_symlink_iops; - else - inode->i_op = &sdcardfs_main_iops; - - /* use different set of file ops for directories */ - if (S_ISDIR(lower_inode->i_mode)) - inode->i_fop = &sdcardfs_dir_fops; - else - inode->i_fop = &sdcardfs_main_fops; - - inode->i_mapping->a_ops = &sdcardfs_aops; - - inode->i_atime.tv_sec = 0; - inode->i_atime.tv_nsec = 0; - inode->i_mtime.tv_sec = 0; - inode->i_mtime.tv_nsec = 0; - inode->i_ctime.tv_sec = 0; - inode->i_ctime.tv_nsec = 0; - - /* properly initialize special inodes */ - if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || - S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) - init_special_inode(inode, lower_inode->i_mode, - lower_inode->i_rdev); - - /* all well, copy inode attributes, don't need to hold i_mutex here */ - sdcardfs_copy_inode_attr(inode, lower_inode); - fsstack_copy_inode_size(inode, lower_inode); - - fix_derived_permission(inode); - - unlock_new_inode(inode); - return inode; -} - -/* - * Connect a sdcardfs inode dentry/inode with several lower ones. This is - * the classic stackable file system "vnode interposition" action. - * - * @dentry: sdcardfs's dentry which interposes on lower one - * @sb: sdcardfs's super_block - * @lower_path: the lower path (caller does path_get/put) - */ -int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, - struct path *lower_path) -{ - int err = 0; - struct inode *inode; - struct inode *lower_inode; - struct super_block *lower_sb; - - lower_inode = lower_path->dentry->d_inode; - lower_sb = sdcardfs_lower_super(sb); - - /* check that the lower file system didn't cross a mount point */ - if (lower_inode->i_sb != lower_sb) { - err = -EXDEV; - goto out; - } - - /* - * We allocate our new inode below by calling sdcardfs_iget, - * which will initialize some of the new inode's fields - */ - - /* inherit lower inode number for sdcardfs's inode */ - inode = sdcardfs_iget(sb, lower_inode); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto out; - } - - d_add(dentry, inode); - update_derived_permission(dentry); -out: - return err; -} - -/* - * Main driver function for sdcardfs's lookup. - * - * Returns: NULL (ok), ERR_PTR if an error occurred. - * Fills in lower_parent_path with on success. - */ -static struct dentry *__sdcardfs_lookup(struct dentry *dentry, - unsigned int flags, struct path *lower_parent_path) -{ - int err = 0; - struct vfsmount *lower_dir_mnt; - struct dentry *lower_dir_dentry = NULL; - struct dentry *lower_dentry; - const char *name; - struct path lower_path; - struct qstr this; - struct sdcardfs_sb_info *sbi; - - sbi = SDCARDFS_SB(dentry->d_sb); - /* must initialize dentry operations */ - d_set_d_op(dentry, &sdcardfs_ci_dops); - - if (IS_ROOT(dentry)) - goto out; - - name = dentry->d_name.name; - - /* now start the actual lookup procedure */ - lower_dir_dentry = lower_parent_path->dentry; - lower_dir_mnt = lower_parent_path->mnt; - - /* Use vfs_path_lookup to check if the dentry exists or not */ - if (sbi->options.lower_fs == LOWER_FS_EXT4) { - err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, - LOOKUP_CASE_INSENSITIVE, &lower_path); - } else if (sbi->options.lower_fs == LOWER_FS_FAT) { - err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, - &lower_path); - } - - /* no error: handle positive dentries */ - if (!err) { - /* check if the dentry is an obb dentry - * if true, the lower_inode must be replaced with - * the inode of the graft path */ - - if(need_graft_path(dentry)) { - - /* setup_obb_dentry() - * The lower_path will be stored to the dentry's orig_path - * and the base obbpath will be copyed to the lower_path variable. - * if an error returned, there's no change in the lower_path - * returns: -ERRNO if error (0: no error) */ - err = setup_obb_dentry(dentry, &lower_path); - - if(err) { - /* if the sbi->obbpath is not available, we can optionally - * setup the lower_path with its orig_path. - * but, the current implementation just returns an error - * because the sdcard daemon also regards this case as - * a lookup fail. */ - printk(KERN_INFO "sdcardfs: base obbpath is not available\n"); - sdcardfs_put_reset_orig_path(dentry); - goto out; - } - } - - sdcardfs_set_lower_path(dentry, &lower_path); - err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path); - if (err) /* path_put underlying path on error */ - sdcardfs_put_reset_lower_path(dentry); - goto out; - } - - /* - * We don't consider ENOENT an error, and we want to return a - * negative dentry. - */ - if (err && err != -ENOENT) - goto out; - - /* instatiate a new negative dentry */ - this.name = name; - this.len = strlen(name); - lower_dentry = d_hash_and_lookup(lower_dir_dentry, &this); - if (unlikely(IS_ERR(lower_dentry))) { - err = PTR_ERR(lower_dentry); - goto out; - } - if (lower_dentry) - goto setup_lower; - - lower_dentry = d_alloc(lower_dir_dentry, &this); - if (!lower_dentry) { - err = -ENOMEM; - goto out; - } - d_add(lower_dentry, NULL); /* instantiate and hash */ - -setup_lower: - lower_path.dentry = lower_dentry; - lower_path.mnt = mntget(lower_dir_mnt); - sdcardfs_set_lower_path(dentry, &lower_path); - - /* - * If the intent is to create a file, then don't return an error, so - * the VFS will continue the process of making this negative dentry - * into a positive one. - */ - err = 0; - -out: - return ERR_PTR(err); -} - -/* - * On success: - * fills dentry object appropriate values and returns NULL. - * On fail (== error) - * returns error ptr - * - * @dir : Parent inode. It is locked (dir->i_mutex) - * @dentry : Target dentry to lookup. we should set each of fields. - * (dentry->d_name is initialized already) - * @nd : nameidata of parent inode - */ -struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - struct dentry *ret = NULL, *parent; - struct path lower_parent_path; - int err = 0; - const struct cred *saved_cred = NULL; - - parent = dget_parent(dentry); - - if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name)) { - ret = ERR_PTR(-EACCES); - 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); - goto out_err; - } - - /* save current_cred and override it */ - OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred); - - sdcardfs_get_lower_path(parent, &lower_parent_path); - - /* allocate dentry private data. We free it in ->d_release */ - err = new_dentry_private_data(dentry); - if (err) { - ret = ERR_PTR(err); - goto out; - } - - ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path); - if (IS_ERR(ret)) - { - goto out; - } - if (ret) - dentry = ret; - if (dentry->d_inode) { - fsstack_copy_attr_times(dentry->d_inode, - sdcardfs_lower_inode(dentry->d_inode)); - /* get drived permission */ - get_derived_permission(parent, dentry); - fix_derived_permission(dentry->d_inode); - } - /* update parent directory's atime */ - fsstack_copy_attr_atime(parent->d_inode, - sdcardfs_lower_inode(parent->d_inode)); - -out: - sdcardfs_put_lower_path(parent, &lower_parent_path); - REVERT_CRED(saved_cred); -out_err: - dput(parent); - return ret; -} diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c deleted file mode 100644 index ad185b611604..000000000000 --- a/fs/sdcardfs/main.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * fs/sdcardfs/main.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" -#include "version.h" -#include -#include -#include -#include "../internal.h" - -enum { - Opt_low_uid, - Opt_low_gid, - Opt_gid, - Opt_userid, - Opt_debug, - Opt_lower_fs, - Opt_reserved_mb, - Opt_mask, - Opt_multi_user, - Opt_label, - Opt_type, - Opt_err, -}; - -static const match_table_t sdcardfs_tokens = { - {Opt_low_uid, "low_uid=%u"}, - {Opt_low_gid, "low_gid=%u"}, - {Opt_gid, "gid=%u"}, - {Opt_userid, "userid=%u"}, - {Opt_debug, "debug"}, - {Opt_lower_fs, "lower_fs=%s"}, - {Opt_reserved_mb, "reserved_mb=%u"}, - {Opt_mask, "mask=%o"}, - {Opt_multi_user, "multi_user"}, - {Opt_label, "label=%s"}, - {Opt_type, "type=%s"}, - {Opt_err, NULL} -}; - -static int parse_options(struct super_block *sb, char *options, int silent, - int *debug, struct sdcardfs_mount_options *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *string_option; - char *label; - - /* by default, we use AID_MEDIA_RW as low_uid, low_gid */ - opts->fs_low_uid = AID_MEDIA_RW; - opts->fs_low_gid = AID_MEDIA_RW; - /* by default, userid is 0, gid is AID_EVERYBODY */ - opts->gid = AID_EVERYBODY; - opts->userid = 0; - /* by default, we use LOWER_FS_EXT4 as lower fs type */ - opts->lower_fs = LOWER_FS_EXT4; - /* by default, 0MB is reserved */ - opts->reserved_mb = 0; - /* by default, mask is 0 */ - opts->mask = 0; - /* by default, multi_user is false */ - opts->multi_user = false; - opts->label = NULL; - opts->type = TYPE_NONE; - - *debug = 0; - - if (!options) - return 0; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - if (!*p) - continue; - - token = match_token(p, sdcardfs_tokens, args); - - switch (token) { - case Opt_debug: - *debug = 1; - break; - case Opt_low_uid: - if (match_int(&args[0], &option)) - return 0; - opts->fs_low_uid = option; - break; - case Opt_low_gid: - if (match_int(&args[0], &option)) - return 0; - opts->fs_low_gid = option; - break; - case Opt_gid: - if (match_int(&args[0], &option)) - goto invalid_option; - opts->gid = option; - break; - case Opt_userid: - if (match_int(&args[0], &option)) - goto invalid_option; - opts->userid = option; - break; - case Opt_lower_fs: - string_option = match_strdup(&args[0]); - if (!string_option) - return -ENOMEM; - if (!strcmp("ext4", string_option)) { - opts->lower_fs = LOWER_FS_EXT4; - } else if (!strcmp("fat", string_option)) { - opts->lower_fs = LOWER_FS_FAT; - } else { - kfree(string_option); - goto invalid_option; - } - kfree(string_option); - break; - case Opt_reserved_mb: - if (match_int(&args[0], &option)) - return 0; - opts->reserved_mb = option; - break; - case Opt_mask: - if (match_octal(&args[0], &option)) - goto invalid_option; - opts->mask = option; - break; - case Opt_multi_user: - opts->multi_user = true; - break; - case Opt_label: - label = match_strdup(&args[0]); - if (!label) - return -ENOMEM; - opts->label = label; - break; - case Opt_type: - string_option = match_strdup(&args[0]); - if (!string_option) - return -ENOMEM; - if (!strcmp("default", string_option)) { - opts->type = TYPE_DEFAULT; - } else if (!strcmp("read", string_option)) { - opts->type = TYPE_READ; - } else if (!strcmp("write", string_option)) { - opts->type = TYPE_WRITE; - } else { - kfree(string_option); - goto invalid_option; - } - kfree(string_option); - break; - /* unknown option */ - default: -invalid_option: - if (!silent) { - printk( KERN_ERR "Unrecognized mount option \"%s\" " - "or missing value", p); - } - return -EINVAL; - } - } - - if (*debug) { - printk( KERN_INFO "sdcardfs : options - debug:%d\n", *debug); - printk( KERN_INFO "sdcardfs : options - uid:%d\n", - opts->fs_low_uid); - printk( KERN_INFO "sdcardfs : options - gid:%d\n", - opts->fs_low_gid); - } - - return 0; -} - -/* - * our custom d_alloc_root work-alike - * - * we can't use d_alloc_root if we want to use our own interpose function - * unchanged, so we simply call our own "fake" d_alloc_root - */ -static struct dentry *sdcardfs_d_alloc_root(struct super_block *sb) -{ - struct dentry *ret = NULL; - - if (sb) { - static const struct qstr name = { - .name = "/", - .len = 1 - }; - - ret = __d_alloc(sb, &name); - if (ret) { - d_set_d_op(ret, &sdcardfs_ci_dops); - ret->d_parent = ret; - } - } - return ret; -} - -/* - * There is no need to lock the sdcardfs_super_info's rwsem as there is no - * way anyone can have a reference to the superblock at this point in time. - */ -static int sdcardfs_read_super(struct super_block *sb, const char *dev_name, - void *raw_data, int silent) -{ - int err = 0; - int debug; - struct super_block *lower_sb; - struct path lower_path; - struct sdcardfs_sb_info *sb_info; - void *pkgl_id; - - printk(KERN_INFO "sdcardfs: version %s\n", SDCARDFS_VERSION); - - if (!dev_name) { - printk(KERN_ERR - "sdcardfs: read_super: missing dev_name argument\n"); - err = -EINVAL; - goto out; - } - - printk(KERN_INFO "sdcardfs: dev_name -> %s\n", dev_name); - printk(KERN_INFO "sdcardfs: options -> %s\n", (char *)raw_data); - - /* parse lower path */ - err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, - &lower_path); - if (err) { - printk(KERN_ERR "sdcardfs: error accessing " - "lower directory '%s'\n", dev_name); - goto out; - } - - /* allocate superblock private data */ - sb->s_fs_info = kzalloc(sizeof(struct sdcardfs_sb_info), GFP_KERNEL); - if (!SDCARDFS_SB(sb)) { - printk(KERN_CRIT "sdcardfs: read_super: out of memory\n"); - err = -ENOMEM; - goto out_free; - } - - sb_info = sb->s_fs_info; - - /* parse options */ - err = parse_options(sb, raw_data, silent, &debug, &sb_info->options); - if (err) { - printk(KERN_ERR "sdcardfs: invalid options or out of memory\n"); - goto out_freesbi; - } - - pkgl_id = packagelist_create(); - if(IS_ERR(pkgl_id)) - goto out_freesbi; - else - sb_info->pkgl_id = pkgl_id; - - /* set the lower superblock field of upper superblock */ - lower_sb = lower_path.dentry->d_sb; - atomic_inc(&lower_sb->s_active); - sdcardfs_set_lower_super(sb, lower_sb); - - sb->s_stack_depth = lower_sb->s_stack_depth + 1; - if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { - pr_err("sdcardfs: maximum fs stacking depth exceeded\n"); - err = -EINVAL; - goto out_sput; - } - - /* inherit maxbytes from lower file system */ - sb->s_maxbytes = lower_sb->s_maxbytes; - - /* - * Our c/m/atime granularity is 1 ns because we may stack on file - * systems whose granularity is as good. - */ - sb->s_time_gran = 1; - - sb->s_magic = SDCARDFS_SUPER_MAGIC; - if (sb_info->options.type != TYPE_NONE) - sb->s_op = &sdcardfs_multimount_sops; - else - sb->s_op = &sdcardfs_sops; - - /* see comment next to the definition of sdcardfs_d_alloc_root */ - sb->s_root = sdcardfs_d_alloc_root(sb); - if (!sb->s_root) { - err = -ENOMEM; - goto out_sput; - } - - /* link the upper and lower dentries */ - sb->s_root->d_fsdata = NULL; - err = new_dentry_private_data(sb->s_root); - if (err) - goto out_freeroot; - - /* set the lower dentries for s_root */ - sdcardfs_set_lower_path(sb->s_root, &lower_path); - - /* call interpose to create the upper level inode */ - err = sdcardfs_interpose(sb->s_root, sb, &lower_path); - if (!err) { - /* setup permission policy */ - if(sb_info->options.multi_user){ - setup_derived_state(sb->s_root->d_inode, - PERM_PRE_ROOT, sb_info->options.userid, AID_ROOT, sb_info->options.gid, false); - sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL); - snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name); - err = prepare_dir(sb_info->obbpath_s, - sb_info->options.fs_low_uid, - sb_info->options.fs_low_gid, 00775); - } else { - setup_derived_state(sb->s_root->d_inode, - PERM_ROOT, sb_info->options.userid, AID_ROOT, sb_info->options.gid, false); - sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL); - snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name); - } - fix_derived_permission(sb->s_root->d_inode); - - sb_info->devpath = kzalloc(PATH_MAX, GFP_KERNEL); - if(sb_info->devpath && dev_name) - strncpy(sb_info->devpath, dev_name, strlen(dev_name)); - - if (!silent && !err) - printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n", - dev_name, lower_sb->s_type->name); - goto out; - } - /* else error: fall through */ - - free_dentry_private_data(sb->s_root); -out_freeroot: - dput(sb->s_root); -out_sput: - /* drop refs we took earlier */ - atomic_dec(&lower_sb->s_active); - packagelist_destroy(sb_info->pkgl_id); -out_freesbi: - kfree(SDCARDFS_SB(sb)); - sb->s_fs_info = NULL; -out_free: - path_put(&lower_path); - -out: - return err; -} - -/* A feature which supports mount_nodev() with options */ -static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, - int (*fill_super)(struct super_block *, const char *, void *, int)) - -{ - int error; - struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL); - - if (IS_ERR(s)) - return ERR_CAST(s); - - s->s_flags = flags; - - error = fill_super(s, dev_name, data, flags & MS_SILENT ? 1 : 0); - if (error) { - deactivate_locked_super(s); - return ERR_PTR(error); - } - s->s_flags |= MS_ACTIVE; - return dget(s->s_root); -} - -struct dentry *sdcardfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data) -{ - /* - * dev_name is a lower_path_name, - * raw_data is a option string. - */ - return mount_nodev_with_options(fs_type, flags, dev_name, - raw_data, sdcardfs_read_super); -} - -static struct file_system_type sdcardfs_fs_type = { - .owner = THIS_MODULE, - .name = SDCARDFS_NAME, - .mount = sdcardfs_mount, - .kill_sb = generic_shutdown_super, - .fs_flags = 0, -}; - -static int __init init_sdcardfs_fs(void) -{ - int err; - - pr_info("Registering sdcardfs " SDCARDFS_VERSION "\n"); - - err = sdcardfs_init_inode_cache(); - if (err) - goto out; - err = sdcardfs_init_dentry_cache(); - if (err) - goto out; - err = packagelist_init(); - if (err) - goto out; - err = register_filesystem(&sdcardfs_fs_type); -out: - if (err) { - sdcardfs_destroy_inode_cache(); - sdcardfs_destroy_dentry_cache(); - packagelist_exit(); - } - return err; -} - -static void __exit exit_sdcardfs_fs(void) -{ - sdcardfs_destroy_inode_cache(); - sdcardfs_destroy_dentry_cache(); - packagelist_exit(); - unregister_filesystem(&sdcardfs_fs_type); - pr_info("Completed sdcardfs module unload\n"); -} - -MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil" - " System Memory Lab., Samsung Electronics"); -MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION); -MODULE_LICENSE("GPL"); - -module_init(init_sdcardfs_fs); -module_exit(exit_sdcardfs_fs); diff --git a/fs/sdcardfs/mmap.c b/fs/sdcardfs/mmap.c deleted file mode 100644 index f90e352a2b32..000000000000 --- a/fs/sdcardfs/mmap.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * fs/sdcardfs/mmap.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" - -static int sdcardfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - int err; - struct file *file, *lower_file; - const struct vm_operations_struct *lower_vm_ops; - struct vm_area_struct lower_vma; - - memcpy(&lower_vma, vma, sizeof(struct vm_area_struct)); - file = lower_vma.vm_file; - lower_vm_ops = SDCARDFS_F(file)->lower_vm_ops; - BUG_ON(!lower_vm_ops); - - lower_file = sdcardfs_lower_file(file); - /* - * XXX: vm_ops->fault may be called in parallel. Because we have to - * resort to temporarily changing the vma->vm_file to point to the - * lower file, a concurrent invocation of sdcardfs_fault could see a - * different value. In this workaround, we keep a different copy of - * the vma structure in our stack, so we never expose a different - * value of the vma->vm_file called to us, even temporarily. A - * better fix would be to change the calling semantics of ->fault to - * take an explicit file pointer. - */ - lower_vma.vm_file = lower_file; - err = lower_vm_ops->fault(&lower_vma, vmf); - return err; -} - -static ssize_t sdcardfs_direct_IO(int rw, struct kiocb *iocb, - const struct iovec *iov, loff_t offset, - unsigned long nr_segs) -{ - /* - * This function returns zero on purpose in order to support direct IO. - * __dentry_open checks a_ops->direct_IO and returns EINVAL if it is null. - * - * However, this function won't be called by certain file operations - * including generic fs functions. * reads and writes are delivered to - * the lower file systems and the direct IOs will be handled by them. - * - * NOTE: exceptionally, on the recent kernels (since Linux 3.8.x), - * swap_writepage invokes this function directly. - */ - printk(KERN_INFO "%s, operation is not supported\n", __func__); - return 0; -} - -/* - * XXX: the default address_space_ops for sdcardfs is empty. We cannot set - * our inode->i_mapping->a_ops to NULL because too many code paths expect - * the a_ops vector to be non-NULL. - */ -const struct address_space_operations sdcardfs_aops = { - /* empty on purpose */ - .direct_IO = sdcardfs_direct_IO, -}; - -const struct vm_operations_struct sdcardfs_vm_ops = { - .fault = sdcardfs_fault, -}; diff --git a/fs/sdcardfs/multiuser.h b/fs/sdcardfs/multiuser.h deleted file mode 100644 index e84db83f2b53..000000000000 --- a/fs/sdcardfs/multiuser.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * fs/sdcardfs/multiuser.h - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#define MULTIUSER_APP_PER_USER_RANGE 100000 - -typedef uid_t userid_t; -typedef uid_t appid_t; - -static inline userid_t multiuser_get_user_id(uid_t uid) { - return uid / MULTIUSER_APP_PER_USER_RANGE; -} - -static inline appid_t multiuser_get_app_id(uid_t uid) { - return uid % MULTIUSER_APP_PER_USER_RANGE; -} - -static inline uid_t multiuser_get_uid(userid_t userId, appid_t appId) { - return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE); -} - diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c deleted file mode 100644 index d65e0472bc2d..000000000000 --- a/fs/sdcardfs/packagelist.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * fs/sdcardfs/packagelist.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" -#include -#include -#include -#include -#include - -#define STRING_BUF_SIZE (512) - -struct hashtable_entry { - struct hlist_node hlist; - void *key; - int value; -}; - -struct packagelist_data { - DECLARE_HASHTABLE(package_to_appid,8); - struct mutex hashtable_lock; - struct task_struct *thread_id; - char read_buf[STRING_BUF_SIZE]; - char event_buf[STRING_BUF_SIZE]; - char app_name_buf[STRING_BUF_SIZE]; - char gids_buf[STRING_BUF_SIZE]; -}; - -static struct kmem_cache *hashtable_entry_cachep; - -/* Path to system-provided mapping of package name to appIds */ -static const char* const kpackageslist_file = "/data/system/packages.list"; -/* Supplementary groups to execute with */ -static const gid_t kgroups[1] = { AID_PACKAGE_INFO }; - -static unsigned int str_hash(void *key) { - int i; - unsigned int h = strlen(key); - char *data = (char *)key; - - for (i = 0; i < strlen(key); i++) { - h = h * 31 + *data; - data++; - } - return h; -} - -appid_t get_appid(void *pkgl_id, const char *app_name) -{ - struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id; - struct hashtable_entry *hash_cur; - unsigned int hash = str_hash((void *)app_name); - appid_t ret_id; - - //printk(KERN_INFO "sdcardfs: %s: %s, %u\n", __func__, (char *)app_name, hash); - mutex_lock(&pkgl_dat->hashtable_lock); - hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) { - //printk(KERN_INFO "sdcardfs: %s: %s\n", __func__, (char *)hash_cur->key); - if (!strcasecmp(app_name, hash_cur->key)) { - ret_id = (appid_t)hash_cur->value; - mutex_unlock(&pkgl_dat->hashtable_lock); - //printk(KERN_INFO "=> app_id: %d\n", (int)ret_id); - return ret_id; - } - } - mutex_unlock(&pkgl_dat->hashtable_lock); - //printk(KERN_INFO "=> app_id: %d\n", 0); - return 0; -} - -/* Kernel has already enforced everything we returned through - * derive_permissions_locked(), so this is used to lock down access - * even further, such as enforcing that apps hold sdcard_rw. */ -int check_caller_access_to_name(struct inode *parent_node, const char* name) { - /* Always block security-sensitive files at root */ - if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) { - if (!strcasecmp(name, "autorun.inf") - || !strcasecmp(name, ".android_secure") - || !strcasecmp(name, "android_secure")) { - return 0; - } - } - - /* Root always has access; access for any other UIDs should always - * be controlled through packages.list. */ - if (current_fsuid() == 0) { - return 1; - } - - /* No extra permissions to enforce */ - return 1; -} - -/* This function is used when file opening. The open flags must be - * checked before calling check_caller_access_to_name() */ -int open_flags_to_access_mode(int open_flags) { - if((open_flags & O_ACCMODE) == O_RDONLY) { - return 0; /* R_OK */ - } else if ((open_flags & O_ACCMODE) == O_WRONLY) { - return 1; /* W_OK */ - } else { - /* Probably O_RDRW, but treat as default to be safe */ - return 1; /* R_OK | W_OK */ - } -} - -static int insert_str_to_int(struct packagelist_data *pkgl_dat, void *key, int value) { - struct hashtable_entry *hash_cur; - struct hashtable_entry *new_entry; - unsigned int hash = str_hash(key); - - //printk(KERN_INFO "sdcardfs: %s: %s: %d, %u\n", __func__, (char *)key, value, hash); - hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) { - if (!strcasecmp(key, hash_cur->key)) { - hash_cur->value = value; - return 0; - } - } - new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL); - if (!new_entry) - return -ENOMEM; - new_entry->key = kstrdup(key, GFP_KERNEL); - new_entry->value = value; - hash_add(pkgl_dat->package_to_appid, &new_entry->hlist, hash); - return 0; -} - -static void remove_str_to_int(struct hashtable_entry *h_entry) { - //printk(KERN_INFO "sdcardfs: %s: %s: %d\n", __func__, (char *)h_entry->key, h_entry->value); - kfree(h_entry->key); - kmem_cache_free(hashtable_entry_cachep, h_entry); -} - -/*static void remove_int_to_null(struct hashtable_entry *h_entry) { - //printk(KERN_INFO "sdcardfs: %s: %d: %d\n", __func__, (int)h_entry->key, h_entry->value); - kmem_cache_free(hashtable_entry_cachep, h_entry); -}*/ - -static void remove_all_hashentrys(struct packagelist_data *pkgl_dat) -{ - struct hashtable_entry *hash_cur; - struct hlist_node *h_t; - int i; - - hash_for_each_safe(pkgl_dat->package_to_appid, i, h_t, hash_cur, hlist) - remove_str_to_int(hash_cur); - - hash_init(pkgl_dat->package_to_appid); -} - -static int read_package_list(struct packagelist_data *pkgl_dat) { - int ret; - int fd; - int read_amount; - - printk(KERN_INFO "sdcardfs: read_package_list\n"); - - mutex_lock(&pkgl_dat->hashtable_lock); - - remove_all_hashentrys(pkgl_dat); - - fd = sys_open(kpackageslist_file, O_RDONLY, 0); - if (fd < 0) { - printk(KERN_ERR "sdcardfs: failed to open package list\n"); - mutex_unlock(&pkgl_dat->hashtable_lock); - return fd; - } - - while ((read_amount = sys_read(fd, pkgl_dat->read_buf, - sizeof(pkgl_dat->read_buf))) > 0) { - int appid; - int one_line_len = 0; - int additional_read; - - while (one_line_len < read_amount) { - if (pkgl_dat->read_buf[one_line_len] == '\n') { - one_line_len++; - break; - } - one_line_len++; - } - additional_read = read_amount - one_line_len; - if (additional_read > 0) - sys_lseek(fd, -additional_read, SEEK_CUR); - - if (sscanf(pkgl_dat->read_buf, "%s %d %*d %*s %*s %s", - pkgl_dat->app_name_buf, &appid, - pkgl_dat->gids_buf) == 3) { - ret = insert_str_to_int(pkgl_dat, pkgl_dat->app_name_buf, appid); - if (ret) { - sys_close(fd); - mutex_unlock(&pkgl_dat->hashtable_lock); - return ret; - } - } - } - - sys_close(fd); - mutex_unlock(&pkgl_dat->hashtable_lock); - return 0; -} - -static int packagelist_reader(void *thread_data) -{ - struct packagelist_data *pkgl_dat = (struct packagelist_data *)thread_data; - struct inotify_event *event; - bool active = false; - int event_pos; - int event_size; - int res = 0; - int nfd; - - allow_signal(SIGINT); - - nfd = sys_inotify_init(); - if (nfd < 0) { - printk(KERN_ERR "sdcardfs: inotify_init failed: %d\n", nfd); - return nfd; - } - - while (!kthread_should_stop()) { - if (signal_pending(current)) { - msleep(100); - continue; - } - - if (!active) { - res = sys_inotify_add_watch(nfd, kpackageslist_file, IN_DELETE_SELF); - if (res < 0) { - if (res == -ENOENT || res == -EACCES) { - /* Framework may not have created yet, sleep and retry */ - printk(KERN_ERR "sdcardfs: missing packages.list; retrying\n"); - ssleep(2); - printk(KERN_ERR "sdcardfs: missing packages.list_end; retrying\n"); - continue; - } else { - printk(KERN_ERR "sdcardfs: inotify_add_watch failed: %d\n", res); - goto interruptable_sleep; - } - } - /* Watch above will tell us about any future changes, so - * read the current state. */ - res = read_package_list(pkgl_dat); - if (res) { - printk(KERN_ERR "sdcardfs: read_package_list failed: %d\n", res); - goto interruptable_sleep; - } - active = true; - } - - event_pos = 0; - res = sys_read(nfd, pkgl_dat->event_buf, sizeof(pkgl_dat->event_buf)); - if (res < (int) sizeof(*event)) { - if (res == -EINTR) - continue; - printk(KERN_ERR "sdcardfs: failed to read inotify event: %d\n", res); - goto interruptable_sleep; - } - - while (res >= (int) sizeof(*event)) { - event = (struct inotify_event *) (pkgl_dat->event_buf + event_pos); - - printk(KERN_INFO "sdcardfs: inotify event: %08x\n", event->mask); - if ((event->mask & IN_IGNORED) == IN_IGNORED) { - /* Previously watched file was deleted, probably due to move - * that swapped in new data; re-arm the watch and read. */ - active = false; - } - - event_size = sizeof(*event) + event->len; - res -= event_size; - event_pos += event_size; - } - continue; - -interruptable_sleep: - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } - flush_signals(current); - sys_close(nfd); - return res; -} - -void * packagelist_create(void) -{ - struct packagelist_data *pkgl_dat; - struct task_struct *packagelist_thread; - - pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO); - if (!pkgl_dat) { - printk(KERN_ERR "sdcardfs: creating kthread failed\n"); - return ERR_PTR(-ENOMEM); - } - - mutex_init(&pkgl_dat->hashtable_lock); - hash_init(pkgl_dat->package_to_appid); - - packagelist_thread = kthread_run(packagelist_reader, (void *)pkgl_dat, "pkgld"); - if (IS_ERR(packagelist_thread)) { - printk(KERN_ERR "sdcardfs: creating kthread failed\n"); - kfree(pkgl_dat); - return packagelist_thread; - } - pkgl_dat->thread_id = packagelist_thread; - - printk(KERN_INFO "sdcardfs: created packagelist pkgld/%d\n", - (int)pkgl_dat->thread_id->pid); - - return (void *)pkgl_dat; -} - -void packagelist_destroy(void *pkgl_id) -{ - struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id; - pid_t pkgl_pid = pkgl_dat->thread_id->pid; - - force_sig_info(SIGINT, SEND_SIG_PRIV, pkgl_dat->thread_id); - kthread_stop(pkgl_dat->thread_id); - remove_all_hashentrys(pkgl_dat); - printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld/%d\n", (int)pkgl_pid); - kfree(pkgl_dat); -} - -int packagelist_init(void) -{ - hashtable_entry_cachep = - kmem_cache_create("packagelist_hashtable_entry", - sizeof(struct hashtable_entry), 0, 0, NULL); - if (!hashtable_entry_cachep) { - printk(KERN_ERR "sdcardfs: failed creating pkgl_hashtable entry slab cache\n"); - return -ENOMEM; - } - - return 0; -} - -void packagelist_exit(void) -{ - if (hashtable_entry_cachep) - kmem_cache_destroy(hashtable_entry_cachep); -} diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h deleted file mode 100644 index a4e53d3204c1..000000000000 --- a/fs/sdcardfs/sdcardfs.h +++ /dev/null @@ -1,567 +0,0 @@ -/* - * fs/sdcardfs/sdcardfs.h - * - * The sdcardfs v2.0 - * This file system replaces the sdcard daemon on Android - * On version 2.0, some of the daemon functions have been ported - * to support the multi-user concepts of Android 4.4 - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#ifndef _SDCARDFS_H_ -#define _SDCARDFS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "multiuser.h" - -/* the file system magic number */ -#define SDCARDFS_SUPER_MAGIC 0xb550ca10 - -/* the file system name */ -#define SDCARDFS_NAME "sdcardfs" - -/* sdcardfs root inode number */ -#define SDCARDFS_ROOT_INO 1 - -/* useful for tracking code reachability */ -#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) - -#define SDCARDFS_DIRENT_SIZE 256 - -/* temporary static uid settings for development */ -#define AID_ROOT 0 /* uid for accessing /mnt/sdcard & extSdcard */ -#define AID_MEDIA_RW 1023 /* internal media storage write access */ - -#define AID_SDCARD_RW 1015 /* external storage write access */ -#define AID_SDCARD_R 1028 /* external storage read access */ -#define AID_SDCARD_PICS 1033 /* external storage photos access */ -#define AID_SDCARD_AV 1034 /* external storage audio/video access */ -#define AID_SDCARD_ALL 1035 /* access all users external storage */ - -#define AID_PACKAGE_INFO 1027 -#define AID_EVERYBODY 9997 - -/* OVERRIDE_CRED() and REVERT_CRED() - * OVERRID_CRED() - * backup original task->cred - * and modifies task->cred->fsuid/fsgid to specified value. - * REVERT_CRED() - * restore original task->cred->fsuid/fsgid. - * These two macro should be used in pair, and OVERRIDE_CRED() should be - * placed at the beginning of a function, right after variable declaration. - */ -#define OVERRIDE_CRED(sdcardfs_sbi, saved_cred) \ - saved_cred = override_fsids(sdcardfs_sbi->options.fs_low_uid, \ - sdcardfs_sbi->options.fs_low_gid); \ - if (!saved_cred) { return -ENOMEM; } - -#define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred) \ - saved_cred = override_fsids(sdcardfs_sbi->options.fs_low_uid, \ - sdcardfs_sbi->options.fs_low_gid); \ - if (!saved_cred) { return ERR_PTR(-ENOMEM); } - -#define OVERRIDE_ROOT_CRED(saved_cred) \ - saved_cred = override_fsids(0, 0); \ - if (!saved_cred) { return -ENOMEM; } - -#define REVERT_CRED(saved_cred) revert_fsids(saved_cred) - -#define DEBUG_CRED() \ - printk("KAKJAGI: %s:%d fsuid %d fsgid %d\n", \ - __FUNCTION__, __LINE__, \ - (int)current->cred->fsuid, \ - (int)current->cred->fsgid); - -/* Permission mode for a specific node. Controls how file permissions - * are derived for children nodes. */ -typedef enum { - /* Nothing special; this node should just inherit from its parent. */ - PERM_INHERIT, - /* This node is one level above a normal root; used for legacy layouts - * which use the first level to represent user_id. */ - PERM_PRE_ROOT, - /* This node is "/" */ - PERM_ROOT, - /* This node is "/Android" */ - PERM_ANDROID, - /* This node is "/Android/data" */ - PERM_ANDROID_DATA, - /* This node is "/Android/obb" */ - PERM_ANDROID_OBB, - /* This node is "/Android/media" */ - PERM_ANDROID_MEDIA, - /* knox folder */ - PERM_ANDROID_KNOX, - /* knox user folder*/ - PERM_ANDROID_KNOX_USER, - /* knox Android folder*/ - PERM_ANDROID_KNOX_ANDROID, - /* knox shared folder */ - PERM_ANDROID_KNOX_SHARED, - /* knox data folder */ - PERM_ANDROID_KNOX_DATA, - /* knox package data folder */ - PERM_ANDROID_KNOX_PACKAGE_DATA -} perm_t; - -typedef enum { - LOWER_FS_EXT4, - LOWER_FS_FAT, -} lower_fs_t; - -typedef enum { - TYPE_NONE, - TYPE_DEFAULT, - TYPE_READ, - TYPE_WRITE, -} type_t; - -struct sdcardfs_sb_info; -struct sdcardfs_mount_options; - -/* Do not directly use this function. Use OVERRIDE_CRED() instead. */ -const struct cred * override_fsids(uid_t fsuid, gid_t fsgid); -/* Do not directly use this function, use REVERT_CRED() instead. */ -void revert_fsids(const struct cred * old_cred); - -/* operations vectors defined in specific files */ -extern const struct file_operations sdcardfs_main_fops; -extern const struct file_operations sdcardfs_dir_fops; -extern const struct inode_operations sdcardfs_main_iops; -extern const struct inode_operations sdcardfs_dir_iops; -extern const struct inode_operations sdcardfs_symlink_iops; -extern const struct super_operations sdcardfs_sops; -extern const struct super_operations sdcardfs_multimount_sops; -extern const struct dentry_operations sdcardfs_ci_dops; -extern const struct address_space_operations sdcardfs_aops, sdcardfs_dummy_aops; -extern const struct vm_operations_struct sdcardfs_vm_ops; - -extern int sdcardfs_init_inode_cache(void); -extern void sdcardfs_destroy_inode_cache(void); -extern int sdcardfs_init_dentry_cache(void); -extern void sdcardfs_destroy_dentry_cache(void); -extern int new_dentry_private_data(struct dentry *dentry); -extern void free_dentry_private_data(struct dentry *dentry); -extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags); -extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, - struct path *lower_path); - -#ifdef SDCARD_FS_XATTR -extern int sdcardfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -extern ssize_t sdcardfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size); -extern ssize_t sdcardfs_listxattr(struct dentry *dentry, char *list, size_t size); -extern int sdcardfs_removexattr(struct dentry *dentry, const char *name); -#endif // SDCARD_FS_XATTR -/* file private data */ -struct sdcardfs_file_info { - struct file *lower_file; - const struct vm_operations_struct *lower_vm_ops; -}; - -/* sdcardfs inode data in memory */ -struct sdcardfs_inode_info { - struct inode *lower_inode; - /* state derived based on current position in hierachy - */ - perm_t perm; - userid_t userid; - uid_t d_uid; - gid_t d_gid; - bool under_android; - - struct inode vfs_inode; -}; - -/* sdcardfs dentry data in memory */ -struct sdcardfs_dentry_info { - spinlock_t lock; /* protects lower_path */ - struct path lower_path; - struct path orig_path; -#ifdef CONFIG_SDP - int under_knox; - int userid; -#define PERMISSION_PRE_ROOT 0 -#define PERMISSION_ROOT 1 -#define PERMISSION_ANDROID 2 -#define PERMISSION_UNDER_ANDROID 3 - int permission; - appid_t appid; -#endif -}; - -struct sdcardfs_mount_options { - uid_t fs_low_uid; - gid_t fs_low_gid; - gid_t gid; - userid_t userid; - lower_fs_t lower_fs; - unsigned int reserved_mb; - mode_t mask; - bool multi_user; - char *label; - type_t type; -}; - -/* sdcardfs super-block data in memory */ -struct sdcardfs_sb_info { - struct super_block *lower_sb; - /* derived perm policy : some of options have been added - * to sdcardfs_mount_options (Android 4.4 support) */ - struct sdcardfs_mount_options options; - spinlock_t lock; /* protects obbpath */ - char *obbpath_s; - struct path obbpath; - void *pkgl_id; - char *devpath; -}; - -/* - * inode to private data - * - * Since we use containers and the struct inode is _inside_ the - * sdcardfs_inode_info structure, SDCARDFS_I will always (given a non-NULL - * inode pointer), return a valid non-NULL pointer. - */ -static inline struct sdcardfs_inode_info *SDCARDFS_I(const struct inode *inode) -{ - return container_of(inode, struct sdcardfs_inode_info, vfs_inode); -} - -/* dentry to private data */ -#define SDCARDFS_D(dent) ((struct sdcardfs_dentry_info *)(dent)->d_fsdata) - -/* superblock to private data */ -#define SDCARDFS_SB(super) ((struct sdcardfs_sb_info *)(super)->s_fs_info) - -/* file to private Data */ -#define SDCARDFS_F(file) ((struct sdcardfs_file_info *)((file)->private_data)) - -/* file to lower file */ -static inline struct file *sdcardfs_lower_file(const struct file *f) -{ - return SDCARDFS_F(f)->lower_file; -} - -static inline void sdcardfs_set_lower_file(struct file *f, struct file *val) -{ - SDCARDFS_F(f)->lower_file = val; -} - -/* inode to lower inode. */ -static inline struct inode *sdcardfs_lower_inode(const struct inode *i) -{ - return SDCARDFS_I(i)->lower_inode; -} - -static inline void sdcardfs_set_lower_inode(struct inode *i, struct inode *val) -{ - SDCARDFS_I(i)->lower_inode = val; -} - -/* copy the inode attrs from src to dest except uid and gid */ -static inline void sdcardfs_copy_inode_attr(struct inode *dest, const struct inode *src) -{ - dest->i_mode = src->i_mode; - dest->i_rdev = src->i_rdev; - dest->i_atime = src->i_atime; - dest->i_mtime = src->i_mtime; - dest->i_ctime = src->i_ctime; - dest->i_blkbits = src->i_blkbits; - dest->i_flags = src->i_flags; - set_nlink(dest, src->i_nlink); -} - -/* superblock to lower superblock */ -static inline struct super_block *sdcardfs_lower_super( - const struct super_block *sb) -{ - return SDCARDFS_SB(sb)->lower_sb; -} - -static inline void sdcardfs_set_lower_super(struct super_block *sb, - struct super_block *val) -{ - SDCARDFS_SB(sb)->lower_sb = val; -} - -/* path based (dentry/mnt) macros */ -static inline void pathcpy(struct path *dst, const struct path *src) -{ - dst->dentry = src->dentry; - dst->mnt = src->mnt; -} - -/* sdcardfs_get_pname functions calls path_get() - * therefore, the caller must call "proper" path_put functions - */ -#define SDCARDFS_DENT_FUNC(pname) \ -static inline void sdcardfs_get_##pname(const struct dentry *dent, \ - struct path *pname) \ -{ \ - spin_lock(&SDCARDFS_D(dent)->lock); \ - pathcpy(pname, &SDCARDFS_D(dent)->pname); \ - path_get(pname); \ - spin_unlock(&SDCARDFS_D(dent)->lock); \ - return; \ -} \ -static inline void sdcardfs_put_##pname(const struct dentry *dent, \ - struct path *pname) \ -{ \ - path_put(pname); \ - return; \ -} \ -static inline void sdcardfs_set_##pname(const struct dentry *dent, \ - struct path *pname) \ -{ \ - spin_lock(&SDCARDFS_D(dent)->lock); \ - pathcpy(&SDCARDFS_D(dent)->pname, pname); \ - spin_unlock(&SDCARDFS_D(dent)->lock); \ - return; \ -} \ -static inline void sdcardfs_reset_##pname(const struct dentry *dent) \ -{ \ - spin_lock(&SDCARDFS_D(dent)->lock); \ - SDCARDFS_D(dent)->pname.dentry = NULL; \ - SDCARDFS_D(dent)->pname.mnt = NULL; \ - spin_unlock(&SDCARDFS_D(dent)->lock); \ - return; \ -} \ -static inline void sdcardfs_put_reset_##pname(const struct dentry *dent) \ -{ \ - struct path pname; \ - spin_lock(&SDCARDFS_D(dent)->lock); \ - if(SDCARDFS_D(dent)->pname.dentry) { \ - pathcpy(&pname, &SDCARDFS_D(dent)->pname); \ - SDCARDFS_D(dent)->pname.dentry = NULL; \ - SDCARDFS_D(dent)->pname.mnt = NULL; \ - spin_unlock(&SDCARDFS_D(dent)->lock); \ - path_put(&pname); \ - } else \ - spin_unlock(&SDCARDFS_D(dent)->lock); \ - return; \ -} - -SDCARDFS_DENT_FUNC(lower_path) -SDCARDFS_DENT_FUNC(orig_path) - -static inline void sdcardfs_copy_lower_path(const struct dentry *dent, - struct path *lower_path) -{ - spin_lock(&SDCARDFS_D(dent)->lock); - pathcpy(lower_path, &SDCARDFS_D(dent)->lower_path); - spin_unlock(&SDCARDFS_D(dent)->lock); - return; -} - -static inline int has_graft_path(const struct dentry *dent) -{ - int ret = 0; - - spin_lock(&SDCARDFS_D(dent)->lock); - if (SDCARDFS_D(dent)->orig_path.dentry != NULL) - ret = 1; - spin_unlock(&SDCARDFS_D(dent)->lock); - - return ret; -} - -static inline void sdcardfs_get_real_lower(const struct dentry *dent, - struct path *real_lower) -{ - /* in case of a local obb dentry - * the orig_path should be returned - */ - if(has_graft_path(dent)) - sdcardfs_get_orig_path(dent, real_lower); - else - sdcardfs_get_lower_path(dent, real_lower); -} - -static inline void sdcardfs_put_real_lower(const struct dentry *dent, - struct path *real_lower) -{ - if(has_graft_path(dent)) - sdcardfs_put_orig_path(dent, real_lower); - else - sdcardfs_put_lower_path(dent, real_lower); -} - -/* for packagelist.c */ -extern appid_t get_appid(void *pkgl_id, const char *app_name); -extern int check_caller_access_to_name(struct inode *parent_node, const char* name); -extern int open_flags_to_access_mode(int open_flags); -extern void *packagelist_create(void); -extern void packagelist_destroy(void *pkgl_id); -extern int packagelist_init(void); -extern void packagelist_exit(void); - -/* for derived_perm.c */ -extern void setup_derived_state(struct inode *inode, perm_t perm, - userid_t userid, uid_t uid, gid_t gid, bool under_android); -extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); -extern void fix_derived_permission(struct inode *inode); -extern void update_derived_permission(struct dentry *dentry); -extern int need_graft_path(struct dentry *dentry); -extern int is_base_obbpath(struct dentry *dentry); -extern int is_obbpath_invalid(struct dentry *dentry); -extern int setup_obb_dentry(struct dentry *dentry, struct path *lower_path); - -/* locking helpers */ -static inline struct dentry *lock_parent(struct dentry *dentry) -{ - struct dentry *dir = dget_parent(dentry); - mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); - return dir; -} - -static inline void unlock_dir(struct dentry *dir) -{ - mutex_unlock(&dir->d_inode->i_mutex); - dput(dir); -} - -static inline int prepare_dir(const char *path_s, uid_t uid, gid_t gid, mode_t mode) -{ - int err; - struct dentry *dent; - struct path path; - struct iattr attrs; - - dent = kern_path_create(AT_FDCWD, path_s, &path, LOOKUP_DIRECTORY); - - if (IS_ERR(dent)) { - err = PTR_ERR(dent); - if (err == -EEXIST) - err = 0; - return err; - } - - err = mnt_want_write(path.mnt); - if (err) - goto out; - - err = vfs_mkdir(path.dentry->d_inode, dent, mode); - if (err) { - if (err == -EEXIST) - err = 0; - goto out_drop; - } - - attrs.ia_uid = uid; - attrs.ia_gid = gid; - attrs.ia_valid = ATTR_UID | ATTR_GID; - mutex_lock(&dent->d_inode->i_mutex); - notify_change(dent, &attrs); - mutex_unlock(&dent->d_inode->i_mutex); - -out_drop: - mnt_drop_write(path.mnt); - -out: - dput(dent); - /* parent dentry locked by kern_path_create */ - mutex_unlock(&path.dentry->d_inode->i_mutex); - path_put(&path); - return err; -} - -/* - * Return 1, if a disk has enough free space, otherwise 0. - * We assume that any files can not be overwritten. - */ -static inline int check_min_free_space(struct dentry *dentry, size_t size, int dir) -{ - int err; - struct path lower_path; - struct kstatfs statfs; - u64 avail; - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - - if (sbi->options.reserved_mb) { - /* Get fs stat of lower filesystem. */ - sdcardfs_get_lower_path(dentry, &lower_path); - err = vfs_statfs(&lower_path, &statfs); - sdcardfs_put_lower_path(dentry, &lower_path); - - if (unlikely(err)) - goto out_invalid; - - /* Invalid statfs informations. */ - if (unlikely(statfs.f_bsize == 0)) - goto out_invalid; - - /* if you are checking directory, set size to f_bsize. */ - if (unlikely(dir)) - size = statfs.f_bsize; - - /* available size */ - avail = statfs.f_bavail * statfs.f_bsize; - - /* not enough space */ - if ((u64)size > avail) - goto out_nospc; - - /* enough space */ - if ((avail - size) > (sbi->options.reserved_mb * 1024 * 1024)) - return 1; - goto out_nospc; - } else - return 1; - -out_invalid: - printk(KERN_INFO "statfs : invalid return\n"); - printk(KERN_INFO "vfs_statfs error# : %d\n", err); - printk(KERN_INFO "statfs.f_type : 0x%X\n", (u32)statfs.f_type); - printk(KERN_INFO "statfs.f_blocks : %llu blocks\n", statfs.f_blocks); - printk(KERN_INFO "statfs.f_bfree : %llu blocks\n", statfs.f_bfree); - printk(KERN_INFO "statfs.f_files : %llu\n", statfs.f_files); - printk(KERN_INFO "statfs.f_ffree : %llu\n", statfs.f_ffree); - printk(KERN_INFO "statfs.f_fsid.val[1] : 0x%X\n", (u32)statfs.f_fsid.val[1]); - printk(KERN_INFO "statfs.f_fsid.val[0] : 0x%X\n", (u32)statfs.f_fsid.val[0]); - printk(KERN_INFO "statfs.f_namelen : %ld\n", statfs.f_namelen); - printk(KERN_INFO "statfs.f_frsize : %ld\n", statfs.f_frsize); - printk(KERN_INFO "statfs.f_flags : %ld\n", statfs.f_flags); - printk(KERN_INFO "sdcardfs reserved_mb : %u\n", sbi->options.reserved_mb); - if (sbi->devpath) - printk(KERN_INFO "sdcardfs source path : %s\n", sbi->devpath); - -out_nospc: - printk_ratelimited(KERN_INFO "statfs.f_bavail : %llu blocks / " - "statfs.f_bsize : %ld bytes / " - "required size : %llu byte\n" - ,statfs.f_bavail, statfs.f_bsize, (u64)size); - return 0; -} -#endif /* not _SDCARDFS_H_ */ diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c deleted file mode 100644 index e80955ca8587..000000000000 --- a/fs/sdcardfs/super.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * fs/sdcardfs/super.c - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, - * Sunghwan Yun, Sungjong Seo - * - * This program has been developed as a stackable file system based on - * 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 - * - * 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. - */ - -#include "sdcardfs.h" - -/* - * The inode cache is used with alloc_inode for both our inode info and the - * vfs inode. - */ -static struct kmem_cache *sdcardfs_inode_cachep; - -/* final actions when unmounting a file system */ -static void sdcardfs_put_super(struct super_block *sb) -{ - struct sdcardfs_sb_info *spd; - struct super_block *s; - - spd = SDCARDFS_SB(sb); - if (!spd) - return; - - printk(KERN_ERR "sdcardfs: umounted dev_name %s\n", - spd->devpath ? spd->devpath : ""); - if(spd->devpath) - kfree(spd->devpath); - - if(spd->obbpath_s) { - kfree(spd->obbpath_s); - path_put(&spd->obbpath); - } - - if(spd->options.label) - kfree(spd->options.label); - - /* decrement lower super references */ - s = sdcardfs_lower_super(sb); - sdcardfs_set_lower_super(sb, NULL); - atomic_dec(&s->s_active); - - if(spd->pkgl_id) - packagelist_destroy(spd->pkgl_id); - - kfree(spd); - sb->s_fs_info = NULL; -} - -static int sdcardfs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - int err; - struct path lower_path; - u32 min_blocks; - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); - - sdcardfs_get_lower_path(dentry, &lower_path); - err = vfs_statfs(&lower_path, buf); - sdcardfs_put_lower_path(dentry, &lower_path); - - if (sbi->options.reserved_mb) { - /* Invalid statfs informations. */ - if (buf->f_bsize == 0) { - printk(KERN_ERR "Returned block size is zero.\n"); - return -EINVAL; - } - - min_blocks = ((sbi->options.reserved_mb * 1024 * 1024)/buf->f_bsize); - buf->f_blocks -= min_blocks; - - if (buf->f_bavail > min_blocks) - buf->f_bavail -= min_blocks; - else - buf->f_bavail = 0; - - /* Make reserved blocks invisiable to media storage */ - buf->f_bfree = buf->f_bavail; - } - - /* set return buf to our f/s to avoid confusing user-level utils */ - buf->f_type = SDCARDFS_SUPER_MAGIC; - - return err; -} - -/* - * @flags: numeric mount options - * @options: mount options string - */ -static int sdcardfs_remount_fs(struct super_block *sb, int *flags, char *options) -{ - int err = 0; - - /* - * The VFS will take care of "ro" and "rw" flags among others. We - * can safely accept a few flags (RDONLY, MANDLOCK), and honor - * SILENT, but anything else left over is an error. - */ - if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) { - printk(KERN_ERR - "sdcardfs: remount flags 0x%x unsupported\n", *flags); - err = -EINVAL; - } - - return err; -} - -/* - * Called by iput() when the inode reference count reached zero - * and the inode is not hashed anywhere. Used to clear anything - * that needs to be, before the inode is completely destroyed and put - * on the inode free list. - */ -static void sdcardfs_evict_inode(struct inode *inode) -{ - struct inode *lower_inode; - - truncate_inode_pages(&inode->i_data, 0); - clear_inode(inode); - /* - * Decrement a reference to a lower_inode, which was incremented - * by our read_inode when it was created initially. - */ - lower_inode = sdcardfs_lower_inode(inode); - sdcardfs_set_lower_inode(inode, NULL); - iput(lower_inode); -} - -static struct inode *sdcardfs_alloc_inode(struct super_block *sb) -{ - struct sdcardfs_inode_info *i; - - i = kmem_cache_alloc(sdcardfs_inode_cachep, GFP_KERNEL); - if (!i) - return NULL; - - /* memset everything up to the inode to 0 */ - memset(i, 0, offsetof(struct sdcardfs_inode_info, vfs_inode)); - - i->vfs_inode.i_version = 1; - return &i->vfs_inode; -} - -static void sdcardfs_destroy_inode(struct inode *inode) -{ - kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode)); -} - -/* sdcardfs inode cache constructor */ -static void init_once(void *obj) -{ - struct sdcardfs_inode_info *i = obj; - - inode_init_once(&i->vfs_inode); -} - -int sdcardfs_init_inode_cache(void) -{ - int err = 0; - - sdcardfs_inode_cachep = - kmem_cache_create("sdcardfs_inode_cache", - sizeof(struct sdcardfs_inode_info), 0, - SLAB_RECLAIM_ACCOUNT, init_once); - if (!sdcardfs_inode_cachep) - err = -ENOMEM; - return err; -} - -/* sdcardfs inode cache destructor */ -void sdcardfs_destroy_inode_cache(void) -{ - if (sdcardfs_inode_cachep) - kmem_cache_destroy(sdcardfs_inode_cachep); -} - -static long sdcardfs_propagate_lookup(struct super_block *sb, char* pathname) { - long ret = 0; - char *propagate_path = NULL; - struct sdcardfs_sb_info *sbi; - struct path sibling_path; - const struct cred *saved_cred = NULL; - - sbi = SDCARDFS_SB(sb); - OVERRIDE_ROOT_CRED(saved_cred); - propagate_path = kmalloc(PATH_MAX, GFP_KERNEL); - if (!propagate_path) { - REVERT_CRED(saved_cred); - return -ENOMEM; - } - if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_DEFAULT) { - snprintf(propagate_path, PATH_MAX, "/mnt/runtime/default/%s%s", - sbi->options.label, pathname); - ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); - if (!ret) - path_put(&sibling_path); - } - - if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_READ) { - snprintf(propagate_path, PATH_MAX, "/mnt/runtime/read/%s%s", - sbi->options.label, pathname); - ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); - if (!ret) - path_put(&sibling_path); - } - - if (sbi->options.type != TYPE_NONE && sbi->options.type != TYPE_WRITE) { - snprintf(propagate_path, PATH_MAX, "/mnt/runtime/write/%s%s", - sbi->options.label, pathname); - ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); - if (!ret) - path_put(&sibling_path); - } - - if (sbi->options.type != TYPE_NONE) { - snprintf(propagate_path, PATH_MAX, "/storage/%s%s", - sbi->options.label, pathname); - ret = (long)kern_path(propagate_path, LOOKUP_FOLLOW, &sibling_path); - if (!ret) - path_put(&sibling_path); - } - REVERT_CRED(saved_cred); - kfree(propagate_path); - return ret; -} - -/* - * Used only in nfs, to kill any pending RPC tasks, so that subsequent - * code can actually succeed and won't leave tasks that need handling. - */ -static void sdcardfs_umount_begin(struct super_block *sb) -{ - struct super_block *lower_sb; - - lower_sb = sdcardfs_lower_super(sb); - if (lower_sb && lower_sb->s_op && lower_sb->s_op->umount_begin) - lower_sb->s_op->umount_begin(lower_sb); -} - -static int sdcardfs_show_options(struct seq_file *m, struct dentry *root) -{ - struct sdcardfs_sb_info *sbi = SDCARDFS_SB(root->d_sb); - struct sdcardfs_mount_options *opts = &sbi->options; - - if (opts->fs_low_uid != 0) - seq_printf(m, ",low_uid=%u", opts->fs_low_uid); - if (opts->fs_low_gid != 0) - seq_printf(m, ",low_gid=%u", opts->fs_low_gid); - if (opts->gid != 0) - seq_printf(m, ",gid=%u", opts->gid); - if (opts->userid != 0) - seq_printf(m, ",userid=%u", opts->userid); - if (opts->multi_user) - seq_printf(m, ",multi_user"); - if (opts->mask != 0) - seq_printf(m, ",mask=%04o", opts->mask); - if (opts->reserved_mb != 0) - seq_printf(m, ",reserved=%uMB", opts->reserved_mb); - - return 0; -}; - -const struct super_operations sdcardfs_sops = { - .put_super = sdcardfs_put_super, - .statfs = sdcardfs_statfs, - .remount_fs = sdcardfs_remount_fs, - .evict_inode = sdcardfs_evict_inode, - .umount_begin = sdcardfs_umount_begin, - .show_options = sdcardfs_show_options, - .alloc_inode = sdcardfs_alloc_inode, - .destroy_inode = sdcardfs_destroy_inode, - .drop_inode = generic_delete_inode, -}; - -const struct super_operations sdcardfs_multimount_sops = { - .put_super = sdcardfs_put_super, - .statfs = sdcardfs_statfs, - .remount_fs = sdcardfs_remount_fs, - .evict_inode = sdcardfs_evict_inode, - .umount_begin = sdcardfs_umount_begin, - .show_options = sdcardfs_show_options, - .alloc_inode = sdcardfs_alloc_inode, - .destroy_inode = sdcardfs_destroy_inode, - .drop_inode = generic_delete_inode, - .unlink_callback = sdcardfs_propagate_lookup, -}; diff --git a/fs/sdcardfs/version.h b/fs/sdcardfs/version.h deleted file mode 100644 index a70c4fbdd32f..000000000000 --- a/fs/sdcardfs/version.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * The sdcardfs - * - * Copyright (c) 2013 Samsung Electronics Co. Ltd - * Authors: Daeho Jeong, Woojoong Lee, Kitae Lee, Yeongjin Gil - * - * Revision History - * 2014.06.24 : Release Version 2.1.0 - * - Add sdcardfs version - * - Add kernel log when put_super - * 2014.07.21 : Release Version 2.1.1 - * - Add sdcardfs_copy_inode_attr() to fix permission issue - * - Delete mmap_sem lock in sdcardfs_setattr() to avoid deadlock - * 2014.11.12 : Release Version 2.1.2 - * - Add get_lower_file function pointer in file_operations - * 2014.11.25 : Release Version 2.1.3 - * - Add error handling routine in sdcardfs_d_revalidate - * when dentry is equal to lower_dentry - * 2015.03.25 : Release Version 2.1.4 - * - Add FMODE_NONMAPPABLE, FMODE_NONCACHEABLE flag to file->f_mode - * - Modify do_mmap_pgoff because of new f_mode flags - * 2015.07. : Release Version 3.0.0 - * 2015.11.24 : Release Version 3.1.0 - * - Add unlink_callback(), get_lower_inode() - * - Add mount option type, label - * 2016.02. : Release Version 3.2.0 - * - remove get_lower_inode(), make sdcardfs use only unlink_callback() - * - modify name hash creation because it's different with vfat's - * - obb will be used only multi_user option is enabled - * - modify sdcardfs_setattr because it changes i_size without spinlock - * it can make race condition with fsstack_copy_inode_size() - */ - -#define SDCARDFS_VERSION "3.2.0" diff --git a/fs/sdcardfs/xattr.c b/fs/sdcardfs/xattr.c deleted file mode 100644 index 4fad9882ebf8..000000000000 --- a/fs/sdcardfs/xattr.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include -#include "sdcardfs.h" - -static struct dentry * -sdcardfs_dentry_to_lower(struct dentry *dentry) -{ - struct dentry* ret; - - ret = ((struct sdcardfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry; - return ret; -} - -int -sdcardfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) -{ - int rc = 0; - struct dentry *lower_dentry; - - lower_dentry = sdcardfs_dentry_to_lower(dentry); - if (!lower_dentry->d_inode->i_op->setxattr) { - rc = -EOPNOTSUPP; - goto out; - } - - rc = vfs_setxattr(lower_dentry, name, value, size, flags); -out: - return rc; -} - -static ssize_t -sdcardfs_getxattr_lower(struct dentry *lower_dentry, const char *name, void *value, size_t size) -{ - int rc = 0; - - if (!lower_dentry->d_inode->i_op->getxattr) { - rc = -EOPNOTSUPP; - goto out; - } - rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value, - size); -out: - return rc; -} - -ssize_t -sdcardfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) -{ - ssize_t ret; - ret = sdcardfs_getxattr_lower(sdcardfs_dentry_to_lower(dentry), name, - value, size); - return ret; -} - -ssize_t -sdcardfs_listxattr(struct dentry *dentry, char *list, size_t size) -{ - int rc = 0; - struct dentry *lower_dentry; - - lower_dentry = sdcardfs_dentry_to_lower(dentry); - if (!lower_dentry->d_inode->i_op->listxattr) { - rc = -EOPNOTSUPP; - goto out; - } - rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size); -out: - return rc; -} - -int -sdcardfs_removexattr(struct dentry *dentry, const char *name) -{ - int rc = 0; - struct dentry *lower_dentry; - - lower_dentry = sdcardfs_dentry_to_lower(dentry); - if (!lower_dentry->d_inode->i_op->removexattr) { - rc = -EOPNOTSUPP; - goto out; - } - mutex_lock(&lower_dentry->d_inode->i_mutex); - rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name); - mutex_unlock(&lower_dentry->d_inode->i_mutex); -out: - return rc; -} diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 0085161f939a..5abd1a92839d 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -158,7 +158,6 @@ struct dentry_operations { char *(*d_dname)(struct dentry *, char *, int); struct vfsmount *(*d_automount)(struct path *); int (*d_manage)(struct dentry *, bool); - void (*d_canonical_path)(const struct path *, struct path *); } ____cacheline_aligned; /* @@ -210,7 +209,6 @@ struct dentry_operations { (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) #define DCACHE_DENTRY_KILLED 0x100000 -#define DCACHE_WILL_INVALIDATE 0x80000000 /* will be invalidated */ #define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */ diff --git a/include/linux/fs.h b/include/linux/fs.h index a1de645bbdd3..b167ac142801 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -124,9 +124,6 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* File is opened with O_PATH; almost nothing can be done with it */ #define FMODE_PATH ((__force fmode_t)0x4000) -/* File hasn't page cache and can't be mmaped, for stackable filesystem */ -#define FMODE_NONMAPPABLE ((__force fmode_t)0x400000) - /* File page don't need to be cached, for stackable filesystem's lower file */ #define FMODE_NONCACHEABLE ((__force fmode_t)0x800000) diff --git a/include/linux/namei.h b/include/linux/namei.h index 4061514107b4..5a5ff57ceed4 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -55,9 +55,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_JUMPED 0x1000 #define LOOKUP_ROOT 0x2000 #define LOOKUP_EMPTY 0x4000 -#ifdef CONFIG_SDCARD_FS_CI_SEARCH -#define LOOKUP_CASE_INSENSITIVE 0x8000 -#endif extern int user_path_at(int, const char __user *, unsigned, struct path *); extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty); diff --git a/mm/mmap.c b/mm/mmap.c index fa6f89055d8e..9580d2ede391 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1239,8 +1239,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, *populate = 0; - while (file && (file->f_mode & FMODE_NONMAPPABLE)) - file = file->f_op->get_lower_file(file); /* * Does the application expect PROT_READ to imply PROT_EXEC? *