Skip to content

Commit 403688e

Browse files
committed
Merge tag 'ovl-fixes-6.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs
Pull overlayfs fixes from Amir Goldstein: - Fix for file reference leak regression - Fix for NULL pointer deref regression - Fixes for RCU-walk race regressions: Two of the fixes were taken from Al's RCU pathwalk race fixes series with his consent [1]. Note that unlike most of Al's series, these two patches are not about racing with ->kill_sb() and they are also very recent regressions from v6.5, so I think it's worth getting them into v6.5.y. There is also a fix for an RCU pathwalk race with ->kill_sb(), which may have been solved in vfs generic code as you suggested, but it also rids overlayfs from a nasty hack, so I think it's worth anyway. Link: https://lore.kernel.org/linux-fsdevel/20231003204749.GA800259@ZenIV/ [1] * tag 'ovl-fixes-6.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs: ovl: fix NULL pointer defer when encoding non-decodable lower fid ovl: make use of ->layers safe in rcu pathwalk ovl: fetch inode once in ovl_dentry_revalidate_common() ovl: move freeing ovl_entry past rcu delay ovl: fix file reference leak when submitting aio
2 parents 3006adf + c7242a4 commit 403688e

File tree

5 files changed

+28
-30
lines changed

5 files changed

+28
-30
lines changed

fs/overlayfs/export.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static int ovl_check_encode_origin(struct dentry *dentry)
188188

189189
/* Lower file handle for non-upper non-decodable */
190190
if (!ovl_dentry_upper(dentry) && !decodable)
191-
return 0;
191+
return 1;
192192

193193
/* Upper file handle for pure upper */
194194
if (!ovl_dentry_lower(dentry))

fs/overlayfs/file.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,6 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
341341
if (!aio_req)
342342
goto out;
343343

344-
real.flags = 0;
345344
aio_req->orig_iocb = iocb;
346345
kiocb_clone(&aio_req->iocb, iocb, get_file(real.file));
347346
aio_req->iocb.ki_complete = ovl_aio_rw_complete;
@@ -413,7 +412,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
413412
if (!aio_req)
414413
goto out;
415414

416-
real.flags = 0;
417415
aio_req->orig_iocb = iocb;
418416
kiocb_clone(&aio_req->iocb, iocb, get_file(real.file));
419417
aio_req->iocb.ki_flags = ifl;

fs/overlayfs/ovl_entry.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
struct ovl_config {
99
char *upperdir;
1010
char *workdir;
11+
char **lowerdirs;
1112
bool default_permissions;
1213
int redirect_mode;
1314
int verity_mode;
@@ -39,17 +40,8 @@ struct ovl_layer {
3940
int idx;
4041
/* One fsid per unique underlying sb (upper fsid == 0) */
4142
int fsid;
42-
char *name;
4343
};
4444

45-
/*
46-
* ovl_free_fs() relies on @mnt being the first member when unmounting
47-
* the private mounts created for each layer. Let's check both the
48-
* offset and type.
49-
*/
50-
static_assert(offsetof(struct ovl_layer, mnt) == 0);
51-
static_assert(__same_type(typeof_member(struct ovl_layer, mnt), struct vfsmount *));
52-
5345
struct ovl_path {
5446
const struct ovl_layer *layer;
5547
struct dentry *dentry;

fs/overlayfs/params.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -752,19 +752,20 @@ void ovl_free_fs(struct ovl_fs *ofs)
752752
if (ofs->upperdir_locked)
753753
ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root);
754754

755-
/* Hack! Reuse ofs->layers as a vfsmount array before freeing it */
756-
mounts = (struct vfsmount **) ofs->layers;
755+
/* Reuse ofs->config.lowerdirs as a vfsmount array before freeing it */
756+
mounts = (struct vfsmount **) ofs->config.lowerdirs;
757757
for (i = 0; i < ofs->numlayer; i++) {
758758
iput(ofs->layers[i].trap);
759+
kfree(ofs->config.lowerdirs[i]);
759760
mounts[i] = ofs->layers[i].mnt;
760-
kfree(ofs->layers[i].name);
761761
}
762762
kern_unmount_array(mounts, ofs->numlayer);
763763
kfree(ofs->layers);
764764
for (i = 0; i < ofs->numfs; i++)
765765
free_anon_bdev(ofs->fs[i].pseudo_dev);
766766
kfree(ofs->fs);
767767

768+
kfree(ofs->config.lowerdirs);
768769
kfree(ofs->config.upperdir);
769770
kfree(ofs->config.workdir);
770771
if (ofs->creator_cred)
@@ -949,16 +950,16 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry)
949950
struct super_block *sb = dentry->d_sb;
950951
struct ovl_fs *ofs = OVL_FS(sb);
951952
size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer;
952-
const struct ovl_layer *data_layers = &ofs->layers[nr_merged_lower];
953+
char **lowerdatadirs = &ofs->config.lowerdirs[nr_merged_lower];
953954

954-
/* ofs->layers[0] is the upper layer */
955-
seq_printf(m, ",lowerdir=%s", ofs->layers[1].name);
955+
/* lowerdirs[] starts from offset 1 */
956+
seq_printf(m, ",lowerdir=%s", ofs->config.lowerdirs[1]);
956957
/* dump regular lower layers */
957958
for (nr = 2; nr < nr_merged_lower; nr++)
958-
seq_printf(m, ":%s", ofs->layers[nr].name);
959+
seq_printf(m, ":%s", ofs->config.lowerdirs[nr]);
959960
/* dump data lower layers */
960961
for (nr = 0; nr < ofs->numdatalayer; nr++)
961-
seq_printf(m, "::%s", data_layers[nr].name);
962+
seq_printf(m, "::%s", lowerdatadirs[nr]);
962963
if (ofs->config.upperdir) {
963964
seq_show_option(m, "upperdir", ofs->config.upperdir);
964965
seq_show_option(m, "workdir", ofs->config.workdir);

fs/overlayfs/super.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ static int ovl_revalidate_real(struct dentry *d, unsigned int flags, bool weak)
104104
static int ovl_dentry_revalidate_common(struct dentry *dentry,
105105
unsigned int flags, bool weak)
106106
{
107-
struct ovl_entry *oe = OVL_E(dentry);
108-
struct ovl_path *lowerstack = ovl_lowerstack(oe);
107+
struct ovl_entry *oe;
108+
struct ovl_path *lowerstack;
109109
struct inode *inode = d_inode_rcu(dentry);
110110
struct dentry *upper;
111111
unsigned int i;
@@ -115,6 +115,8 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry,
115115
if (!inode)
116116
return -ECHILD;
117117

118+
oe = OVL_I_E(inode);
119+
lowerstack = ovl_lowerstack(oe);
118120
upper = ovl_i_dentry_upper(inode);
119121
if (upper)
120122
ret = ovl_revalidate_real(upper, flags, weak);
@@ -167,6 +169,7 @@ static void ovl_free_inode(struct inode *inode)
167169
struct ovl_inode *oi = OVL_I(inode);
168170

169171
kfree(oi->redirect);
172+
kfree(oi->oe);
170173
mutex_destroy(&oi->lock);
171174
kmem_cache_free(ovl_inode_cachep, oi);
172175
}
@@ -176,7 +179,7 @@ static void ovl_destroy_inode(struct inode *inode)
176179
struct ovl_inode *oi = OVL_I(inode);
177180

178181
dput(oi->__upperdentry);
179-
ovl_free_entry(oi->oe);
182+
ovl_stack_put(ovl_lowerstack(oi->oe), ovl_numlower(oi->oe));
180183
if (S_ISDIR(inode->i_mode))
181184
ovl_dir_cache_free(inode);
182185
else
@@ -569,11 +572,6 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs,
569572
upper_layer->idx = 0;
570573
upper_layer->fsid = 0;
571574

572-
err = -ENOMEM;
573-
upper_layer->name = kstrdup(ofs->config.upperdir, GFP_KERNEL);
574-
if (!upper_layer->name)
575-
goto out;
576-
577575
/*
578576
* Inherit SB_NOSEC flag from upperdir.
579577
*
@@ -1122,7 +1120,8 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
11221120
layers[ofs->numlayer].idx = ofs->numlayer;
11231121
layers[ofs->numlayer].fsid = fsid;
11241122
layers[ofs->numlayer].fs = &ofs->fs[fsid];
1125-
layers[ofs->numlayer].name = l->name;
1123+
/* Store for printing lowerdir=... in ovl_show_options() */
1124+
ofs->config.lowerdirs[ofs->numlayer] = l->name;
11261125
l->name = NULL;
11271126
ofs->numlayer++;
11281127
ofs->fs[fsid].is_lower = true;
@@ -1367,8 +1366,16 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
13671366
if (!layers)
13681367
goto out_err;
13691368

1369+
ofs->config.lowerdirs = kcalloc(ctx->nr + 1, sizeof(char *), GFP_KERNEL);
1370+
if (!ofs->config.lowerdirs) {
1371+
kfree(layers);
1372+
goto out_err;
1373+
}
13701374
ofs->layers = layers;
1371-
/* Layer 0 is reserved for upper even if there's no upper */
1375+
/*
1376+
* Layer 0 is reserved for upper even if there's no upper.
1377+
* For consistency, config.lowerdirs[0] is NULL.
1378+
*/
13721379
ofs->numlayer = 1;
13731380

13741381
sb->s_stack_depth = 0;

0 commit comments

Comments
 (0)