sdcardfs: Bring up to date with Android M permissions:
authorDaniel Rosenberg <drosen@google.com>
Thu, 4 Feb 2016 05:08:21 +0000 (21:08 -0800)
committerStricted <info@stricted.net>
Thu, 11 Oct 2018 16:03:13 +0000 (18:03 +0200)
In M, the workings of sdcardfs were changed significantly.
This brings sdcardfs into line with the changes.

Change-Id: I10e91a84a884c838feef7aa26c0a2b21f02e052e

fs/sdcardfs/Kconfig
fs/sdcardfs/derived_perm.c
fs/sdcardfs/file.c
fs/sdcardfs/inode.c
fs/sdcardfs/lookup.c
fs/sdcardfs/main.c
fs/sdcardfs/packagelist.c
fs/sdcardfs/sdcardfs.h
fs/sdcardfs/strtok.h [deleted file]
fs/sdcardfs/super.c

index d995f3eaae6dfa4a186371ba9840ffba4c2bf88f..ab25f88ebb37a574db4f4b6aea25315c5bce9e1a 100644 (file)
@@ -1,5 +1,6 @@
 config SDCARD_FS
        tristate "sdcard file system"
+       depends on CONFIGFS_FS
        default n
        help
          Sdcardfs is based on Wrapfs file system.
index 00c33a471dcc57e117458f19ae28eb9b5b47ec1e..9de45bc54f0eb1a77ff630a68252881e222127a3 100644 (file)
@@ -29,24 +29,23 @@ static void inherit_derived_state(struct inode *parent, struct inode *child)
        ci->perm = PERM_INHERIT;
        ci->userid = pi->userid;
        ci->d_uid = pi->d_uid;
-       ci->d_gid = pi->d_gid;
-       ci->d_mode = pi->d_mode;
+       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, mode_t mode)
+                        userid_t userid, uid_t uid, 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->d_mode = mode;
+       info->under_android = under_android;
 }
 
-void get_derived_permission(struct dentry *parent, struct dentry *dentry)
+/* While renaming, there is a point where we want the path from dentry, but the name from newdentry */
+void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry)
 {
        struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
@@ -63,86 +62,68 @@ void get_derived_permission(struct dentry *parent, struct dentry *dentry)
 
        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);
-
-       if (sbi->options.derive == DERIVE_NONE) {
-               return;
-       }
-
        /* Derive custom permissions based on parent and current node */
        switch (parent_info->perm) {
                case PERM_INHERIT:
                        /* Already inherited above */
                        break;
-               case PERM_LEGACY_PRE_ROOT:
+               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);
+                       info->userid = simple_strtoul(newdentry->d_name.name, NULL, 10);
                        break;
                case PERM_ROOT:
                        /* Assume masked off by default. */
-                       info->d_mode = 00770;
-                       if (!strcasecmp(dentry->d_name.name, "Android")) {
+                       if (!strcasecmp(newdentry->d_name.name, "Android")) {
                                /* App-specific directories inside; let anyone traverse */
                                info->perm = PERM_ANDROID;
-                               info->d_mode = 00771;
-                       } else if (sbi->options.split_perms) {
-                               if (!strcasecmp(dentry->d_name.name, "DCIM")
-                                       || !strcasecmp(dentry->d_name.name, "Pictures")) {
-                                       info->d_gid = AID_SDCARD_PICS;
-                               } else if (!strcasecmp(dentry->d_name.name, "Alarms")
-                                               || !strcasecmp(dentry->d_name.name, "Movies")
-                                               || !strcasecmp(dentry->d_name.name, "Music")
-                                               || !strcasecmp(dentry->d_name.name, "Notifications")
-                                               || !strcasecmp(dentry->d_name.name, "Podcasts")
-                                               || !strcasecmp(dentry->d_name.name, "Ringtones")) {
-                                       info->d_gid = AID_SDCARD_AV;
-                               }
+                               info->under_android = true;
                        }
                        break;
                case PERM_ANDROID:
-                       if (!strcasecmp(dentry->d_name.name, "data")) {
+                       if (!strcasecmp(newdentry->d_name.name, "data")) {
                                /* App-specific directories inside; let anyone traverse */
                                info->perm = PERM_ANDROID_DATA;
-                               info->d_mode = 00771;
-                       } else if (!strcasecmp(dentry->d_name.name, "obb")) {
+                       } else if (!strcasecmp(newdentry->d_name.name, "obb")) {
                                /* App-specific directories inside; let anyone traverse */
                                info->perm = PERM_ANDROID_OBB;
-                               info->d_mode = 00771;
-                               // FIXME : this feature will be implemented later.
                                /* Single OBB directory is always shared */
-                       } else if (!strcasecmp(dentry->d_name.name, "user")) {
-                               /* User directories must only be accessible to system, protected
-                                * by sdcard_all. Zygote will bind mount the appropriate user-
-                                * specific path. */
-                               info->perm = PERM_ANDROID_USER;
-                               info->d_gid = AID_SDCARD_ALL;
-                               info->d_mode = 00770;
+                       } else if (!strcasecmp(newdentry->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:
-                       appid = get_appid(sbi->pkgl_id, dentry->d_name.name);
+               case PERM_ANDROID_MEDIA:
+                       appid = get_appid(sbi->pkgl_id, newdentry->d_name.name);
                        if (appid != 0) {
                                info->d_uid = multiuser_get_uid(parent_info->userid, appid);
                        }
-                       info->d_mode = 00770;
-                       break;
-               case PERM_ANDROID_USER:
-                       /* Root of a secondary user */
-                       info->perm = PERM_ROOT;
-                       info->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
-                       info->d_gid = AID_SDCARD_R;
-                       info->d_mode = 00771;
                        break;
        }
 }
 
+void get_derived_permission(struct dentry *parent, struct dentry *dentry)
+{
+       get_derived_permission_new(parent, dentry, dentry);
+}
+
+void get_derive_permissions_recursive(struct dentry *parent) {
+       struct dentry *dentry;
+       list_for_each_entry(dentry, &parent->d_subdirs, d_u.d_child) {
+               if (dentry && dentry->d_inode) {
+                       mutex_lock(&dentry->d_inode->i_mutex);
+                       get_derived_permission(parent, dentry);
+                       fix_derived_permission(dentry->d_inode);
+                       get_derive_permissions_recursive(dentry);
+                       mutex_unlock(&dentry->d_inode->i_mutex);
+               }
+       }
+}
+
 /* main function for updating derived permission */
-inline void update_derived_permission(struct dentry *dentry)
+inline void update_derived_permission_lock(struct dentry *dentry)
 {
        struct dentry *parent;
 
@@ -154,6 +135,7 @@ inline void update_derived_permission(struct dentry *dentry)
         * 1. need to check whether the dentry is updated or not
         * 2. remove the root dentry update
         */
+       mutex_lock(&dentry->d_inode->i_mutex);
        if(IS_ROOT(dentry)) {
                //setup_default_pre_root_state(dentry->d_inode);
        } else {
@@ -164,6 +146,7 @@ inline void update_derived_permission(struct dentry *dentry)
                }
        }
        fix_derived_permission(dentry->d_inode);
+       mutex_unlock(&dentry->d_inode->i_mutex);
 }
 
 int need_graft_path(struct dentry *dentry)
@@ -177,7 +160,7 @@ int need_graft_path(struct dentry *dentry)
                        !strcasecmp(dentry->d_name.name, "obb")) {
 
                /* /Android/obb is the base obbpath of DERIVED_UNIFIED */
-               if(!(sbi->options.derive == DERIVE_UNIFIED
+               if(!(sbi->options.multiuser == false
                                && parent_info->userid == 0)) {
                        ret = 1;
                }
@@ -207,8 +190,7 @@ int is_obbpath_invalid(struct dentry *dent)
                        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__);
+                               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) ||
@@ -234,21 +216,16 @@ int is_base_obbpath(struct dentry *dentry)
        struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 
        spin_lock(&SDCARDFS_D(dentry)->lock);
-       /* DERIVED_LEGACY */
-       if(parent_info->perm == PERM_LEGACY_PRE_ROOT &&
-                       !strcasecmp(dentry->d_name.name, "obb")) {
-               ret = 1;
-       }
-       /* DERIVED_UNIFIED :/Android/obb is the base obbpath */
-       else if (parent_info->perm == PERM_ANDROID &&
-                       !strcasecmp(dentry->d_name.name, "obb")) {
-               if((sbi->options.derive == DERIVE_UNIFIED
-                               && parent_info->userid == 0)) {
+       if (sbi->options.multiuser) {
+               if(parent_info->perm == PERM_PRE_ROOT &&
+                               !strcasecmp(dentry->d_name.name, "obb")) {
                        ret = 1;
                }
+       } else  if (parent_info->perm == PERM_ANDROID &&
+                       !strcasecmp(dentry->d_name.name, "obb")) {
+               ret = 1;
        }
        spin_unlock(&SDCARDFS_D(dentry)->lock);
-       dput(parent);
        return ret;
 }
 
@@ -272,8 +249,7 @@ int setup_obb_dentry(struct dentry *dentry, struct path *lower_path)
 
        if(!err) {
                /* the obbpath base has been found */
-               printk(KERN_INFO "sdcardfs: "
-                               "the sbi->obbpath is found\n");
+               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
@@ -281,8 +257,7 @@ int setup_obb_dentry(struct dentry *dentry, struct path *lower_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");
+               printk(KERN_INFO "sdcardfs: the sbi->obbpath is not available\n");
        }
        return err;
 }
index 8cd51c91f2ea9f472f3be6acfaa09ca816e66d48..369051e6dce2a0cc40c0a8b0225e1440ec07e6d8 100644 (file)
@@ -209,7 +209,6 @@ static int sdcardfs_open(struct inode *inode, struct file *file)
        struct dentry *parent = dget_parent(dentry);
        struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        const struct cred *saved_cred = NULL;
-       int has_rw;
 
        /* don't open unhashed/deleted files */
        if (d_unhashed(dentry)) {
@@ -217,11 +216,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file)
                goto out_err;
        }
 
-       has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
-
-       if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name,
-                               sbi->options.derive,
-                               open_flags_to_access_mode(file->f_flags), has_rw)) {
+       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);
@@ -257,8 +252,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file)
        if (err)
                kfree(SDCARDFS_F(file));
        else {
-               fsstack_copy_attr_all(inode, sdcardfs_lower_inode(inode));
-               fix_derived_permission(inode);
+               sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode));
        }
 
 out_revert_cred:
index 0a6a04941b4e725f829e2ddd0f818c344b4d782e..0f4aa17645d6f8f27311007b768d66851c64e185 100644 (file)
@@ -55,11 +55,9 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
        struct dentry *lower_dentry;
        struct dentry *lower_parent_dentry = NULL;
        struct path lower_path;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        const struct cred *saved_cred = NULL;
 
-       int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
-       if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+       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);
@@ -80,7 +78,7 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
        if (err)
                goto out;
 
-       err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
+       err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, SDCARDFS_I(dir)->userid);
        if (err)
                goto out;
        fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
@@ -143,11 +141,9 @@ static int sdcardfs_unlink(struct inode *dir, struct dentry *dentry)
        struct inode *lower_dir_inode = sdcardfs_lower_inode(dir);
        struct dentry *lower_dir_dentry;
        struct path lower_path;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        const struct cred *saved_cred = NULL;
 
-       int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
-       if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+       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);
@@ -255,8 +251,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        int fullpath_namelen;
        int touch_err = 0;
 
-       int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
-       if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+       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);
@@ -293,19 +288,19 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
                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.
+                        * 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 */
+                        * 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);
+       err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path, pi->userid);
        if (err)
                goto out;
 
@@ -314,7 +309,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        /* update number of links on parent directory */
        set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink);
 
-       if ((sbi->options.derive == DERIVE_UNIFIED) && (!strcasecmp(dentry->d_name.name, "obb"))
+       if ((!sbi->options.multiuser) && (!strcasecmp(dentry->d_name.name, "obb"))
                && (pi->perm == PERM_ANDROID) && (pi->userid == 0))
                make_nomedia_in_obb = 1;
 
@@ -371,12 +366,9 @@ static int sdcardfs_rmdir(struct inode *dir, struct dentry *dentry)
        struct dentry *lower_dir_dentry;
        int err;
        struct path lower_path;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        const struct cred *saved_cred = NULL;
-       //char *path_s = NULL;
 
-       int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
-       if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
+       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);
@@ -461,14 +453,10 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct dentry *trap = NULL;
        struct dentry *new_parent = NULL;
        struct path lower_old_path, lower_new_path;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(old_dentry->d_sb);
        const struct cred *saved_cred = NULL;
 
-       int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
-       if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name,
-                       sbi->options.derive, 1, has_rw) ||
-               !check_caller_access_to_name(new_dir, new_dentry->d_name.name,
-                       sbi->options.derive, 1, has_rw)) {
+       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);
@@ -504,26 +492,31 @@ static int sdcardfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                goto out;
 
        /* Copy attrs from lower dir, but i_uid/i_gid */
-       fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
+       sdcardfs_copy_and_fix_attrs(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) {
-               fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
+               sdcardfs_copy_and_fix_attrs(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);
+                               update_derived_permission_lock(old_dentry);
                        }
                        dput(new_parent);
                }
        }
-
+       /* At this point, not all dentry information has been moved, so
+        * we pass along new_dentry for the name.*/
+       mutex_lock(&old_dentry->d_inode->i_mutex);
+       get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry);
+       fix_derived_permission(old_dentry->d_inode);
+       get_derive_permissions_recursive(old_dentry);
+       mutex_unlock(&old_dentry->d_inode->i_mutex);
 out:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        dput(lower_old_dir_dentry);
@@ -651,11 +644,9 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct inode *lower_inode;
        struct path lower_path;
        struct dentry *parent;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
 
        parent = dget_parent(dentry);
-       if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name,
-                                               sbi->options.derive, 0, 0)) {
+       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);
@@ -670,13 +661,10 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        lower_dentry = lower_path.dentry;
        lower_inode = sdcardfs_lower_inode(inode);
 
-       fsstack_copy_attr_all(inode, lower_inode);
+
+       sdcardfs_copy_and_fix_attrs(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);
+
 
        generic_fillattr(inode, stat);
        sdcardfs_put_lower_path(dentry, &lower_path);
@@ -691,9 +679,7 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
        struct inode *lower_inode;
        struct path lower_path;
        struct iattr lower_ia;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        struct dentry *parent;
-       int has_rw;
 
        inode = dentry->d_inode;
 
@@ -707,10 +693,8 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
        /* no vfs_XXX operations required, cred overriding will be skipped. wj*/
        if (!err) {
                /* check the Android group ID */
-               has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
                parent = dget_parent(dentry);
-               if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name,
-                                               sbi->options.derive, 1, has_rw)) {
+               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);
@@ -774,10 +758,8 @@ static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
        if (err)
                goto out;
 
-       /* get attributes from the lower inode */
-       fsstack_copy_attr_all(inode, lower_inode);
-       /* update derived permission of the upper inode */
-       fix_derived_permission(inode);
+       /* get attributes from the lower inode and update derived permissions */
+       sdcardfs_copy_and_fix_attrs(inode, lower_inode);
 
        /*
         * Not running fsstack_copy_inode_size(inode, lower_inode), because
index a4b94df99f3200b45454210e0f77c62ab2558d3f..f80abcb6b4675f366e826f3f374b42f539947e1e 100644 (file)
@@ -64,10 +64,17 @@ int new_dentry_private_data(struct dentry *dentry)
        return 0;
 }
 
-static int sdcardfs_inode_test(struct inode *inode, void *candidate_lower_inode)
+struct inode_data {
+       struct inode *lower_inode;
+       userid_t id;
+};
+
+static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
 {
        struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
-       if (current_lower_inode == (struct inode *)candidate_lower_inode)
+       userid_t current_userid = SDCARDFS_I(inode)->userid;
+       if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
+                       current_userid == ((struct inode_data *)candidate_data)->id)
                return 1; /* found a match */
        else
                return 0; /* no match */
@@ -79,12 +86,15 @@ static int sdcardfs_inode_set(struct inode *inode, void *lower_inode)
        return 0;
 }
 
-struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode)
+struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id)
 {
        struct sdcardfs_inode_info *info;
+       struct inode_data data;
        struct inode *inode; /* the new inode to return */
        int err;
 
+       data.id = id;
+       data.lower_inode = lower_inode;
        inode = iget5_locked(sb, /* our superblock */
                             /*
                              * hashval: we use inode number, but we can
@@ -94,7 +104,7 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode)
                             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 */
+                            &data); /* data passed to test+set fxns */
        if (!inode) {
                err = -EACCES;
                iput(lower_inode);
@@ -146,11 +156,9 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode)
                                   lower_inode->i_rdev);
 
        /* all well, copy inode attributes */
-       fsstack_copy_attr_all(inode, lower_inode);
+       sdcardfs_copy_and_fix_attrs(inode, lower_inode);
        fsstack_copy_inode_size(inode, lower_inode);
 
-       fix_derived_permission(inode);
-
        unlock_new_inode(inode);
        return inode;
 }
@@ -164,7 +172,7 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode)
  * @lower_path: the lower path (caller does path_get/put)
  */
 int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
-                    struct path *lower_path)
+                    struct path *lower_path, userid_t id)
 {
        int err = 0;
        struct inode *inode;
@@ -186,14 +194,14 @@ int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
         */
 
        /* inherit lower inode number for sdcardfs's inode */
-       inode = sdcardfs_iget(sb, lower_inode);
+       inode = sdcardfs_iget(sb, lower_inode, id);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto out;
        }
 
        d_add(dentry, inode);
-       update_derived_permission(dentry);
+       update_derived_permission_lock(dentry);
 out:
        return err;
 }
@@ -205,7 +213,7 @@ out:
  * Fills in lower_parent_path with <dentry,mnt> on success.
  */
 static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
-               unsigned int flags, struct path *lower_parent_path)
+               unsigned int flags, struct path *lower_parent_path, userid_t id)
 {
        int err = 0;
        struct vfsmount *lower_dir_mnt;
@@ -266,7 +274,7 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
                }
 
                sdcardfs_set_lower_path(dentry, &lower_path);
-               err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path);
+               err = sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
                if (err) /* path_put underlying path on error */
                        sdcardfs_put_reset_lower_path(dentry);
                goto out;
@@ -328,13 +336,11 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
        struct dentry *ret = NULL, *parent;
        struct path lower_parent_path;
        int err = 0;
-       struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
        const struct cred *saved_cred = NULL;
 
        parent = dget_parent(dentry);
 
-       if(!check_caller_access_to_name(parent->d_inode, dentry->d_name.name,
-                                               sbi->options.derive, 0, 0)) {
+       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",
@@ -354,7 +360,7 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
                goto out;
        }
 
-       ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path);
+       ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
        if (IS_ERR(ret))
        {
                goto out;
@@ -365,8 +371,10 @@ struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
                fsstack_copy_attr_times(dentry->d_inode,
                                        sdcardfs_lower_inode(dentry->d_inode));
                /* get drived permission */
+               mutex_lock(&dentry->d_inode->i_mutex);
                get_derived_permission(parent, dentry);
                fix_derived_permission(dentry->d_inode);
+               mutex_unlock(&dentry->d_inode->i_mutex);
        }
        /* update parent directory's atime */
        fsstack_copy_attr_atime(parent->d_inode,
index 5e20fd754846d9ae258090f7c30c18a5395c9d3e..130edbe186f3b14f1f6aaa970ba97d86f0cb79b9 100644 (file)
 #include <linux/parser.h>
 
 enum {
-       Opt_uid,
+       Opt_fsuid,
+       Opt_fsgid,
        Opt_gid,
-       Opt_wgid,
        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_uid, "uid=%u"},
+       {Opt_fsuid, "fsuid=%u"},
+       {Opt_fsgid, "fsgid=%u"},
        {Opt_gid, "gid=%u"},
-       {Opt_wgid, "wgid=%u"},
        {Opt_debug, "debug"},
-       {Opt_split, "split"},
-       {Opt_derive, "derive=%s"},
        {Opt_lower_fs, "lower_fs=%s"},
+       {Opt_mask, "mask=%u"},
+       {Opt_userid, "userid=%d"},
+       {Opt_multiuser, "multiuser"},
        {Opt_reserved_mb, "reserved_mb=%u"},
        {Opt_err, NULL}
 };
@@ -58,12 +60,10 @@ static int parse_options(struct super_block *sb, char *options, int silent,
        /* by default, we use AID_MEDIA_RW as uid, gid */
        opts->fs_low_uid = AID_MEDIA_RW;
        opts->fs_low_gid = AID_MEDIA_RW;
-       /* 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;
+       opts->mask = 0;
+       opts->multiuser = false;
+       opts->fs_user_id = 0;
+       opts->gid = 0;
        /* by default, we use LOWER_FS_EXT4 as lower fs type */
        opts->lower_fs = LOWER_FS_EXT4;
        /* by default, 0MB is reserved */
@@ -85,37 +85,33 @@ static int parse_options(struct super_block *sb, char *options, int silent,
                case Opt_debug:
                        *debug = 1;
                        break;
-               case Opt_uid:
+               case Opt_fsuid:
                        if (match_int(&args[0], &option))
                                return 0;
                        opts->fs_low_uid = option;
                        break;
-               case Opt_gid:
+               case Opt_fsgid:
                        if (match_int(&args[0], &option))
                                return 0;
                        opts->fs_low_gid = option;
                        break;
-               case Opt_wgid:
+               case Opt_gid:
                        if (match_int(&args[0], &option))
                                return 0;
-                       opts->write_gid = option;
+                       opts->gid = option;
                        break;
-               case Opt_split:
-                       opts->split_perms=1;
+               case Opt_userid:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       opts->fs_user_id = option;
                        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 {
-                               kfree(string_option);
-                               goto invalid_option;
-                       }
-                       kfree(string_option);
+               case Opt_mask:
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       opts->mask = option;
+                       break;
+               case Opt_multiuser:
+                       opts->multiuser = true;
                        break;
                case Opt_lower_fs:
                        string_option = match_strdup(&args[0]);
@@ -184,6 +180,11 @@ static struct dentry *sdcardfs_d_alloc_root(struct super_block *sb)
 }
 #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.
@@ -196,7 +197,6 @@ 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;
-       void *pkgl_id;
        struct inode *inode;
 
        printk(KERN_INFO "sdcardfs version 2.0\n");
@@ -215,8 +215,7 @@ 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;
        }
 
@@ -229,7 +228,6 @@ 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) {
@@ -237,14 +235,6 @@ 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);
@@ -263,7 +253,7 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
        sb->s_op = &sdcardfs_sops;
 
        /* get a new inode and allocate our root dentry */
-       inode = sdcardfs_iget(sb, lower_path.dentry->d_inode);
+       inode = sdcardfs_iget(sb, lower_path.dentry->d_inode, 0);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto out_sput;
@@ -292,41 +282,22 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
        d_rehash(sb->s_root);
 
        /* 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);
-                       err =  prepare_dir(sb_info->obbpath_s,
+       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, 00664);
-                       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);
-                       break;
+                                       sb_info->options.fs_low_gid, 00664);*/
+       } 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);
        }
        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);
 
        if (!silent)
                printk(KERN_INFO "sdcardfs: mounted on top of %s type %s\n",
@@ -341,7 +312,6 @@ out_iput:
 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;
@@ -386,11 +356,22 @@ 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        = generic_shutdown_super,
+       .kill_sb        = sdcardfs_kill_sb,
        .fs_flags       = 0,
 };
 
index 61354ff2dc2094b2417b3b4d7df027d060d6e444..cf1f8027499dd59d04c8b3ee678af2e09c50242b 100644 (file)
  */
 
 #include "sdcardfs.h"
-#include "strtok.h"
 #include <linux/hashtable.h>
-#include <linux/syscalls.h>
-#include <linux/kthread.h>
-#include <linux/inotify.h>
 #include <linux/delay.h>
 
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/configfs.h>
+
 #define STRING_BUF_SIZE                (512)
 
 struct hashtable_entry {
@@ -34,25 +37,20 @@ struct hashtable_entry {
        unsigned int value;
 };
 
+struct sb_list {
+       struct super_block *sb;
+       struct list_head list;
+};
+
 struct packagelist_data {
        DECLARE_HASHTABLE(package_to_appid,8);
-       DECLARE_HASHTABLE(appid_with_rw,7);
        struct mutex hashtable_lock;
-       struct task_struct *thread_id;
-       gid_t write_gid;
-       char *strtok_last;
-       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;
+static struct packagelist_data *pkgl_data_all;
 
-/* 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 struct kmem_cache *hashtable_entry_cachep;
 
 static unsigned int str_hash(const char *key) {
        int i;
@@ -66,62 +64,29 @@ static unsigned int str_hash(const char *key) {
        return h;
 }
 
-static int contain_appid_key(struct packagelist_data *pkgl_dat, unsigned int appid) {
-       struct hashtable_entry *hash_cur;
-
-       hash_for_each_possible(pkgl_dat->appid_with_rw, hash_cur, hlist, appid)
-               if ((void *)(uintptr_t)appid == hash_cur->key)
-                       return 1;
-
-       return 0;
-}
-
-/* Return if the calling UID holds sdcard_rw. */
-int get_caller_has_rw_locked(void *pkgl_id, derive_t derive) {
-       struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id;
-       appid_t appid;
-       int ret;
-
-       /* No additional permissions enforcement */
-       if (derive == DERIVE_NONE) {
-               return 1;
-       }
-
-       appid = multiuser_get_app_id(current_fsuid());
-       mutex_lock(&pkgl_dat->hashtable_lock);
-       ret = contain_appid_key(pkgl_dat, appid);
-       mutex_unlock(&pkgl_dat->hashtable_lock);
-       return ret;
-}
-
 appid_t get_appid(void *pkgl_id, const char *app_name)
 {
-       struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id;
+       struct packagelist_data *pkgl_dat = pkgl_data_all;
        struct hashtable_entry *hash_cur;
        unsigned int hash = str_hash(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,
-                                       derive_t derive, int w_ok, int has_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) {
@@ -132,27 +97,12 @@ int check_caller_access_to_name(struct inode *parent_node, const char* name,
                }
        }
 
-       /* No additional permissions enforcement */
-       if (derive == DERIVE_NONE) {
-               return 1;
-       }
-
        /* Root always has access; access for any other UIDs should always
         * be controlled through packages.list. */
        if (current_fsuid() == 0) {
                return 1;
        }
 
-       /* If asking to write, verify that caller either owns the
-        * parent or holds sdcard_rw. */
-       if (w_ok) {
-               if (parent_node &&
-                       (current_fsuid() == SDCARDFS_I(parent_node)->d_uid)) {
-                       return 1;
-               }
-               return has_rw;
-       }
-
        /* No extra permissions to enforce */
        return 1;
 }
@@ -170,14 +120,13 @@ int open_flags_to_access_mode(int open_flags) {
        }
 }
 
-static int insert_str_to_int(struct packagelist_data *pkgl_dat, char *key,
+static int insert_str_to_int_lock(struct packagelist_data *pkgl_dat, char *key,
                unsigned 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;
@@ -193,245 +142,278 @@ static int insert_str_to_int(struct packagelist_data *pkgl_dat, char *key,
        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 fixup_perms(struct super_block *sb) {
+       if (sb && sb->s_magic == SDCARDFS_SUPER_MAGIC) {
+               mutex_lock(&sb->s_root->d_inode->i_mutex);
+               get_derive_permissions_recursive(sb->s_root);
+               mutex_unlock(&sb->s_root->d_inode->i_mutex);
+       }
 }
 
-static int insert_int_to_null(struct packagelist_data *pkgl_dat, unsigned int key,
-               unsigned int value)
-{
-       struct hashtable_entry *hash_cur;
-       struct hashtable_entry *new_entry;
+static int insert_str_to_int(struct packagelist_data *pkgl_dat, char *key,
+               unsigned int value) {
+       int ret;
+       struct sdcardfs_sb_info *sbinfo;
+       mutex_lock(&sdcardfs_super_list_lock);
+       mutex_lock(&pkgl_dat->hashtable_lock);
+       ret = insert_str_to_int_lock(pkgl_dat, key, value);
+       mutex_unlock(&pkgl_dat->hashtable_lock);
 
-       //printk(KERN_INFO "sdcardfs: %s: %d: %d\n", __func__, (int)key, value);
-       hash_for_each_possible(pkgl_dat->appid_with_rw, hash_cur, hlist, key) {
-               if ((void *)(uintptr_t)key == hash_cur->key) {
-                       hash_cur->value = value;
-                       return 0;
+       list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+               if (sbinfo) {
+                       fixup_perms(sbinfo->sb);
                }
        }
-       new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL);
-       if (!new_entry)
-               return -ENOMEM;
-       new_entry->key = (void *)(uintptr_t)key;
-       new_entry->value = value;
-       hash_add(pkgl_dat->appid_with_rw, &new_entry->hlist, key);
-       return 0;
+       mutex_unlock(&sdcardfs_super_list_lock);
+       return ret;
 }
 
-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);
+static void remove_str_to_int_lock(struct hashtable_entry *h_entry) {
+       kfree(h_entry->key);
+       hash_del(&h_entry->hlist);
        kmem_cache_free(hashtable_entry_cachep, h_entry);
 }
 
+static void remove_str_to_int(struct packagelist_data *pkgl_dat, const char *key)
+{
+       struct sdcardfs_sb_info *sbinfo;
+       struct hashtable_entry *hash_cur;
+       unsigned int hash = str_hash(key);
+       mutex_lock(&sdcardfs_super_list_lock);
+       mutex_lock(&pkgl_dat->hashtable_lock);
+       hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
+               if (!strcasecmp(key, hash_cur->key)) {
+                       remove_str_to_int_lock(hash_cur);
+                       break;
+               }
+       }
+       mutex_unlock(&pkgl_dat->hashtable_lock);
+       list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
+               if (sbinfo) {
+                       fixup_perms(sbinfo->sb);
+               }
+       }
+       mutex_unlock(&sdcardfs_super_list_lock);
+       return;
+}
+
 static void remove_all_hashentrys(struct packagelist_data *pkgl_dat)
 {
        struct hashtable_entry *hash_cur;
        struct hlist_node *h_t;
        int i;
-
+       mutex_lock(&pkgl_dat->hashtable_lock);
        hash_for_each_safe(pkgl_dat->package_to_appid, i, h_t, hash_cur, hlist)
-               remove_str_to_int(hash_cur);
-       hash_for_each_safe(pkgl_dat->appid_with_rw, i, h_t, hash_cur, hlist)
-               remove_int_to_null(hash_cur);
-
+               remove_str_to_int_lock(hash_cur);
+       mutex_unlock(&pkgl_dat->hashtable_lock);
        hash_init(pkgl_dat->package_to_appid);
-       hash_init(pkgl_dat->appid_with_rw);
 }
 
-static int read_package_list(struct packagelist_data *pkgl_dat) {
-       int ret;
-       int fd;
-       int read_amount;
+static struct packagelist_data * packagelist_create(void)
+{
+       struct packagelist_data *pkgl_dat;
 
-       printk(KERN_INFO "sdcardfs: read_package_list\n");
+       pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO);
+       if (!pkgl_dat) {
+                printk(KERN_ERR "sdcardfs: Failed to create hash\n");
+               return ERR_PTR(-ENOMEM);
+       }
 
-       mutex_lock(&pkgl_dat->hashtable_lock);
+       mutex_init(&pkgl_dat->hashtable_lock);
+       hash_init(pkgl_dat->package_to_appid);
+
+       return pkgl_dat;
+}
 
+static void packagelist_destroy(struct packagelist_data *pkgl_dat)
+{
        remove_all_hashentrys(pkgl_dat);
+       printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld\n");
+       kfree(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;
-       }
+struct package_appid {
+       struct config_item item;
+       int add_pid;
+};
 
-       while ((read_amount = sys_read(fd, pkgl_dat->read_buf,
-                                       sizeof(pkgl_dat->read_buf))) > 0) {
-               unsigned int appid;
-               char *token;
-               int one_line_len = 0;
-               int additional_read;
-               unsigned long ret_gid;
-
-               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 %u %*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;
-                       }
-
-                       token = strtok_r(pkgl_dat->gids_buf, ",", &pkgl_dat->strtok_last);
-                       while (token != NULL) {
-                               if (!kstrtoul(token, 10, &ret_gid) &&
-                                               (ret_gid == pkgl_dat->write_gid)) {
-                                       ret = insert_int_to_null(pkgl_dat, appid, 1);
-                                       if (ret) {
-                                               sys_close(fd);
-                                               mutex_unlock(&pkgl_dat->hashtable_lock);
-                                               return ret;
-                                       }
-                                       break;
-                               }
-                               token = strtok_r(NULL, ",", &pkgl_dat->strtok_last);
-                       }
-               }
-       }
+static inline struct package_appid *to_package_appid(struct config_item *item)
+{
+       return item ? container_of(item, struct package_appid, item) : NULL;
+}
 
-       sys_close(fd);
-       mutex_unlock(&pkgl_dat->hashtable_lock);
-       return 0;
+static struct configfs_attribute package_appid_attr_add_pid = {
+       .ca_owner = THIS_MODULE,
+       .ca_name = "appid",
+       .ca_mode = S_IRUGO | S_IWUGO,
+};
+
+static struct configfs_attribute *package_appid_attrs[] = {
+       &package_appid_attr_add_pid,
+       NULL,
+};
+
+static ssize_t package_appid_attr_show(struct config_item *item,
+                                     struct configfs_attribute *attr,
+                                     char *page)
+{
+       ssize_t count;
+       count = sprintf(page, "%d\n", get_appid(pkgl_data_all, item->ci_name));
+       return count;
 }
 
-static int packagelist_reader(void *thread_data)
+static ssize_t package_appid_attr_store(struct config_item *item,
+                                      struct configfs_attribute *attr,
+                                      const char *page, size_t count)
 {
-       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;
-       }
+       struct package_appid *package_appid = to_package_appid(item);
+       unsigned long tmp;
+       char *p = (char *) page;
+       int ret;
 
-       while (!kthread_should_stop()) {
-               if (signal_pending(current)) {
-                       ssleep(1);
-                       continue;
-               }
+       tmp = simple_strtoul(p, &p, 10);
+       if (!p || (*p && (*p != '\n')))
+               return -EINVAL;
 
-               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;
-               }
+       if (tmp > INT_MAX)
+               return -ERANGE;
+       ret = insert_str_to_int(pkgl_data_all, item->ci_name, (unsigned int)tmp);
+       package_appid->add_pid = tmp;
+       if (ret)
+               return ret;
 
-               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;
-               }
+       return count;
+}
 
-               while (res >= (int) sizeof(*event)) {
-                       event = (struct inotify_event *) (pkgl_dat->event_buf + event_pos);
+static void package_appid_release(struct config_item *item)
+{
+       printk(KERN_INFO "sdcardfs: removing %s\n", item->ci_dentry->d_name.name);
+       /* item->ci_name is freed already, so we rely on the dentry */
+       remove_str_to_int(pkgl_data_all, item->ci_dentry->d_name.name);
+       kfree(to_package_appid(item));
+}
 
-                       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;
-                       }
+static struct configfs_item_operations package_appid_item_ops = {
+       .release                = package_appid_release,
+       .show_attribute         = package_appid_attr_show,
+       .store_attribute        = package_appid_attr_store,
+};
 
-                       event_size = sizeof(*event) + event->len;
-                       res -= event_size;
-                       event_pos += event_size;
-               }
-               continue;
+static struct config_item_type package_appid_type = {
+       .ct_item_ops    = &package_appid_item_ops,
+       .ct_attrs       = package_appid_attrs,
+       .ct_owner       = THIS_MODULE,
+};
 
-interruptable_sleep:
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-       }
-       flush_signals(current);
-       sys_close(nfd);
-       return res;
+
+struct sdcardfs_packages {
+       struct config_group group;
+};
+
+static inline struct sdcardfs_packages *to_sdcardfs_packages(struct config_item *item)
+{
+       return item ? container_of(to_config_group(item), struct sdcardfs_packages, group) : NULL;
 }
 
-void * packagelist_create(gid_t write_gid)
+static struct config_item *sdcardfs_packages_make_item(struct config_group *group, const char *name)
 {
-       struct packagelist_data *pkgl_dat;
-        struct task_struct *packagelist_thread;
+       struct package_appid *package_appid;
 
-       pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO);
-       if (!pkgl_dat) {
-                printk(KERN_ERR "sdcardfs: creating kthread failed\n");
+       package_appid = kzalloc(sizeof(struct package_appid), GFP_KERNEL);
+       if (!package_appid)
                return ERR_PTR(-ENOMEM);
-       }
 
-       mutex_init(&pkgl_dat->hashtable_lock);
-       hash_init(pkgl_dat->package_to_appid);
-       hash_init(pkgl_dat->appid_with_rw);
-       pkgl_dat->write_gid = write_gid;
+       config_item_init_type_name(&package_appid->item, name,
+                                  &package_appid_type);
+
+       package_appid->add_pid = 0;
 
-        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;
+       return &package_appid->item;
+}
 
-       printk(KERN_INFO "sdcardfs: created packagelist pkgld/%d\n",
-                               (int)pkgl_dat->thread_id->pid);
+static struct configfs_attribute sdcardfs_packages_attr_description = {
+       .ca_owner = THIS_MODULE,
+       .ca_name = "packages_gid.list",
+       .ca_mode = S_IRUGO,
+};
 
-       return (void *)pkgl_dat;
+static struct configfs_attribute *sdcardfs_packages_attrs[] = {
+       &sdcardfs_packages_attr_description,
+       NULL,
+};
+
+static ssize_t packages_attr_show(struct config_item *item,
+                                        struct configfs_attribute *attr,
+                                        char *page)
+{
+       struct hashtable_entry *hash_cur;
+       struct hlist_node *h_t;
+       int i;
+       int count = 0;
+       mutex_lock(&pkgl_data_all->hashtable_lock);
+       hash_for_each_safe(pkgl_data_all->package_to_appid, i, h_t, hash_cur, hlist)
+               count += snprintf(page + count, PAGE_SIZE - count, "%s %d\n", (char *)hash_cur->key, hash_cur->value);
+       mutex_unlock(&pkgl_data_all->hashtable_lock);
+
+
+       return count;
 }
 
-void packagelist_destroy(void *pkgl_id)
+static void sdcardfs_packages_release(struct config_item *item)
 {
-       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);
+       printk(KERN_INFO "sdcardfs: destroyed something?\n");
+       kfree(to_sdcardfs_packages(item));
+}
+
+static struct configfs_item_operations sdcardfs_packages_item_ops = {
+       .release        = sdcardfs_packages_release,
+       .show_attribute = packages_attr_show,
+};
+
+/*
+ * Note that, since no extra work is required on ->drop_item(),
+ * no ->drop_item() is provided.
+ */
+static struct configfs_group_operations sdcardfs_packages_group_ops = {
+       .make_item      = sdcardfs_packages_make_item,
+};
+
+static struct config_item_type sdcardfs_packages_type = {
+       .ct_item_ops    = &sdcardfs_packages_item_ops,
+       .ct_group_ops   = &sdcardfs_packages_group_ops,
+       .ct_attrs       = sdcardfs_packages_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct configfs_subsystem sdcardfs_packages_subsys = {
+       .su_group = {
+               .cg_item = {
+                       .ci_namebuf = "sdcardfs",
+                       .ci_type = &sdcardfs_packages_type,
+               },
+       },
+};
+
+static int __init configfs_sdcardfs_init(void)
+{
+       int ret;
+       struct configfs_subsystem *subsys = &sdcardfs_packages_subsys;
+
+       config_group_init(&subsys->su_group);
+       mutex_init(&subsys->su_mutex);
+       ret = configfs_register_subsystem(subsys);
+       if (ret) {
+               printk(KERN_ERR "Error %d while registering subsystem %s\n",
+                      ret,
+                      subsys->su_group.cg_item.ci_namebuf);
+       }
+       return ret;
+}
+
+static void __exit configfs_sdcardfs_exit(void)
+{
+       configfs_unregister_subsystem(&sdcardfs_packages_subsys);
 }
 
 int packagelist_init(void)
@@ -444,13 +426,15 @@ int packagelist_init(void)
                return -ENOMEM;
        }
 
+       pkgl_data_all = packagelist_create();
+       configfs_sdcardfs_init();
         return 0;
 }
 
 void packagelist_exit(void)
 {
+       configfs_sdcardfs_exit();
+       packagelist_destroy(pkgl_data_all);
        if (hashtable_entry_cachep)
                kmem_cache_destroy(hashtable_entry_cachep);
 }
-
-
index 540459add4a049126b1828ce24d2df3fbb1f96bc..10b2afb2a424e876690ed5f39d1373c4090d4cb5 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/types.h>
 #include <linux/security.h>
 #include <linux/string.h>
+#include <linux/list.h>
 #include "multiuser.h"
 
 /* the file system name */
 #define fix_derived_permission(x)      \
        do {                                            \
                (x)->i_uid = SDCARDFS_I(x)->d_uid;      \
-               (x)->i_gid = SDCARDFS_I(x)->d_gid;      \
-               (x)->i_mode = ((x)->i_mode & S_IFMT) | SDCARDFS_I(x)->d_mode;\
+               (x)->i_gid = get_gid(SDCARDFS_I(x));    \
+               (x)->i_mode = ((x)->i_mode & S_IFMT) | get_mode(SDCARDFS_I(x));\
        } while (0)
 
+
 /* OVERRIDE_CRED() and REVERT_CRED()
  *     OVERRID_CRED()
  *             backup original task->cred
                (int)current->cred->fsuid,              \
                (int)current->cred->fsgid);
 
-/* Android 4.4 support */
+/* Android 5.0 support */
 
 /* 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_LEGACY_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/user" */
-       PERM_ANDROID_USER,
+    /* 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,
 } perm_t;
 
-/* Permissions structure to derive */
-typedef enum {
-       DERIVE_NONE,
-       DERIVE_LEGACY,
-       DERIVE_UNIFIED,
-} derive_t;
-
 typedef enum {
        LOWER_FS_EXT4,
        LOWER_FS_FAT,
@@ -161,9 +156,9 @@ extern void free_dentry_private_data(struct dentry *dentry);
 extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
                                unsigned int flags);
 extern struct inode *sdcardfs_iget(struct super_block *sb,
-                                struct inode *lower_inode);
+                                struct inode *lower_inode, userid_t id);
 extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
-                           struct path *lower_path);
+                           struct path *lower_path, userid_t id);
 
 /* file private data */
 struct sdcardfs_file_info {
@@ -174,18 +169,16 @@ struct sdcardfs_file_info {
 /* sdcardfs inode data in memory */
 struct sdcardfs_inode_info {
        struct inode *lower_inode;
-       /* state derived based on current position in hierachy
-        * caution: d_mode does not include file types
-        */
+       /* state derived based on current position in hierachy */
        perm_t perm;
        userid_t userid;
        uid_t d_uid;
-       gid_t d_gid;
-       mode_t d_mode;
+       bool under_android;
 
        struct inode vfs_inode;
 };
 
+
 /* sdcardfs dentry data in memory */
 struct sdcardfs_dentry_info {
        spinlock_t lock;        /* protects lower_path */
@@ -196,15 +189,17 @@ struct sdcardfs_dentry_info {
 struct sdcardfs_mount_options {
        uid_t fs_low_uid;
        gid_t fs_low_gid;
-       gid_t write_gid;
-       int split_perms;
-       derive_t derive;
+       userid_t fs_user_id;
+       gid_t gid;
        lower_fs_t lower_fs;
+       mode_t mask;
+       bool multiuser;
        unsigned int reserved_mb;
 };
 
 /* sdcardfs super-block data in memory */
 struct sdcardfs_sb_info {
+       struct super_block *sb;
        struct super_block *lower_sb;
        /* derived perm policy : some of options have been added
         * to sdcardfs_mount_options (Android 4.4 support) */
@@ -213,6 +208,7 @@ struct sdcardfs_sb_info {
        char *obbpath_s;
        struct path obbpath;
        void *pkgl_id;
+       struct list_head list;
 };
 
 /*
@@ -331,6 +327,44 @@ static inline void sdcardfs_put_reset_##pname(const struct dentry *dent) \
 SDCARDFS_DENT_FUNC(lower_path)
 SDCARDFS_DENT_FUNC(orig_path)
 
+static inline int get_gid(struct sdcardfs_inode_info *info) {
+       struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
+       if (sb_info->options.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. */
+               return AID_SDCARD_RW;
+       } else {
+               return multiuser_get_uid(info->userid, sb_info->options.gid);
+       }
+}
+static inline int get_mode(struct sdcardfs_inode_info *info) {
+       int owner_mode;
+       int filtered_mode;
+       struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
+       int visible_mode = 0775 & ~sb_info->options.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 = 0711;
+       } else if (info->under_android) {
+               /* Block "other" access to Android directories, since only apps
+               * belonging to a specific user should be in there; we still
+               * leave +x open for the default view. */
+               if (sb_info->options.gid == AID_SDCARD_RW) {
+                       visible_mode = visible_mode & ~0006;
+               } else {
+                       visible_mode = visible_mode & ~0007;
+               }
+       }
+       owner_mode = info->lower_inode->i_mode & 0700;
+       filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6));
+       return filtered_mode;
+}
+
 static inline int has_graft_path(const struct dentry *dent)
 {
        int ret = 0;
@@ -364,22 +398,24 @@ static inline void sdcardfs_put_real_lower(const struct dentry *dent,
                sdcardfs_put_lower_path(dent, real_lower);
 }
 
+extern struct mutex sdcardfs_super_list_lock;
+extern struct list_head sdcardfs_super_list;
+
 /* for packagelist.c */
-extern int get_caller_has_rw_locked(void *pkgl_id, derive_t derive);
 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,
-                                        derive_t derive, int w_ok, int has_rw);
+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(gid_t write_gid);
-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, mode_t mode);
+                       userid_t userid, uid_t uid, bool under_android);
 extern void get_derived_permission(struct dentry *parent, struct dentry *dentry);
-extern void update_derived_permission(struct dentry *dentry);
+extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry);
+extern void get_derive_permissions_recursive(struct dentry *parent);
+
+extern void update_derived_permission_lock(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);
@@ -483,4 +519,18 @@ static inline int check_min_free_space(struct dentry *dentry, size_t size, int d
                return 1;
 }
 
+/* Copies attrs and maintains sdcardfs managed attrs */
+static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src)
+{
+       dest->i_mode = (src->i_mode  & S_IFMT) | get_mode(SDCARDFS_I(dest));
+       dest->i_uid = SDCARDFS_I(dest)->d_uid;
+       dest->i_gid = get_gid(SDCARDFS_I(dest));
+       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);
+}
 #endif /* not _SDCARDFS_H_ */
diff --git a/fs/sdcardfs/strtok.h b/fs/sdcardfs/strtok.h
deleted file mode 100644 (file)
index 50ab25a..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * fs/sdcardfs/strtok.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.
- */
-
-static char *
-strtok_r(char *s, const char *delim, char **last)
-{
-        char *spanp;
-        int c, sc;
-        char *tok;
-
-
-        /* if (s == NULL && (s = *last) == NULL)
-                return NULL;     */
-        if (s == NULL) {
-                s = *last;
-                if (s == NULL)
-                        return NULL;
-        }
-
-        /*
-         * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
-         */
-cont:
-        c = *s++;
-        for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
-                if (c == sc)
-                        goto cont;
-        }
-
-        if (c == 0) {           /* no non-delimiter characters */
-                *last = NULL;
-                return NULL;
-        }
-        tok = s - 1;
-
-        /*
-         * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
-         * Note that delim must have one NUL; we stop if we see that, too.
-         */
-        for (;;) {
-                c = *s++;
-                spanp = (char *)delim;
-                do {
-                        sc = *spanp++;
-                        if (sc == c) {
-                                if (c == 0)
-                                        s = NULL;
-                                else
-                                        s[-1] = 0;
-                                *last = s;
-                                return tok;
-                        }
-                } while (sc != 0);
-        }
-
-        /* NOTREACHED */
-}
-
index f153ce1b8cf398de0d57f6460901cd9ade754608..1d6490128c9905f36eba30e0e896a4634ee5dc32 100644 (file)
@@ -46,9 +46,6 @@ static void sdcardfs_put_super(struct super_block *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;
 }
@@ -203,12 +200,8 @@ static int sdcardfs_show_options(struct seq_file *m, struct dentry *root)
        if (opts->fs_low_gid != 0)
                seq_printf(m, ",gid=%u", opts->fs_low_gid);
 
-       if (opts->derive == DERIVE_NONE)
-               seq_printf(m, ",derive=none");
-       else if (opts->derive == DERIVE_LEGACY)
-               seq_printf(m, ",derive=legacy");
-       else if (opts->derive == DERIVE_UNIFIED)
-               seq_printf(m, ",derive=unified");
+       if (opts->multiuser)
+               seq_printf(m, ",multiuser");
 
        if (opts->reserved_mb != 0)
                seq_printf(m, ",reserved=%uMB", opts->reserved_mb);