ovl: check IS_APPEND() on real upper inode
For overlay file open, check IS_APPEND() on the real upper inode inside d_real(), because the overlay inode does not have the S_APPEND flag and IS_APPEND() can only be checked at open time. Note that because overlayfs does not copy up the chattr inode flags (i.e. S_APPEND, S_IMMUTABLE), the IS_APPEND() check is only relevant for upper inodes that were set with chattr +a and not to lower inodes that had chattr +a before copy up. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
78757af651
commit
b0990fbbbd
|
@ -49,11 +49,28 @@ static void ovl_dentry_release(struct dentry *dentry)
|
|||
}
|
||||
}
|
||||
|
||||
static int ovl_check_append_only(struct inode *inode, int flag)
|
||||
{
|
||||
/*
|
||||
* This test was moot in vfs may_open() because overlay inode does
|
||||
* not have the S_APPEND flag, so re-check on real upper inode
|
||||
*/
|
||||
if (IS_APPEND(inode)) {
|
||||
if ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
|
||||
return -EPERM;
|
||||
if (flag & O_TRUNC)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dentry *ovl_d_real(struct dentry *dentry,
|
||||
const struct inode *inode,
|
||||
unsigned int open_flags)
|
||||
{
|
||||
struct dentry *real;
|
||||
int err;
|
||||
|
||||
if (!d_is_reg(dentry)) {
|
||||
if (!inode || inode == d_inode(dentry))
|
||||
|
@ -65,15 +82,20 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
|
|||
return dentry;
|
||||
|
||||
if (open_flags) {
|
||||
int err = ovl_open_maybe_copy_up(dentry, open_flags);
|
||||
|
||||
err = ovl_open_maybe_copy_up(dentry, open_flags);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
real = ovl_dentry_upper(dentry);
|
||||
if (real && (!inode || inode == d_inode(real)))
|
||||
if (real && (!inode || inode == d_inode(real))) {
|
||||
if (!inode) {
|
||||
err = ovl_check_append_only(d_inode(real), open_flags);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
return real;
|
||||
}
|
||||
|
||||
real = ovl_dentry_lower(dentry);
|
||||
if (!real)
|
||||
|
|
Loading…
Reference in New Issue