All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yang Shi <shy828301@gmail.com>
To: Mike Rapoport <rppt@kernel.org>, Jan Kara <jack@suse.cz>
Cc: "Darrick J. Wong" <djwong@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Axel Rasmussen <axelrasmussen@google.com>,
	Eric Biggers <ebiggers@kernel.org>,
	Hillf Danton <hdanton@sina.com>,
	Matthew Wilcox <willy@infradead.org>,
	Mike Rapoport <rppt@linux.ibm.com>,
	Linux FS-devel Mailing List <linux-fsdevel@vger.kernel.org>,
	Linux MM <linux-mm@kvack.org>,
	syzkaller-bugs <syzkaller-bugs@googlegroups.com>,
	syzbot+9bd2b7adbd34b30b87e4@syzkaller.appspotmail.com
Subject: Re: [PATCH v2] secretmem: fix unhandled fault in truncate
Date: Tue, 12 Jul 2022 10:40:11 -0700	[thread overview]
Message-ID: <CAHbLzkpB59wX-U4Y4Bs4hxAZKy9JG29UtRPks1458VredwRxTg@mail.gmail.com> (raw)
In-Reply-To: <Ysfqxg9Ury1NX27N@kernel.org>

On Fri, Jul 8, 2022 at 1:29 AM Mike Rapoport <rppt@kernel.org> wrote:
>
> On Thu, Jul 07, 2022 at 03:09:32PM -0700, Yang Shi wrote:
> > On Thu, Jul 7, 2022 at 1:55 PM Darrick J. Wong <djwong@kernel.org> wrote:
> > >
> > > On Thu, Jul 07, 2022 at 10:48:00AM -0700, Yang Shi wrote:
> > > > On Thu, Jul 7, 2022 at 9:57 AM Mike Rapoport <rppt@kernel.org> wrote:
> > > > >
> > > > > Eric Biggers suggested that this happens when
> > > > > secretmem_setattr()->simple_setattr() races with secretmem_fault() so
> > > > > that a page that is faulted in by secretmem_fault() (and thus removed
> > > > > from the direct map) is zeroed by inode truncation right afterwards.
> > > > >
> > > > > Since do_truncate() takes inode_lock(), adding inode_lock_shared() to
> > > > > secretmem_fault() prevents the race.
> > > >
> > > > Should invalidate_lock be used to serialize between page fault and truncate?
> > >
> > > I would have thought so, given Documentation/filesystems/locking.rst:
> > >
> > > "->fault() is called when a previously not present pte is about to be
> > > faulted in. The filesystem must find and return the page associated with
> > > the passed in "pgoff" in the vm_fault structure. If it is possible that
> > > the page may be truncated and/or invalidated, then the filesystem must
> > > lock invalidate_lock, then ensure the page is not already truncated
> > > (invalidate_lock will block subsequent truncate), and then return with
> > > VM_FAULT_LOCKED, and the page locked. The VM will unlock the page."
> > >
> > > IIRC page faults aren't supposed to take i_rwsem because the fault could
> > > be in response to someone mmaping a file into memory and then write()ing
> > > to the same file using the mmapped region.  The write() takes
> > > inode_lock and faults on the buffer, so the fault cannot take inode_lock
> > > again.
> >
> > Do you mean writing from one part of the file to the other part of the
> > file so the "from" buffer used by copy_from_user() is part of the
> > mmaped region?
> >
> > Another possible deadlock issue by using inode_lock in page faults is
> > mmap_lock is acquired before inode_lock, but write may acquire
> > inode_lock before mmap_lock, it is a AB-BA lock pattern, but it should
> > not cause real deadlock since mmap_lock is not exclusive for page
> > faults. But such pattern should be avoided IMHO.
> >
> > > That said... I don't think memfd_secret files /can/ be written to?
>
> memfd_secret files cannot be written to, they can only be mmap()ed.
> Synchronization is only required between
> do_truncate()->...->simple_setatt() and secretmem->fault() and I don't see
> how that can deadlock.

Sure, there is no deadlock.

>
> I'm not an fs expert though, so if you think that invalidate_lock() is
> safer, I don't mind s/inode_lock/invalidate_lock/ in the patch.

IIUC invalidate_lock should be preferred per the filesystem's locking
document. And I found Jan Kara's email of the invalidate_lock
patchset, please refer to
https://lore.kernel.org/linux-mm/20210715133202.5975-1-jack@suse.cz/.

>
> > > Hard to say, since I can't find a manpage describing what that syscall
> > > does.
>
> Right, I don't see it's published :-/
>
> There is a groff version:
> https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/memfd_secret.2
>
> > > --D
> > >
> > > >
> > > > >
> > > > > Reported-by: syzbot+9bd2b7adbd34b30b87e4@syzkaller.appspotmail.com
> > > > > Suggested-by: Eric Biggers <ebiggers@kernel.org>
> > > > > Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
> > > > > ---
> > > > >
> > > > > v2: use inode_lock_shared() rather than add a new rw_sem to secretmem
> > > > >
> > > > > Axel, I didn't add your Reviewed-by because v2 is quite different.
> > > > >
> > > > >  mm/secretmem.c | 21 ++++++++++++++++-----
> > > > >  1 file changed, 16 insertions(+), 5 deletions(-)
> > > > >
> > > > > diff --git a/mm/secretmem.c b/mm/secretmem.c
> > > > > index 206ed6b40c1d..a4fabf705e4f 100644
> > > > > --- a/mm/secretmem.c
> > > > > +++ b/mm/secretmem.c
> > > > > @@ -55,22 +55,28 @@ static vm_fault_t secretmem_fault(struct vm_fault *vmf)
> > > > >         gfp_t gfp = vmf->gfp_mask;
> > > > >         unsigned long addr;
> > > > >         struct page *page;
> > > > > +       vm_fault_t ret;
> > > > >         int err;
> > > > >
> > > > >         if (((loff_t)vmf->pgoff << PAGE_SHIFT) >= i_size_read(inode))
> > > > >                 return vmf_error(-EINVAL);
> > > > >
> > > > > +       inode_lock_shared(inode);
> > > > > +
> > > > >  retry:
> > > > >         page = find_lock_page(mapping, offset);
> > > > >         if (!page) {
> > > > >                 page = alloc_page(gfp | __GFP_ZERO);
> > > > > -               if (!page)
> > > > > -                       return VM_FAULT_OOM;
> > > > > +               if (!page) {
> > > > > +                       ret = VM_FAULT_OOM;
> > > > > +                       goto out;
> > > > > +               }
> > > > >
> > > > >                 err = set_direct_map_invalid_noflush(page);
> > > > >                 if (err) {
> > > > >                         put_page(page);
> > > > > -                       return vmf_error(err);
> > > > > +                       ret = vmf_error(err);
> > > > > +                       goto out;
> > > > >                 }
> > > > >
> > > > >                 __SetPageUptodate(page);
> > > > > @@ -86,7 +92,8 @@ static vm_fault_t secretmem_fault(struct vm_fault *vmf)
> > > > >                         if (err == -EEXIST)
> > > > >                                 goto retry;
> > > > >
> > > > > -                       return vmf_error(err);
> > > > > +                       ret = vmf_error(err);
> > > > > +                       goto out;
> > > > >                 }
> > > > >
> > > > >                 addr = (unsigned long)page_address(page);
> > > > > @@ -94,7 +101,11 @@ static vm_fault_t secretmem_fault(struct vm_fault *vmf)
> > > > >         }
> > > > >
> > > > >         vmf->page = page;
> > > > > -       return VM_FAULT_LOCKED;
> > > > > +       ret = VM_FAULT_LOCKED;
> > > > > +
> > > > > +out:
> > > > > +       inode_unlock_shared(inode);
> > > > > +       return ret;
> > > > >  }
> > > > >
> > > > >  static const struct vm_operations_struct secretmem_vm_ops = {
> > > > >
> > > > > base-commit: 03c765b0e3b4cb5063276b086c76f7a612856a9a
> > > > > --
> > > > > 2.34.1
> > > > >
> > > > >
>
> --
> Sincerely yours,
> Mike.

  reply	other threads:[~2022-07-12 17:40 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-07 16:56 [PATCH v2] secretmem: fix unhandled fault in truncate Mike Rapoport
2022-07-07 17:48 ` Yang Shi
2022-07-07 20:55   ` Darrick J. Wong
2022-07-07 22:09     ` Yang Shi
2022-07-08  8:28       ` Mike Rapoport
2022-07-12 17:40         ` Yang Shi [this message]
2022-07-13 13:27           ` Jan Kara
2022-07-07 20:27 ` Axel Rasmussen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAHbLzkpB59wX-U4Y4Bs4hxAZKy9JG29UtRPks1458VredwRxTg@mail.gmail.com \
    --to=shy828301@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=djwong@kernel.org \
    --cc=ebiggers@kernel.org \
    --cc=hdanton@sina.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=rppt@kernel.org \
    --cc=rppt@linux.ibm.com \
    --cc=syzbot+9bd2b7adbd34b30b87e4@syzkaller.appspotmail.com \
    --cc=syzkaller-bugs@googlegroups.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.