overlayfs update for 5.16
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQSQHSd0lITzzeNWNm3h3BK/laaZPAUCYYk9CAAKCRDh3BK/laaZ PNk0AP4l7/V9QdvJ3kwzSsADZaw2859H8oIw0unJF4RaGYY/IwD/QUnj20vMpyN5 HbcyOCKdZfE6egtMKHik10ltOV8ZQQY= =LgJR -----END PGP SIGNATURE----- Merge tag 'ovl-update-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs Pull overlayfs updates from Miklos Szeredi: - Fix a regression introduced in the last cycle - Fix a use-after-free in the AIO path - Fix a bogus warning reported by syzbot * tag 'ovl-update-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: fix filattr copy-up failure ovl: fix warning in ovl_create_real() ovl: fix use after free in struct ovl_aio_req
This commit is contained in:
commit
1bdd629e5a
|
@ -140,12 +140,14 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old,
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ovl_real_fileattr_get(old, &oldfa);
|
err = ovl_real_fileattr_get(old, &oldfa);
|
||||||
if (err)
|
if (err) {
|
||||||
return err;
|
/* Ntfs-3g returns -EINVAL for "no fileattr support" */
|
||||||
|
if (err == -ENOTTY || err == -EINVAL)
|
||||||
err = ovl_real_fileattr_get(new, &newfa);
|
return 0;
|
||||||
if (err)
|
pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n",
|
||||||
|
old, err);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We cannot set immutable and append-only flags on upper inode,
|
* We cannot set immutable and append-only flags on upper inode,
|
||||||
|
@ -159,6 +161,17 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't bother copying flags if none are set */
|
||||||
|
if (!(oldfa.flags & OVL_COPY_FS_FLAGS_MASK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = ovl_real_fileattr_get(new, &newfa);
|
||||||
|
if (err) {
|
||||||
|
pr_warn("failed to retrieve upper fileattr (%pd2, err=%i)\n",
|
||||||
|
new, err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL);
|
BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL);
|
||||||
newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK;
|
newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK;
|
||||||
newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK);
|
newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK);
|
||||||
|
|
|
@ -137,8 +137,7 @@ kill_whiteout:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry,
|
int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode)
|
||||||
umode_t mode)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct dentry *d, *dentry = *newdentry;
|
struct dentry *d, *dentry = *newdentry;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
struct ovl_aio_req {
|
struct ovl_aio_req {
|
||||||
struct kiocb iocb;
|
struct kiocb iocb;
|
||||||
|
refcount_t ref;
|
||||||
struct kiocb *orig_iocb;
|
struct kiocb *orig_iocb;
|
||||||
struct fd fd;
|
struct fd fd;
|
||||||
};
|
};
|
||||||
|
@ -252,6 +253,14 @@ static rwf_t ovl_iocb_to_rwf(int ifl)
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ovl_aio_put(struct ovl_aio_req *aio_req)
|
||||||
|
{
|
||||||
|
if (refcount_dec_and_test(&aio_req->ref)) {
|
||||||
|
fdput(aio_req->fd);
|
||||||
|
kmem_cache_free(ovl_aio_request_cachep, aio_req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
|
static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
|
||||||
{
|
{
|
||||||
struct kiocb *iocb = &aio_req->iocb;
|
struct kiocb *iocb = &aio_req->iocb;
|
||||||
|
@ -268,8 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
|
||||||
}
|
}
|
||||||
|
|
||||||
orig_iocb->ki_pos = iocb->ki_pos;
|
orig_iocb->ki_pos = iocb->ki_pos;
|
||||||
fdput(aio_req->fd);
|
ovl_aio_put(aio_req);
|
||||||
kmem_cache_free(ovl_aio_request_cachep, aio_req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ovl_aio_rw_complete(struct kiocb *iocb, long res)
|
static void ovl_aio_rw_complete(struct kiocb *iocb, long res)
|
||||||
|
@ -319,7 +327,9 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||||
aio_req->orig_iocb = iocb;
|
aio_req->orig_iocb = iocb;
|
||||||
kiocb_clone(&aio_req->iocb, iocb, real.file);
|
kiocb_clone(&aio_req->iocb, iocb, real.file);
|
||||||
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
|
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
|
||||||
|
refcount_set(&aio_req->ref, 2);
|
||||||
ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter);
|
ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter);
|
||||||
|
ovl_aio_put(aio_req);
|
||||||
if (ret != -EIOCBQUEUED)
|
if (ret != -EIOCBQUEUED)
|
||||||
ovl_aio_cleanup_handler(aio_req);
|
ovl_aio_cleanup_handler(aio_req);
|
||||||
}
|
}
|
||||||
|
@ -390,7 +400,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||||
kiocb_clone(&aio_req->iocb, iocb, real.file);
|
kiocb_clone(&aio_req->iocb, iocb, real.file);
|
||||||
aio_req->iocb.ki_flags = ifl;
|
aio_req->iocb.ki_flags = ifl;
|
||||||
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
|
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
|
||||||
|
refcount_set(&aio_req->ref, 2);
|
||||||
ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter);
|
ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter);
|
||||||
|
ovl_aio_put(aio_req);
|
||||||
if (ret != -EIOCBQUEUED)
|
if (ret != -EIOCBQUEUED)
|
||||||
ovl_aio_cleanup_handler(aio_req);
|
ovl_aio_cleanup_handler(aio_req);
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,7 +610,10 @@ int ovl_real_fileattr_get(struct path *realpath, struct fileattr *fa)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return vfs_fileattr_get(realpath->dentry, fa);
|
err = vfs_fileattr_get(realpath->dentry, fa);
|
||||||
|
if (err == -ENOIOCTLCMD)
|
||||||
|
err = -ENOTTY;
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)
|
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)
|
||||||
|
|
|
@ -570,6 +570,7 @@ struct ovl_cattr {
|
||||||
|
|
||||||
#define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
|
#define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
|
||||||
|
|
||||||
|
int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode);
|
||||||
struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
|
struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
|
||||||
struct ovl_cattr *attr);
|
struct ovl_cattr *attr);
|
||||||
int ovl_cleanup(struct inode *dir, struct dentry *dentry);
|
int ovl_cleanup(struct inode *dir, struct dentry *dentry);
|
||||||
|
|
|
@ -787,10 +787,14 @@ retry:
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
work = ovl_create_real(dir, work, OVL_CATTR(attr.ia_mode));
|
err = ovl_mkdir_real(dir, &work, attr.ia_mode);
|
||||||
err = PTR_ERR(work);
|
if (err)
|
||||||
if (IS_ERR(work))
|
goto out_dput;
|
||||||
goto out_err;
|
|
||||||
|
/* Weird filesystem returning with hashed negative (kernfs)? */
|
||||||
|
err = -EINVAL;
|
||||||
|
if (d_really_is_negative(work))
|
||||||
|
goto out_dput;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to remove POSIX ACL xattrs from workdir. We are good if:
|
* Try to remove POSIX ACL xattrs from workdir. We are good if:
|
||||||
|
|
Loading…
Reference in New Issue