static int checkentry_lsm(struct xt_secmark_target_info *info) { int err; info->secctx[SECMARK_SECCTX_MAX - 1] = '\0'; info->secid = 0; err = security_secctx_to_secid(info->secctx, strlen(info->secctx), &info->secid); if (err) { if (err == -EINVAL) pr_info("invalid security context \'%s\'\n", info->secctx); return err; } if (!info->secid) { pr_info("unable to map security context \'%s\'\n", info->secctx); return -ENOENT; } err = security_secmark_relabel_packet(info->secid); if (err) { pr_info("unable to obtain relabeling permission\n"); return err; } security_secmark_refcount_inc(); 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\n"); 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); sdcardfs_set_lower_super(sb, lower_sb); /* 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; 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); /*lenovo-sw jixj 2015.11.29 add begin for selinux merge from moto*/ #ifdef CONFIG_SECURITY_SELINUX security_secctx_to_secid(SDCARDFS_LOWER_SECCTX, strlen(SDCARDFS_LOWER_SECCTX), &sb_info->lower_secid); #endif /*lenovo-sw jixj 2015.11.29 add end*/ /* 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; 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); 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); //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); 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); 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); goto out; } /* else error: fall through */ SDFS_ERR("sdcardfs: mount error !!! \n"); 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; }
/* * There is no need to lock the esdfs_super_info's rwsem as there is no * way anyone can have a reference to the superblock at this point in time. */ static int esdfs_read_super(struct super_block *sb, const char *dev_name, void *raw_data, int silent) { int err = 0; struct super_block *lower_sb; struct path lower_path; struct esdfs_sb_info *sbi; struct inode *inode; if (!dev_name) { esdfs_msg(sb, KERN_ERR, "missing dev_name argument\n"); err = -EINVAL; goto out; } /* parse lower path */ err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &lower_path); if (err) { esdfs_msg(sb, KERN_ERR, "error accessing lower directory '%s'\n", dev_name); goto out; } /* allocate superblock private data */ sb->s_fs_info = kzalloc(sizeof(struct esdfs_sb_info), GFP_KERNEL); sbi = ESDFS_SB(sb); if (!sbi) { esdfs_msg(sb, KERN_CRIT, "read_super: out of memory\n"); err = -ENOMEM; goto out_pput; } /* set defaults and then parse the mount options */ memcpy(&sbi->lower_perms, &esdfs_perms_table[ESDFS_PERMS_LOWER_DEFAULT], sizeof(struct esdfs_perms)); memcpy(&sbi->upper_perms, &esdfs_perms_table[ESDFS_PERMS_UPPER_LEGACY], sizeof(struct esdfs_perms)); err = parse_options(sb, (char *)raw_data); if (err) goto out_free; /* set the lower superblock field of upper superblock */ lower_sb = lower_path.dentry->d_sb; atomic_inc(&lower_sb->s_active); esdfs_set_lower_super(sb, lower_sb); /* 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_op = &esdfs_sops; /* get a new inode and allocate our root dentry */ inode = esdfs_iget(sb, lower_path.dentry->d_inode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_sput; } sb->s_root = d_make_root(inode); if (!sb->s_root) { err = -ENOMEM; goto out_iput; } d_set_d_op(sb->s_root, &esdfs_dops); /* 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; /* if get here: cannot have error */ /* set the lower dentries for s_root */ esdfs_set_lower_path(sb->s_root, &lower_path); #ifdef CONFIG_SECURITY_SELINUX security_secctx_to_secid(ESDFS_LOWER_SECCTX, strlen(ESDFS_LOWER_SECCTX), &sbi->lower_secid); #endif /* * 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); if (!silent) esdfs_msg(sb, KERN_INFO, "mounted on top of %s type %s\n", dev_name, lower_sb->s_type->name); if (!ESDFS_DERIVE_PERMS(sbi)) goto out; /* let user know that we ignore this option in derived mode */ if (memcmp(&sbi->upper_perms, &esdfs_perms_table[ESDFS_PERMS_UPPER_LEGACY], sizeof(struct esdfs_perms))) esdfs_msg(sb, KERN_WARNING, "'upper' mount option ignored in derived mode\n"); /* all derived modes start with the same, basic root */ memcpy(&sbi->upper_perms, &esdfs_perms_table[ESDFS_PERMS_UPPER_DERIVED], sizeof(struct esdfs_perms)); /* * In Android 3.0 all user conent in the emulated storage tree was * stored in /data/media. Android 4.2 introduced multi-user support, * which required that the primary user's content be migrated from * /data/media to /data/media/0. The framework then uses bind mounts * to create per-process namespaces to isolate each user's tree at * /data/media/N. This approach of having each user in a common root * is now considered "legacy" by the sdcard service. */ if (test_opt(sbi, DERIVE_LEGACY)) { ESDFS_I(inode)->tree = ESDFS_TREE_ROOT_LEGACY; sbi->obb_parent = dget(sb->s_root); /* * Android 4.4 reorganized this sturcture yet again, so that the * primary user's content was again at the root. Secondary users' * content is found in Android/user/N. Emulated internal storage still * seems to use the legacy tree, but secondary external storage uses * this method. */ } else if (test_opt(sbi, DERIVE_UNIFIED)) ESDFS_I(inode)->tree = ESDFS_TREE_ROOT; /* * Later versions of Android organize user content using quantum * entanglement, which has a low probability of being supported by * this driver. */ else esdfs_msg(sb, KERN_WARNING, "unsupported derived permissions mode\n"); /* initialize root inode */ esdfs_derive_perms(sb->s_root); goto out; out_freeroot: dput(sb->s_root); out_iput: iput(inode); out_sput: /* drop refs we took earlier */ atomic_dec(&lower_sb->s_active); out_free: kfree(ESDFS_SB(sb)); sb->s_fs_info = NULL; out_pput: path_put(&lower_path); out: return err; }