Skip to content

Commit 1bdd629

Browse files
committed
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
2 parents cdd39b0 + 5b0a414 commit 1bdd629

File tree

6 files changed

+46
-14
lines changed

6 files changed

+46
-14
lines changed

fs/overlayfs/copy_up.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,14 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old,
140140
int err;
141141

142142
err = ovl_real_fileattr_get(old, &oldfa);
143-
if (err)
144-
return err;
145-
146-
err = ovl_real_fileattr_get(new, &newfa);
147-
if (err)
143+
if (err) {
144+
/* Ntfs-3g returns -EINVAL for "no fileattr support" */
145+
if (err == -ENOTTY || err == -EINVAL)
146+
return 0;
147+
pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n",
148+
old, err);
148149
return err;
150+
}
149151

150152
/*
151153
* 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,
159161
return err;
160162
}
161163

164+
/* Don't bother copying flags if none are set */
165+
if (!(oldfa.flags & OVL_COPY_FS_FLAGS_MASK))
166+
return 0;
167+
168+
err = ovl_real_fileattr_get(new, &newfa);
169+
if (err) {
170+
pr_warn("failed to retrieve upper fileattr (%pd2, err=%i)\n",
171+
new, err);
172+
return err;
173+
}
174+
162175
BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL);
163176
newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK;
164177
newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK);

fs/overlayfs/dir.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,7 @@ int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct inode *dir,
137137
goto out;
138138
}
139139

140-
static int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry,
141-
umode_t mode)
140+
int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode)
142141
{
143142
int err;
144143
struct dentry *d, *dentry = *newdentry;

fs/overlayfs/file.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
struct ovl_aio_req {
1919
struct kiocb iocb;
20+
refcount_t ref;
2021
struct kiocb *orig_iocb;
2122
struct fd fd;
2223
};
@@ -252,6 +253,14 @@ static rwf_t ovl_iocb_to_rwf(int ifl)
252253
return flags;
253254
}
254255

256+
static inline void ovl_aio_put(struct ovl_aio_req *aio_req)
257+
{
258+
if (refcount_dec_and_test(&aio_req->ref)) {
259+
fdput(aio_req->fd);
260+
kmem_cache_free(ovl_aio_request_cachep, aio_req);
261+
}
262+
}
263+
255264
static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
256265
{
257266
struct kiocb *iocb = &aio_req->iocb;
@@ -268,8 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req)
268277
}
269278

270279
orig_iocb->ki_pos = iocb->ki_pos;
271-
fdput(aio_req->fd);
272-
kmem_cache_free(ovl_aio_request_cachep, aio_req);
280+
ovl_aio_put(aio_req);
273281
}
274282

275283
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)
319327
aio_req->orig_iocb = iocb;
320328
kiocb_clone(&aio_req->iocb, iocb, real.file);
321329
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
330+
refcount_set(&aio_req->ref, 2);
322331
ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter);
332+
ovl_aio_put(aio_req);
323333
if (ret != -EIOCBQUEUED)
324334
ovl_aio_cleanup_handler(aio_req);
325335
}
@@ -390,7 +400,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
390400
kiocb_clone(&aio_req->iocb, iocb, real.file);
391401
aio_req->iocb.ki_flags = ifl;
392402
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
403+
refcount_set(&aio_req->ref, 2);
393404
ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter);
405+
ovl_aio_put(aio_req);
394406
if (ret != -EIOCBQUEUED)
395407
ovl_aio_cleanup_handler(aio_req);
396408
}

fs/overlayfs/inode.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,10 @@ int ovl_real_fileattr_get(struct path *realpath, struct fileattr *fa)
610610
if (err)
611611
return err;
612612

613-
return vfs_fileattr_get(realpath->dentry, fa);
613+
err = vfs_fileattr_get(realpath->dentry, fa);
614+
if (err == -ENOIOCTLCMD)
615+
err = -ENOTTY;
616+
return err;
614617
}
615618

616619
int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa)

fs/overlayfs/overlayfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ struct ovl_cattr {
570570

571571
#define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
572572

573+
int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode);
573574
struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
574575
struct ovl_cattr *attr);
575576
int ovl_cleanup(struct inode *dir, struct dentry *dentry);

fs/overlayfs/super.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -787,10 +787,14 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
787787
goto retry;
788788
}
789789

790-
work = ovl_create_real(dir, work, OVL_CATTR(attr.ia_mode));
791-
err = PTR_ERR(work);
792-
if (IS_ERR(work))
793-
goto out_err;
790+
err = ovl_mkdir_real(dir, &work, attr.ia_mode);
791+
if (err)
792+
goto out_dput;
793+
794+
/* Weird filesystem returning with hashed negative (kernfs)? */
795+
err = -EINVAL;
796+
if (d_really_is_negative(work))
797+
goto out_dput;
794798

795799
/*
796800
* Try to remove POSIX ACL xattrs from workdir. We are good if:

0 commit comments

Comments
 (0)