Skip to content

Commit 368fcc5

Browse files
committed
Merge patch series "Fix encoding overlayfs fid for fanotify delete events"
Amir Goldstein <amir73il@gmail.com> says: This is a followup fix to the reported regression [1] that was introduced by overlayfs non-decodable file handles support in v6.6. The first fix posted two weeks ago [2] was a quick band aid which is justified on its own and is still queued on your vfs.fixes branch. This followup fix fixes the root cause of overlayfs file handle encoding failure and it also solves a bug with fanotify FAN_DELETE_SELF events on overlayfs, that was discovered from analysis of the first report. The fix to fanotify delete events was verified with a new LTP test [3]. [1] https://lore.kernel.org/linux-fsdevel/CAOQ4uxiie81voLZZi2zXS1BziXZCM24nXqPAxbu8kxXCUWdwOg@mail.gmail.com/ [2] https://lore.kernel.org/linux-fsdevel/20241219115301.465396-1-amir73il@gmail.com/ [3] https://github.com/amir73il/ltp/commits/ovl_encode_fid/ * patches from https://lore.kernel.org/r/20250105162404.357058-1-amir73il@gmail.com: ovl: support encoding fid from inode with no alias ovl: pass realinode to ovl_encode_real_fh() instead of realdentry Link: https://lore.kernel.org/r/20250105162404.357058-1-amir73il@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 03f275a + c45beeb commit 368fcc5

File tree

4 files changed

+36
-30
lines changed

4 files changed

+36
-30
lines changed

fs/overlayfs/copy_up.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,13 +415,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
415415
return err;
416416
}
417417

418-
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
418+
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode,
419419
bool is_upper)
420420
{
421421
struct ovl_fh *fh;
422422
int fh_type, dwords;
423423
int buflen = MAX_HANDLE_SZ;
424-
uuid_t *uuid = &real->d_sb->s_uuid;
424+
uuid_t *uuid = &realinode->i_sb->s_uuid;
425425
int err;
426426

427427
/* Make sure the real fid stays 32bit aligned */
@@ -438,7 +438,8 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
438438
* the price or reconnecting the dentry.
439439
*/
440440
dwords = buflen >> 2;
441-
fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0);
441+
fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid,
442+
&dwords, NULL, 0);
442443
buflen = (dwords << 2);
443444

444445
err = -EIO;
@@ -479,7 +480,7 @@ struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin)
479480
if (!ovl_can_decode_fh(origin->d_sb))
480481
return NULL;
481482

482-
return ovl_encode_real_fh(ofs, origin, false);
483+
return ovl_encode_real_fh(ofs, d_inode(origin), false);
483484
}
484485

485486
int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,
@@ -504,7 +505,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
504505
const struct ovl_fh *fh;
505506
int err;
506507

507-
fh = ovl_encode_real_fh(ofs, upper, true);
508+
fh = ovl_encode_real_fh(ofs, d_inode(upper), true);
508509
if (IS_ERR(fh))
509510
return PTR_ERR(fh);
510511

fs/overlayfs/export.c

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -176,35 +176,37 @@ static int ovl_connect_layer(struct dentry *dentry)
176176
*
177177
* Return 0 for upper file handle, > 0 for lower file handle or < 0 on error.
178178
*/
179-
static int ovl_check_encode_origin(struct dentry *dentry)
179+
static int ovl_check_encode_origin(struct inode *inode)
180180
{
181-
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
181+
struct ovl_fs *ofs = OVL_FS(inode->i_sb);
182182
bool decodable = ofs->config.nfs_export;
183+
struct dentry *dentry;
184+
int err;
183185

184186
/* No upper layer? */
185187
if (!ovl_upper_mnt(ofs))
186188
return 1;
187189

188190
/* Lower file handle for non-upper non-decodable */
189-
if (!ovl_dentry_upper(dentry) && !decodable)
191+
if (!ovl_inode_upper(inode) && !decodable)
190192
return 1;
191193

192194
/* Upper file handle for pure upper */
193-
if (!ovl_dentry_lower(dentry))
195+
if (!ovl_inode_lower(inode))
194196
return 0;
195197

196198
/*
197199
* Root is never indexed, so if there's an upper layer, encode upper for
198200
* root.
199201
*/
200-
if (dentry == dentry->d_sb->s_root)
202+
if (inode == d_inode(inode->i_sb->s_root))
201203
return 0;
202204

203205
/*
204206
* Upper decodable file handle for non-indexed upper.
205207
*/
206-
if (ovl_dentry_upper(dentry) && decodable &&
207-
!ovl_test_flag(OVL_INDEX, d_inode(dentry)))
208+
if (ovl_inode_upper(inode) && decodable &&
209+
!ovl_test_flag(OVL_INDEX, inode))
208210
return 0;
209211

210212
/*
@@ -213,14 +215,23 @@ static int ovl_check_encode_origin(struct dentry *dentry)
213215
* ovl_connect_layer() will try to make origin's layer "connected" by
214216
* copying up a "connectable" ancestor.
215217
*/
216-
if (d_is_dir(dentry) && decodable)
217-
return ovl_connect_layer(dentry);
218+
if (!decodable || !S_ISDIR(inode->i_mode))
219+
return 1;
220+
221+
dentry = d_find_any_alias(inode);
222+
if (!dentry)
223+
return -ENOENT;
224+
225+
err = ovl_connect_layer(dentry);
226+
dput(dentry);
227+
if (err < 0)
228+
return err;
218229

219230
/* Lower file handle for indexed and non-upper dir/non-dir */
220231
return 1;
221232
}
222233

223-
static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry,
234+
static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode,
224235
u32 *fid, int buflen)
225236
{
226237
struct ovl_fh *fh = NULL;
@@ -231,13 +242,13 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry,
231242
* Check if we should encode a lower or upper file handle and maybe
232243
* copy up an ancestor to make lower file handle connectable.
233244
*/
234-
err = enc_lower = ovl_check_encode_origin(dentry);
245+
err = enc_lower = ovl_check_encode_origin(inode);
235246
if (enc_lower < 0)
236247
goto fail;
237248

238249
/* Encode an upper or lower file handle */
239-
fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) :
240-
ovl_dentry_upper(dentry), !enc_lower);
250+
fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) :
251+
ovl_inode_upper(inode), !enc_lower);
241252
if (IS_ERR(fh))
242253
return PTR_ERR(fh);
243254

@@ -251,28 +262,22 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry,
251262
return err;
252263

253264
fail:
254-
pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n",
255-
dentry, err);
265+
pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n",
266+
inode->i_ino, err);
256267
goto out;
257268
}
258269

259270
static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
260271
struct inode *parent)
261272
{
262273
struct ovl_fs *ofs = OVL_FS(inode->i_sb);
263-
struct dentry *dentry;
264274
int bytes, buflen = *max_len << 2;
265275

266276
/* TODO: encode connectable file handles */
267277
if (parent)
268278
return FILEID_INVALID;
269279

270-
dentry = d_find_any_alias(inode);
271-
if (!dentry)
272-
return FILEID_INVALID;
273-
274-
bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen);
275-
dput(dentry);
280+
bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen);
276281
if (bytes <= 0)
277282
return FILEID_INVALID;
278283

fs/overlayfs/namei.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry,
542542
struct ovl_fh *fh;
543543
int err;
544544

545-
fh = ovl_encode_real_fh(ofs, real, is_upper);
545+
fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper);
546546
err = PTR_ERR(fh);
547547
if (IS_ERR(fh)) {
548548
fh = NULL;
@@ -738,7 +738,7 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin,
738738
struct ovl_fh *fh;
739739
int err;
740740

741-
fh = ovl_encode_real_fh(ofs, origin, false);
741+
fh = ovl_encode_real_fh(ofs, d_inode(origin), false);
742742
if (IS_ERR(fh))
743743
return PTR_ERR(fh);
744744

fs/overlayfs/overlayfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ int ovl_copy_up_with_data(struct dentry *dentry);
865865
int ovl_maybe_copy_up(struct dentry *dentry, int flags);
866866
int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new);
867867
int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat);
868-
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
868+
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode,
869869
bool is_upper);
870870
struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin);
871871
int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,

0 commit comments

Comments
 (0)