aboutsummaryrefslogtreecommitdiff
path: root/fs/sdcardfs/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sdcardfs/main.c')
-rwxr-xr-x[-rw-r--r--]fs/sdcardfs/main.c395
1 files changed, 283 insertions, 112 deletions
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index a6522286..8322d20f 100644..100755
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -1,69 +1,121 @@
/*
* fs/sdcardfs/main.c
*
- * Copyright (c) 2013 Samsung Electronics Co. Ltd
- * Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
- * Sunghwan Yun, Sungjong Seo
- *
+ * Copyright (c) 2015 Lenovo Co. Ltd
+ * Authors: liaohs , jixj
+
+ *
* This program has been developed as a stackable file system based on
- * the WrapFS which written by
+ * the WrapFS which written by
*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009 Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ * Copyright (c) 1998-2014 Erez Zadok
+ * Copyright (c) 2009 Shrikar Archak
+ * Copyright (c) 2003-2014 Stony Brook University
+ * Copyright (c) 2003-2014 The Research Foundation of SUNY
*
- * This file is dual licensed. It may be redistributed and/or modified
- * under the terms of the Apache 2.0 License OR version 2 of the GNU
- * General Public License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
#include "sdcardfs.h"
+#include "version.h"
#include <linux/module.h>
#include <linux/types.h>
#include <linux/parser.h>
+/*
+ * dcache.c
+ */
+extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
+
enum {
- Opt_fsuid,
- Opt_fsgid,
- Opt_gid,
+ Opt_uid,
+ Opt_gid,
+ Opt_wgid,
+ Opt_upper_perms,
Opt_debug,
+ Opt_split,
+ Opt_derive,
Opt_lower_fs,
- Opt_mask,
- Opt_multiuser, // May need?
- Opt_userid,
Opt_reserved_mb,
Opt_err,
};
static const match_table_t sdcardfs_tokens = {
- {Opt_fsuid, "fsuid=%u"},
- {Opt_fsgid, "fsgid=%u"},
+ {Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
+ {Opt_wgid, "wgid=%u"},
+ {Opt_upper_perms, "upper=%s"},
{Opt_debug, "debug"},
- {Opt_mask, "mask=%u"},
- {Opt_userid, "userid=%d"},
- {Opt_multiuser, "multiuser"},
+ {Opt_split, "split"},
+ {Opt_derive, "derive=%s"},
+ {Opt_lower_fs, "lower_fs=%s"},
{Opt_reserved_mb, "reserved_mb=%u"},
{Opt_err, NULL}
};
-static int parse_options(struct super_block *sb, char *options, int silent,
+static int parse_perms(struct sdcardfs_perms *perms, char *args)
+{
+ char *sep = args;
+ char *sepres;
+ int ret;
+
+ if (!sep)
+ return -EINVAL;
+
+ sepres = strsep(&sep, ":");
+ if (!sep)
+ return -EINVAL;
+ ret = kstrtou32(sepres, 0, &perms->uid);
+ if (ret)
+ return ret;
+
+ sepres = strsep(&sep, ":");
+ if (!sep)
+ return -EINVAL;
+ ret = kstrtou32(sepres, 0, &perms->gid);
+ if (ret)
+ return ret;
+
+ sepres = strsep(&sep, ":");
+ if (!sep)
+ return -EINVAL;
+ ret = kstrtou16(sepres, 8, &perms->fmask);
+ if (ret)
+ return ret;
+
+ sepres = strsep(&sep, ":");
+ ret = kstrtou16(sepres, 8, &perms->dmask);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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;
+ int ret;
+ char *perms;
/* by default, we use AID_MEDIA_RW as uid, gid */
opts->fs_low_uid = AID_MEDIA_RW;
opts->fs_low_gid = AID_MEDIA_RW;
- opts->mask = 0;
- opts->multiuser = false;
- opts->fs_user_id = 0;
- opts->gid = 0;
- /* by default, 0MB is reserved */
- opts->reserved_mb = 0;
+ /* by default, we use AID_SDCARD_RW as write_gid */
+ opts->write_gid = AID_SDCARD_RW;
+ /* default permission policy
+ * (DERIVE_NONE | DERIVE_LEGACY | DERIVE_UNIFIED) */
+ opts->derive = DERIVE_NONE;
+ opts->split_perms = 0;
+ /* by default, we use LOWER_FS_EXT4 as lower fs type */
+ opts->lower_fs = LOWER_FS_EXT4;
+ /* by default, 50MB is reserved */
+ opts->reserved_mb = LOWER_FS_MIN_FREE_SIZE;
*debug = 0;
@@ -76,46 +128,81 @@ static int parse_options(struct super_block *sb, char *options, int silent,
continue;
token = match_token(p, sdcardfs_tokens, args);
-
+
switch (token) {
case Opt_debug:
*debug = 1;
break;
- case Opt_fsuid:
+ case Opt_uid:
if (match_int(&args[0], &option))
return 0;
opts->fs_low_uid = option;
break;
- case Opt_fsgid:
+ case Opt_gid:
if (match_int(&args[0], &option))
return 0;
opts->fs_low_gid = option;
break;
- case Opt_gid:
+ case Opt_wgid:
if (match_int(&args[0], &option))
return 0;
- opts->gid = option;
+ opts->write_gid = option;
break;
- case Opt_userid:
- if (match_int(&args[0], &option))
- return 0;
- opts->fs_user_id = option;
+ case Opt_upper_perms:
+ perms = match_strdup(args);
+ if(perms) {
+ ret = parse_perms(&opts->upper_perms, perms);
+ kfree(perms);
+ if (ret)
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
break;
- case Opt_mask:
- if (match_int(&args[0], &option))
- return 0;
- opts->mask = option;
+ case Opt_split:
+ opts->split_perms=1;
+ break;
+ case Opt_derive:
+ string_option = match_strdup(&args[0]);
+ if (!strcmp("none", string_option)) {
+ opts->derive = DERIVE_NONE;
+ } else if (!strcmp("legacy", string_option)) {
+ opts->derive = DERIVE_LEGACY;
+ } else if (!strcmp("unified", string_option)) {
+ opts->derive = DERIVE_UNIFIED;
+ } else if (!strcmp("public", string_option)) {
+ opts->derive = DERIVE_PUBLIC;
+ } else if (!strcmp("multi", string_option)) {
+ opts->derive = DERIVE_MULTI;
+ } else {
+ kfree(string_option);
+ goto invalid_option;
+ }
+ kfree(string_option);
break;
- case Opt_multiuser:
- opts->multiuser = true;
+ case Opt_lower_fs:
+ string_option = match_strdup(&args[0]);
+ if (!strcmp("ext4", string_option)) {
+ opts->lower_fs = LOWER_FS_EXT4;
+ } else if (!strcmp("fat", string_option)) {
+ opts->lower_fs = LOWER_FS_FAT;
+ } else if (!strcmp("f2fs", string_option)) {
+ opts->lower_fs = LOWER_FS_F2FS;
+ } 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;
+ printk( KERN_INFO "sdcardfs : options - reserved_mb: %d\n", opts->reserved_mb);
break;
/* unknown option */
default:
+invalid_option:
if (!silent) {
printk( KERN_ERR "Unrecognized mount option \"%s\" "
"or missing value", p);
@@ -126,16 +213,20 @@ static int parse_options(struct super_block *sb, char *options, int silent,
if (*debug) {
printk( KERN_INFO "sdcardfs : options - debug:%d\n", *debug);
- printk( KERN_INFO "sdcardfs : options - uid:%d\n",
+ printk( KERN_INFO "sdcardfs : options - uid:%d\n",
opts->fs_low_uid);
- printk( KERN_INFO "sdcardfs : options - gid:%d\n",
+ printk( KERN_INFO "sdcardfs : options - gid:%d\n",
opts->fs_low_gid);
+ printk( KERN_INFO "sdcardfs : options - derive:%d\n",
+ opts->derive);
+ printk( KERN_INFO "sdcardfs : options - write_gid:%d\n",
+ opts->write_gid);
+
}
return 0;
}
-#if 0
/*
* our custom d_alloc_root work-alike
*
@@ -152,27 +243,20 @@ static struct dentry *sdcardfs_d_alloc_root(struct super_block *sb)
.len = 1
};
- ret = d_alloc(NULL, &name);
+ ret = __d_alloc(sb, &name);
if (ret) {
d_set_d_op(ret, &sdcardfs_ci_dops);
- ret->d_sb = sb;
ret->d_parent = ret;
}
}
return ret;
}
-#endif
-
-DEFINE_MUTEX(sdcardfs_super_list_lock);
-LIST_HEAD(sdcardfs_super_list);
-EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock);
-EXPORT_SYMBOL_GPL(sdcardfs_super_list);
/*
* 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,
+static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
void *raw_data, int silent)
{
int err = 0;
@@ -180,9 +264,9 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
struct super_block *lower_sb;
struct path lower_path;
struct sdcardfs_sb_info *sb_info;
- struct inode *inode;
+ void *pkgl_id;
- printk(KERN_INFO "sdcardfs version 2.0\n");
+ printk(KERN_INFO "sdcardfs: version %s\n", SDCARDFS_VERSION);
if (!dev_name) {
printk(KERN_ERR
@@ -198,7 +282,8 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
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);
+ printk(KERN_ERR "sdcardfs: error accessing "
+ "lower directory '%s'\n", dev_name);
goto out;
}
@@ -211,6 +296,7 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
}
sb_info = sb->s_fs_info;
+
/* parse options */
err = parse_options(sb, raw_data, silent, &debug, &sb_info->options);
if (err) {
@@ -218,6 +304,14 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
goto out_freesbi;
}
+ if (sb_info->options.derive != DERIVE_NONE) {
+ pkgl_id = packagelist_create(sb_info->options.write_gid);
+ 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);
@@ -235,18 +329,12 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
sb->s_magic = SDCARDFS_SUPER_MAGIC;
sb->s_op = &sdcardfs_sops;
- /* get a new inode and allocate our root dentry */
- inode = sdcardfs_iget(sb, lower_path.dentry->d_inode, 0);
- if (IS_ERR(inode)) {
- err = PTR_ERR(inode);
- goto out_sput;
- }
- sb->s_root = d_make_root(inode);
+ /* 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_iput;
+ goto out_sput;
}
- d_set_d_op(sb->s_root, &sdcardfs_ci_dops);
/* link the upper and lower dentries */
sb->s_root->d_fsdata = NULL;
@@ -257,44 +345,132 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
/* set the lower dentries for s_root */
sdcardfs_set_lower_path(sb->s_root, &lower_path);
- /*
- * No need to call interpose because we already have a positive
- * dentry, which was instantiated by d_make_root. Just need to
- * d_rehash it.
- */
- d_rehash(sb->s_root);
-
- /* setup permission policy */
- sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
- mutex_lock(&sdcardfs_super_list_lock);
- if(sb_info->options.multiuser) {
- setup_derived_state(sb->s_root->d_inode, PERM_PRE_ROOT, sb_info->options.fs_user_id, AID_ROOT, false);
- 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, 00755);*/
- } else {
- setup_derived_state(sb->s_root->d_inode, PERM_ROOT, sb_info->options.fs_low_uid, AID_ROOT, false);
- snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
+ #ifdef CONFIG_SECURITY_SELINUX
+ security_secctx_to_secid(SDCARDFS_LOWER_SECCTX,
+ strlen(SDCARDFS_LOWER_SECCTX),
+ &sb_info->lower_secid);
+ #endif
+
+ /* call interpose to create the upper level inode */
+ err = sdcardfs_interpose(sb->s_root, sb, &lower_path);
+ if (!err) {
+ /* setup permission policy */
+ switch(sb_info->options.derive) {
+ case DERIVE_NONE:
+ setup_derived_state(sb->s_root->d_inode,
+ PERM_ROOT, 0, AID_ROOT, AID_SDCARD_RW, 00775);
+ sb_info->obbpath_s = NULL;
+ /* Secure Zone panzh2 record the owner sd card path */
+ memset(sb_info->ownersdcard_s, 0, PATH_MAX);
+ break;
+ case DERIVE_LEGACY:
+ /* Legacy behavior used to support internal multiuser layout which
+ * places user_id at the top directory level, with the actual roots
+ * just below that. Shared OBB path is also at top level. */
+ setup_derived_state(sb->s_root->d_inode,
+ PERM_LEGACY_PRE_ROOT, 0, AID_ROOT, AID_SDCARD_R, 00771);
+ /* initialize the obbpath string and lookup the path
+ * sb_info->obb_path will be deactivated by path_put
+ * on sdcardfs_put_super */
+ sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
+ snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name);
+ //printk(KERN_INFO "sdcardfs: legacy oobpath -> %s\n", sb_info->obbpath_s);
+ err = prepare_dir(sb_info->obbpath_s,
+ sb_info->options.fs_low_uid,
+ sb_info->options.fs_low_gid, 00755);
+ /* Secure Zone panzh2 record the owner sd card path */
+ snprintf(sb_info->ownersdcard_s, PATH_MAX, "%s/shared", dev_name);
+ err = prepare_dir(sb_info->ownersdcard_s,
+ sb_info->options.fs_low_uid,
+ sb_info->options.fs_low_gid, 00755);
+ if(err)
+ printk(KERN_ERR "sdcardfs: %s: %d, error on creating %s\n",
+ __func__,__LINE__, sb_info->obbpath_s);
+ break;
+ case DERIVE_UNIFIED:
+ /* Unified multiuser layout which places secondary user_id under
+ * /Android/user and shared OBB path under /Android/obb. */
+ setup_derived_state(sb->s_root->d_inode,
+ PERM_ROOT, 0, AID_ROOT, AID_SDCARD_R, 00771);
+
+ sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
+ snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
+ /* Secure Zone panzh2 record the owner sd card path */
+ snprintf(sb_info->ownersdcard_s, PATH_MAX, "%s/shared", dev_name);
+ //printk(KERN_INFO "sdcardfs: unified oobpath -> %s\n", sb_info->obbpath_s);
+ break;
+ case DERIVE_PUBLIC:
+ setup_derived_state(sb->s_root->d_inode,
+ PERM_ROOT, 0,
+ sb_info->options.upper_perms.uid,
+ sb_info->options.upper_perms.gid,
+ 00711);
+ /* initialize the obbpath string and lookup the path
+ * sb_info->obb_path will be deactivated by path_put
+ * on sdcardfs_put_super */
+ sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
+ snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
+ //printk(KERN_INFO "sdcardfs: legacy oobpath -> %s\n", sb_info->obbpath_s);
+ err = prepare_dir(sb_info->obbpath_s,
+ sb_info->options.fs_low_uid,
+ sb_info->options.fs_low_gid, 00775);
+ /* Secure Zone panzh2 record the owner sd card path */
+ snprintf(sb_info->ownersdcard_s, PATH_MAX, "%s/shared", dev_name);
+ err = prepare_dir(sb_info->ownersdcard_s,
+ sb_info->options.fs_low_uid,
+ sb_info->options.fs_low_gid, 00755);
+ if(err)
+ printk(KERN_ERR "sdcardfs: %s: %d, error on creating %s\n",
+ __func__,__LINE__, sb_info->obbpath_s);
+ break;
+ case DERIVE_MULTI:
+ setup_derived_state(sb->s_root->d_inode,
+ PERM_LEGACY_PRE_ROOT, 0,
+ sb_info->options.upper_perms.uid,
+ sb_info->options.upper_perms.gid,
+ 00711);
+ /* initialize the obbpath string and lookup the path
+ * sb_info->obb_path will be deactivated by path_put
+ * on sdcardfs_put_super */
+ sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
+ snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name);
+ //printk(KERN_INFO "sdcardfs: legacy oobpath -> %s\n", sb_info->obbpath_s);
+ err = prepare_dir(sb_info->obbpath_s,
+ sb_info->options.fs_low_uid,
+ sb_info->options.fs_low_gid, 00775);
+ /* Secure Zone panzh2 record the owner sd card path */
+ snprintf(sb_info->ownersdcard_s, PATH_MAX, "%s/shared", dev_name);
+ err = prepare_dir(sb_info->ownersdcard_s,
+ sb_info->options.fs_low_uid,
+ sb_info->options.fs_low_gid, 00755);
+ if(err)
+ printk(KERN_ERR "sdcardfs: %s: %d, error on creating %s\n",
+ __func__,__LINE__, sb_info->obbpath_s);
+ break;
+ }
+ fix_derived_permission(sb->s_root->d_inode);
+//2015.01.04 merge from Nxx50
+ sb_info->devpath = kzalloc(PATH_MAX, GFP_KERNEL);
+ if(sb_info->devpath && dev_name)
+ memcpy(sb_info->devpath, dev_name, PATH_MAX);
+//end for devpath
+ if (!silent && !err)
+ printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n",
+ dev_name, lower_sb->s_type->name);
+ sdcardfs_add_super(sb_info, sb);
+ goto out;
}
- fix_derived_permission(sb->s_root->d_inode);
- sb_info->sb = sb;
- list_add(&sb_info->list, &sdcardfs_super_list);
- mutex_unlock(&sdcardfs_super_list_lock);
+ /* else error: fall through */
- if (!silent)
- printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n",
- dev_name, lower_sb->s_type->name);
- goto out; /* all is well */
+ SDFS_ERR("sdcardfs: mount error !!! \n");
- /* no longer needed: free_dentry_private_data(sb->s_root); */
+ free_dentry_private_data(sb->s_root);
out_freeroot:
dput(sb->s_root);
-out_iput:
- iput(inode);
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;
@@ -331,7 +507,7 @@ static struct dentry *mount_nodev_with_options(struct file_system_type *fs_type,
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.
*/
@@ -339,22 +515,11 @@ struct dentry *sdcardfs_mount(struct file_system_type *fs_type, int flags,
raw_data, sdcardfs_read_super);
}
-void sdcardfs_kill_sb(struct super_block *sb) {
- struct sdcardfs_sb_info *sbi;
- if (sb->s_magic == SDCARDFS_SUPER_MAGIC) {
- sbi = SDCARDFS_SB(sb);
- mutex_lock(&sdcardfs_super_list_lock);
- list_del(&sbi->list);
- mutex_unlock(&sdcardfs_super_list_lock);
- }
- generic_shutdown_super(sb);
-}
-
static struct file_system_type sdcardfs_fs_type = {
.owner = THIS_MODULE,
.name = SDCARDFS_NAME,
.mount = sdcardfs_mount,
- .kill_sb = sdcardfs_kill_sb,
+ .kill_sb = generic_shutdown_super,
.fs_flags = 0,
};
@@ -392,6 +557,12 @@ static void __exit exit_sdcardfs_fs(void)
pr_info("Completed sdcardfs module unload\n");
}
+bool g_sdcardfs_debug = 0;
+module_param_named(sdcardfs_debug, g_sdcardfs_debug, bool, 0644);
+MODULE_PARM_DESC(
+ sdcardfs_debug,
+ "g_sdcardfs_debug are enable and may print many SDCARDFS tag log ");
+
MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
" (http://www.fsl.cs.sunysb.edu/)");
MODULE_DESCRIPTION("Wrapfs " SDCARDFS_VERSION