diff options
Diffstat (limited to 'fs/sdcardfs/main.c')
| -rwxr-xr-x[-rw-r--r--] | fs/sdcardfs/main.c | 395 |
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 |
