On Fri, Jun 12, 2020 at 3:57 AM Mike Kravetz wrote: > > The core routine get_unmapped_area will call a filesystem specific version > of get_unmapped_area if it exists in file operations. If a file is on a > union/overlay, overlayfs does not contain a get_unmapped_area f_op and the > underlying filesystem routine may be ignored. Add an overlayfs f_op to call > the underlying f_op if it exists. > > The routine is_file_hugetlbfs() is used to determine if a file is on > hugetlbfs. This is determined by f_mode & FMODE_HUGETLBFS. Copy the mode > to the overlayfs file during open so that is_file_hugetlbfs() will work as > intended. > > These two issues can result in the BUG as shown in [1]. > > [1] https://lore.kernel.org/linux-mm/000000000000b4684e05a2968ca6@google.com/ > > Reported-by: syzbot+d6ec23007e951dadf3de@syzkaller.appspotmail.com > Signed-off-by: Miklos Szeredi > Signed-off-by: Mike Kravetz > --- > fs/overlayfs/file.c | 21 +++++++++++++++++++++ > 1 file changed, 21 insertions(+) > > diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c > index 87c362f65448..41e5746ba3c6 100644 > --- a/fs/overlayfs/file.c > +++ b/fs/overlayfs/file.c > @@ -124,6 +124,8 @@ static int ovl_real_fdget(const struct file *file, struct fd *real) > return ovl_real_fdget_meta(file, real, false); > } > > +#define OVL_F_MODE_TO_UPPER (FMODE_HUGETLBFS) > + > static int ovl_open(struct inode *inode, struct file *file) > { > struct file *realfile; > @@ -140,6 +142,9 @@ static int ovl_open(struct inode *inode, struct file *file) > if (IS_ERR(realfile)) > return PTR_ERR(realfile); > > + /* Copy modes from underlying file */ > + file->f_mode |= (realfile->f_mode & OVL_F_MODE_TO_UPPER); > + The name OVL_F_MODE_TO_UPPER is strange because ovl_open() may be opening a file from lower or from upper. Please see attached patches. They are not enough to solve the syzbot repro, but if you do want to fix hugetlb/overlay interop I think they will be necessary. Thanks, Amir.