Skip to content

Commit a16805f

Browse files
committed
Merge: ovl: pass realinode to ovl_encode_real_fh() instead of realdentry
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/317 ovl: support encoding fid from inode with no alias JIRA: https://issues.redhat.com/browse/RHEL-77301 CVE: CVE-2025-21654 Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Approved-by: Ian Kent <ikent@redhat.com> Approved-by: Carlos Maiolino <cmaiolino@redhat.com> Approved-by: David Howells <dhowells@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Jan Stancek <jstancek@redhat.com>
2 parents e41a399 + fc16c6d commit a16805f

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
@@ -416,13 +416,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
416416
return err;
417417
}
418418

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

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

445446
err = -EIO;
@@ -481,7 +482,7 @@ struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin)
481482
if (!ovl_can_decode_fh(origin->d_sb))
482483
return NULL;
483484

484-
return ovl_encode_real_fh(ofs, origin, false);
485+
return ovl_encode_real_fh(ofs, d_inode(origin), false);
485486
}
486487

487488
int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,
@@ -506,7 +507,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
506507
const struct ovl_fh *fh;
507508
int err;
508509

509-
fh = ovl_encode_real_fh(ofs, upper, true);
510+
fh = ovl_encode_real_fh(ofs, d_inode(upper), true);
510511
if (IS_ERR(fh))
511512
return PTR_ERR(fh);
512513

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
@@ -869,7 +869,7 @@ int ovl_copy_up_with_data(struct dentry *dentry);
869869
int ovl_maybe_copy_up(struct dentry *dentry, int flags);
870870
int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new);
871871
int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat);
872-
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
872+
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode,
873873
bool is_upper);
874874
struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin);
875875
int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,

0 commit comments

Comments
 (0)