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

Commit 03ec1392 authored by Daniel Rosenberg's avatar Daniel Rosenberg
Browse files

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.

Change-Id: I19959038309284448f1b7f232d579674ef546385
Signed-off-by: default avatarDaniel Rosenberg <drosen@google.com>
parent 8c50902e
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -187,7 +187,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;
@@ -262,7 +262,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);
@@ -275,4 +277,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
@@ -659,7 +659,7 @@ void do_coredump(const siginfo_t *siginfo)
			goto close_fail;
		if (!cprm.file->f_op->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
@@ -1598,7 +1598,7 @@ int should_remove_suid(struct dentry *dentry)
}
EXPORT_SYMBOL(should_remove_suid);

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

@@ -1607,7 +1607,7 @@ static int __remove_suid(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);
}

int file_remove_suid(struct file *file)
@@ -1630,7 +1630,7 @@ int file_remove_suid(struct file *file)
	if (killpriv)
		error = security_inode_killpriv(dentry);
	if (!error && killsuid)
		error = __remove_suid(dentry, killsuid);
		error = __remove_suid(file->f_path.mnt, dentry, killsuid);
	if (!error && (inode->i_sb->s_flags & MS_NOSEC))
		inode->i_flags |= S_NOSEC;

+14 −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;
@@ -58,10 +58,15 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,

	mutex_lock(&dentry->d_inode->i_mutex);
	/* Note any delegations or leases have already been broken: */
	ret = notify_change(dentry, &newattrs, NULL);
	ret = notify_change2(mnt, dentry, &newattrs, NULL);
	mutex_unlock(&dentry->d_inode->i_mutex);
	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(struct path *path, loff_t length)
{
@@ -106,7 +111,7 @@ long vfs_truncate(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 +160,7 @@ static 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 +177,7 @@ static 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))
@@ -190,7 +197,7 @@ static 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);
@@ -504,7 +511,7 @@ retry_deleg:
		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:
	mutex_unlock(&inode->i_mutex);
	if (delegated_inode) {
@@ -584,7 +591,7 @@ retry_deleg:
	mutex_lock(&inode->i_mutex);
	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);
	mutex_unlock(&inode->i_mutex);
	if (delegated_inode) {
		error = break_deleg_wait(&delegated_inode);
+1 −1
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ static int utimes_common(struct path *path, struct timespec *times)
	}
retry_deleg:
	mutex_lock(&inode->i_mutex);
	error = notify_change(path->dentry, &newattrs, &delegated_inode);
	error = notify_change2(path->mnt, path->dentry, &newattrs, &delegated_inode);
	mutex_unlock(&inode->i_mutex);
	if (delegated_inode) {
		error = break_deleg_wait(&delegated_inode);
Loading