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

Commit a02de960 authored by David Howells's avatar David Howells
Browse files

VFS: Make more complete truncate operation available to CacheFiles



Make a more complete truncate operation available to CacheFiles (including
security checks and suchlike) so that it can use this to clear invalidated
cache files.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent ef778e7a
Loading
Loading
Loading
Loading
+27 −23
Original line number Original line Diff line number Diff line
@@ -61,33 +61,22 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
	return ret;
	return ret;
}
}


static long do_sys_truncate(const char __user *pathname, loff_t length)
long vfs_truncate(struct path *path, loff_t length)
{
{
	struct path path;
	struct inode *inode;
	struct inode *inode;
	int error;
	long error;

	error = -EINVAL;
	if (length < 0)	/* sorry, but loff_t says... */
		goto out;


	error = user_path(pathname, &path);
	inode = path->dentry->d_inode;
	if (error)
		goto out;
	inode = path.dentry->d_inode;


	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
	error = -EISDIR;
	if (S_ISDIR(inode->i_mode))
	if (S_ISDIR(inode->i_mode))
		goto dput_and_out;
		return -EISDIR;

	error = -EINVAL;
	if (!S_ISREG(inode->i_mode))
	if (!S_ISREG(inode->i_mode))
		goto dput_and_out;
		return -EINVAL;


	error = mnt_want_write(path.mnt);
	error = mnt_want_write(path->mnt);
	if (error)
	if (error)
		goto dput_and_out;
		goto out;


	error = inode_permission(inode, MAY_WRITE);
	error = inode_permission(inode, MAY_WRITE);
	if (error)
	if (error)
@@ -111,19 +100,34 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)


	error = locks_verify_truncate(inode, NULL, length);
	error = locks_verify_truncate(inode, NULL, 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_truncate(path->dentry, length, 0, NULL);


put_write_and_out:
put_write_and_out:
	put_write_access(inode);
	put_write_access(inode);
mnt_drop_write_and_out:
mnt_drop_write_and_out:
	mnt_drop_write(path.mnt);
	mnt_drop_write(path->mnt);
dput_and_out:
	path_put(&path);
out:
out:
	return error;
	return error;
}
}
EXPORT_SYMBOL_GPL(vfs_truncate);

static long do_sys_truncate(const char __user *pathname, loff_t length)
{
	struct path path;
	int error;

	if (length < 0)	/* sorry, but loff_t says... */
		return -EINVAL;

	error = user_path(pathname, &path);
	if (!error) {
		error = vfs_truncate(&path, length);
		path_put(&path);
	}
	return error;
}


SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
{
{
+1 −0
Original line number Original line Diff line number Diff line
@@ -1999,6 +1999,7 @@ struct filename {
	bool			separate; /* should "name" be freed? */
	bool			separate; /* should "name" be freed? */
};
};


extern long vfs_truncate(struct path *, loff_t);
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
		       struct file *filp);
		       struct file *filp);
extern int do_fallocate(struct file *file, int mode, loff_t offset,
extern int do_fallocate(struct file *file, int mode, loff_t offset,