On Thu, 2025-06-26 at 08:20 +0800, zhangjian wrote: > Syzkaller found an slab-out-of-bounds in nfs_fh_to_dentry when the memory > of server_fh is not passed from user space. So I add a check for input size. > --- > fs/nfs/export.c | 12 ++++++++++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > > diff --git a/fs/nfs/export.c b/fs/nfs/export.c > index e9c233b6f..e0e77f8ca 100644 > --- a/fs/nfs/export.c > +++ b/fs/nfs/export.c > @@ -65,8 +65,8 @@ nfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > int fh_len, int fh_type) > { > struct nfs_fattr *fattr = NULL; > - struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw); > - size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; > + struct nfs_fh *server_fh; > + size_t fh_size; > const struct nfs_rpc_ops *rpc_ops; > struct dentry *dentry; > struct inode *inode; > @@ -74,6 +74,14 @@ nfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > u32 *p = fid->raw; > int ret; > > + /* check for user input size */ > + if ((char*)server_fh <= (char*)p > + || (int)((u32*)server_fh - (u32*)p + 1) < fh_len) ^^^ nit: this would probably be more readable on a single line. I'm also not sure that the int cast is necessary. Maybe it is though. > + return ERR_PTR(-EINVAL); > + > + fh_size = offsetof(struct nfs_fh, data) + server_fh->size; > + len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); > + > /* NULL translates to ESTALE */ > if (fh_len < len || fh_type != len) > return NULL; This seems like a reasonable thing to check for. If the fh is so short that we can't get to the EMBED_FH, then it's definitely invalid. Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>