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

Commit 74cca90e authored by Daniel Rosenberg's avatar Daniel Rosenberg Committed by Alistair Strachan
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.

Bug: 120446149
Change-Id: I19959038309284448f1b7f232d579674ef546385
Signed-off-by: default avatarDaniel Rosenberg <drosen@google.com>
parent 8fd4c18e
Loading
Loading
Loading
Loading
+10 −2
Original line number 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
 * 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;
	umode_t mode = inode->i_mode;
@@ -330,7 +330,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
	if (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);
	else
		error = simple_setattr(dentry, attr);
@@ -343,4 +345,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de

	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);
+1 −1
Original line number Diff line number Diff line
@@ -742,7 +742,7 @@ void do_coredump(const siginfo_t *siginfo)
			goto close_fail;
		if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
			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;
	}

+3 −3
Original line number Diff line number Diff line
@@ -1797,7 +1797,7 @@ int dentry_needs_remove_privs(struct dentry *dentry)
	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;

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

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

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

#include "internal.h"

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

	inode_lock(dentry->d_inode);
	/* 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);
	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)
{
	struct inode *inode;
	struct vfsmount *mnt;
	long error;

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

	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
	if (S_ISDIR(inode->i_mode))
@@ -106,7 +113,7 @@ long vfs_truncate(const struct path *path, loff_t length)
	if (!error)
		error = security_path_truncate(path);
	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_access(inode);
@@ -155,6 +162,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
{
	struct inode *inode;
	struct dentry *dentry;
	struct vfsmount *mnt;
	struct fd f;
	int error;

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

	dentry = f.file->f_path.dentry;
	mnt = f.file->f_path.mnt;
	inode = dentry->d_inode;
	error = -EINVAL;
	if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
@@ -191,7 +200,7 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
	if (!error)
		error = security_path_truncate(&f.file->f_path);
	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);
out_putf:
	fdput(f);
@@ -538,7 +547,7 @@ static int chmod_common(const struct path *path, umode_t mode)
		goto out_unlock;
	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
	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:
	inode_unlock(inode);
	if (delegated_inode) {
@@ -629,7 +638,7 @@ static int chown_common(const struct path *path, uid_t user, gid_t group)
	inode_lock(inode);
	error = security_path_chown(path, uid, gid);
	if (!error)
		error = notify_change(path->dentry, &newattrs, &delegated_inode);
		error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
	inode_unlock(inode);
	if (delegated_inode) {
		error = break_deleg_wait(&delegated_inode);
Loading