Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e2d3bbc authored by Daniel Rosenberg's avatar Daniel Rosenberg
Browse files

sdcardfs: Bring up to date with Android M permissions:

In M, the workings of sdcardfs were changed significantly.
This brings sdcardfs into line with the changes.

Change-Id: I10e91a84a884c838feef7aa26c0a2b21f02e052e
parent a1590fbe
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
config SDCARD_FS
	tristate "sdcard file system"
	depends on CONFIGFS_FS
	default n
	help
	  Sdcardfs is based on Wrapfs file system.
+47 −72
Original line number Diff line number Diff line
@@ -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_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 &&
	if (sbi->options.multiuser) {
		if(parent_info->perm == PERM_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 &&
	} else  if (parent_info->perm == PERM_ANDROID &&
			!strcasecmp(dentry->d_name.name, "obb")) {
		if((sbi->options.derive == DERIVE_UNIFIED
				&& parent_info->userid == 0)) {
		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;
}
+2 −8
Original line number Diff line number Diff line
@@ -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:
+30 −48
Original line number Diff line number Diff line
@@ -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);
@@ -305,7 +300,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
			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);
@@ -505,26 +493,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, d_inode(lower_new_dir_dentry));
	sdcardfs_copy_and_fix_attrs(new_dir, d_inode(lower_new_dir_dentry));
	fsstack_copy_inode_size(new_dir, d_inode(lower_new_dir_dentry));
	fix_derived_permission(new_dir);

	if (new_dir != old_dir) {
		fsstack_copy_attr_all(old_dir, d_inode(lower_old_dir_dentry));
		sdcardfs_copy_and_fix_attrs(old_dir, d_inode(lower_old_dir_dentry));
		fsstack_copy_inode_size(old_dir, d_inode(lower_old_dir_dentry));
		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(d_inode(old_dentry)) {
				get_derived_permission(new_parent, old_dentry);
				fix_derived_permission(d_inode(old_dentry));
				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(&d_inode(old_dentry)->i_mutex);
	get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry);
	fix_derived_permission(d_inode(old_dentry));
	get_derive_permissions_recursive(old_dentry);
	mutex_unlock(&d_inode(old_dentry)->i_mutex);
out:
	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
	dput(lower_old_dir_dentry);
@@ -639,9 +632,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 = d_inode(dentry);

@@ -655,10 +646,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(d_inode(parent), dentry->d_name.name,
						sbi->options.derive, 1, has_rw)) {
		if(!check_caller_access_to_name(d_inode(parent), 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);
@@ -723,10 +712,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
@@ -748,11 +735,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(d_inode(parent), dentry->d_name.name,
						sbi->options.derive, 0, 0)) {
	if(!check_caller_access_to_name(d_inode(parent), 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);
@@ -767,13 +752,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);
+24 −16
Original line number Diff line number Diff line
@@ -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,
Loading