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

Commit 04436665 authored by Daniel Rosenberg's avatar Daniel Rosenberg Committed by Alistair Delva
Browse files

ANDROID: vfs: Add setattr2 for filesystems with per mount permissions



This allows filesystems to use their mount private data to
influence the permssions they use in setattr2. It has
been separated into a new call to avoid disrupting current
setattr users.

Test: HiKey/X15 + Pie + android-mainline,
      and HiKey + AOSP Maser + android-mainline,
      directories under /sdcard created,
      output of mount is right,
      CTS test collecting device infor works

Change-Id: I19959038309284448f1b7f232d579674ef546385
Signed-off-by: default avatarDaniel Rosenberg <drosen@google.com>
Signed-off-by: default avatarYongqin Liu <yongqin.liu@linaro.org>
parent c0dbfed5
Loading
Loading
Loading
Loading
+10 −2
Original line number Original line Diff line number Diff line
@@ -223,7 +223,7 @@ EXPORT_SYMBOL(setattr_copy);
 * the file open for write, as there can be no conflicting delegation in
 * the file open for write, as there can be no conflicting delegation in
 * that case.
 * that case.
 */
 */
int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
{
{
	struct inode *inode = dentry->d_inode;
	struct inode *inode = dentry->d_inode;
	umode_t mode = inode->i_mode;
	umode_t mode = inode->i_mode;
@@ -330,7 +330,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
	if (error)
	if (error)
		return error;
		return error;


	if (inode->i_op->setattr)
	if (mnt && inode->i_op->setattr2)
		error = inode->i_op->setattr2(mnt, dentry, attr);
	else if (inode->i_op->setattr)
		error = inode->i_op->setattr(dentry, attr);
		error = inode->i_op->setattr(dentry, attr);
	else
	else
		error = simple_setattr(dentry, attr);
		error = simple_setattr(dentry, attr);
@@ -343,4 +345,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de


	return error;
	return error;
}
}
EXPORT_SYMBOL(notify_change2);

int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **delegated_inode)
{
	return notify_change2(NULL, dentry, attr, delegated_inode);
}
EXPORT_SYMBOL(notify_change);
EXPORT_SYMBOL(notify_change);
+1 −1
Original line number Original line Diff line number Diff line
@@ -742,7 +742,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
			goto close_fail;
			goto close_fail;
		if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
		if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
			goto close_fail;
			goto close_fail;
		if (do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file))
		if (do_truncate2(cprm.file->f_path.mnt, cprm.file->f_path.dentry, 0, 0, cprm.file))
			goto close_fail;
			goto close_fail;
	}
	}


+3 −3
Original line number Original line Diff line number Diff line
@@ -1807,7 +1807,7 @@ int dentry_needs_remove_privs(struct dentry *dentry)
	return mask;
	return mask;
}
}


static int __remove_privs(struct dentry *dentry, int kill)
static int __remove_privs(struct vfsmount *mnt, struct dentry *dentry, int kill)
{
{
	struct iattr newattrs;
	struct iattr newattrs;


@@ -1816,7 +1816,7 @@ static int __remove_privs(struct dentry *dentry, int kill)
	 * Note we call this on write, so notify_change will not
	 * Note we call this on write, so notify_change will not
	 * encounter any conflicting delegations:
	 * encounter any conflicting delegations:
	 */
	 */
	return notify_change(dentry, &newattrs, NULL);
	return notify_change2(mnt, dentry, &newattrs, NULL);
}
}


/*
/*
@@ -1843,7 +1843,7 @@ int file_remove_privs(struct file *file)
	if (kill < 0)
	if (kill < 0)
		return kill;
		return kill;
	if (kill)
	if (kill)
		error = __remove_privs(dentry, kill);
		error = __remove_privs(file->f_path.mnt, dentry, kill);
	if (!error)
	if (!error)
		inode_has_no_xattr(inode);
		inode_has_no_xattr(inode);


+1 −1
Original line number Original line Diff line number Diff line
@@ -3003,7 +3003,7 @@ static int handle_truncate(struct file *filp)
	if (!error)
	if (!error)
		error = security_path_truncate(path);
		error = security_path_truncate(path);
	if (!error) {
	if (!error) {
		error = do_truncate(path->dentry, 0,
		error = do_truncate2(path->mnt, path->dentry, 0,
				    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
				    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
				    filp);
				    filp);
	}
	}
+16 −7
Original line number Original line Diff line number Diff line
@@ -35,8 +35,8 @@


#include "internal.h"
#include "internal.h"


int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
	struct file *filp)
		unsigned int time_attrs, struct file *filp)
{
{
	int ret;
	int ret;
	struct iattr newattrs;
	struct iattr newattrs;
@@ -61,17 +61,24 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,


	inode_lock(dentry->d_inode);
	inode_lock(dentry->d_inode);
	/* Note any delegations or leases have already been broken: */
	/* Note any delegations or leases have already been broken: */
	ret = notify_change(dentry, &newattrs, NULL);
	ret = notify_change2(mnt, dentry, &newattrs, NULL);
	inode_unlock(dentry->d_inode);
	inode_unlock(dentry->d_inode);
	return ret;
	return ret;
}
}
int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
	struct file *filp)
{
	return do_truncate2(NULL, dentry, length, time_attrs, filp);
}


long vfs_truncate(const struct path *path, loff_t length)
long vfs_truncate(const struct path *path, loff_t length)
{
{
	struct inode *inode;
	struct inode *inode;
	struct vfsmount *mnt;
	long error;
	long error;


	inode = path->dentry->d_inode;
	inode = path->dentry->d_inode;
	mnt = path->mnt;


	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
	if (S_ISDIR(inode->i_mode))
	if (S_ISDIR(inode->i_mode))
@@ -107,7 +114,7 @@ long vfs_truncate(const struct path *path, loff_t length)
	if (!error)
	if (!error)
		error = security_path_truncate(path);
		error = security_path_truncate(path);
	if (!error)
	if (!error)
		error = do_truncate(path->dentry, length, 0, NULL);
		error = do_truncate2(mnt, path->dentry, length, 0, NULL);


put_write_and_out:
put_write_and_out:
	put_write_access(inode);
	put_write_access(inode);
@@ -156,6 +163,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
{
{
	struct inode *inode;
	struct inode *inode;
	struct dentry *dentry;
	struct dentry *dentry;
	struct vfsmount *mnt;
	struct fd f;
	struct fd f;
	int error;
	int error;


@@ -172,6 +180,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
		small = 0;
		small = 0;


	dentry = f.file->f_path.dentry;
	dentry = f.file->f_path.dentry;
	mnt = f.file->f_path.mnt;
	inode = dentry->d_inode;
	inode = dentry->d_inode;
	error = -EINVAL;
	error = -EINVAL;
	if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
	if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
@@ -192,7 +201,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
	if (!error)
	if (!error)
		error = security_path_truncate(&f.file->f_path);
		error = security_path_truncate(&f.file->f_path);
	if (!error)
	if (!error)
		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
		error = do_truncate2(mnt, dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
	sb_end_write(inode->i_sb);
	sb_end_write(inode->i_sb);
out_putf:
out_putf:
	fdput(f);
	fdput(f);
@@ -539,7 +548,7 @@ static int chmod_common(const struct path *path, umode_t mode)
		goto out_unlock;
		goto out_unlock;
	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
	error = notify_change(path->dentry, &newattrs, &delegated_inode);
	error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
out_unlock:
out_unlock:
	inode_unlock(inode);
	inode_unlock(inode);
	if (delegated_inode) {
	if (delegated_inode) {
@@ -630,7 +639,7 @@ static int chown_common(const struct path *path, uid_t user, gid_t group)
	inode_lock(inode);
	inode_lock(inode);
	error = security_path_chown(path, uid, gid);
	error = security_path_chown(path, uid, gid);
	if (!error)
	if (!error)
		error = notify_change(path->dentry, &newattrs, &delegated_inode);
		error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
	inode_unlock(inode);
	inode_unlock(inode);
	if (delegated_inode) {
	if (delegated_inode) {
		error = break_deleg_wait(&delegated_inode);
		error = break_deleg_wait(&delegated_inode);
Loading