Skip to content

Commit

Permalink
ovl: get_write_access() in truncate
Browse files Browse the repository at this point in the history
When truncating a file we should check write access on the underlying
inode.  And we should do so on the lower file as well (before copy-up) for
consistency.

Original patch and test case by Aihua Zhang.

 - - >o >o - - test.c - - >o >o - -
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	int ret;

	ret = truncate(argv[0], 4096);
	if (ret != -1) {
		fprintf(stderr, "truncate(argv[0]) should have failed\n");
		return 1;
	}
	if (errno != ETXTBSY) {
		perror("truncate(argv[0])");
		return 1;
	}

	return 0;
}
 - - >o >o - - >o >o - - >o >o - -

Reported-by: Aihua Zhang <zhangaihua1@huawei.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Cc: <stable@vger.kernel.org>
  • Loading branch information
Miklos Szeredi committed Jun 29, 2016
1 parent a4859d7 commit 03bea60
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions fs/overlayfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,37 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
if (err)
goto out;

if (attr->ia_valid & ATTR_SIZE) {
struct inode *realinode = d_inode(ovl_dentry_real(dentry));

err = -ETXTBSY;
if (atomic_read(&realinode->i_writecount) < 0)
goto out_drop_write;
}

err = ovl_copy_up(dentry);
if (!err) {
struct inode *winode = NULL;

upperdentry = ovl_dentry_upper(dentry);

if (attr->ia_valid & ATTR_SIZE) {
winode = d_inode(upperdentry);
err = get_write_access(winode);
if (err)
goto out_drop_write;
}

inode_lock(upperdentry->d_inode);
err = notify_change(upperdentry, attr, NULL);
if (!err)
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
inode_unlock(upperdentry->d_inode);

if (winode)
put_write_access(winode);
}
out_drop_write:
ovl_drop_write(dentry);
out:
return err;
Expand Down

0 comments on commit 03bea60

Please sign in to comment.