* [PATCH mm-unstable fix] mm: userfaultfd: add new UFFDIO_POISON ioctl: fix
@ 2023-07-12 1:27 Hugh Dickins
2023-07-12 18:16 ` Axel Rasmussen
0 siblings, 1 reply; 4+ messages in thread
From: Hugh Dickins @ 2023-07-12 1:27 UTC (permalink / raw)
To: Andrew Morton
Cc: Dan Carpenter, Hugh Dickins, Axel Rasmussen, Peter Xu, linux-mm
Smatch has observed that pte_offset_map_lock() is now allowed to fail,
and then ptl should not be unlocked. Use -EAGAIN here like elsewhere.
Signed-off-by: Hugh Dickins <hughd@google.com>
---
Axel, Peter: this seems right as a fix to the patch in mm-unstable;
but in preparing this, I noticed mfill_atomic()'s code before calling
mfill_atomic_pte(), and think that my original choice of -EFAULT was
therefore better than -EAGAIN for all of these; and that mfill_atomic()'s
BUG_ONs there would be better deleted (and is its BUG_ON(folio) safe??).
Something one of us should address, after this fixup is in akpm's tree.
mm/userfaultfd.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -300,7 +300,10 @@ static int mfill_atomic_pte_poison(pmd_t *dst_pmd,
spinlock_t *ptl;
_dst_pte = make_pte_marker(PTE_MARKER_POISONED);
+ ret = -EAGAIN;
dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+ if (!dst_pte)
+ goto out;
if (mfill_file_over_size(dst_vma, dst_addr)) {
ret = -EFAULT;
@@ -319,6 +322,7 @@ static int mfill_atomic_pte_poison(pmd_t *dst_pmd,
ret = 0;
out_unlock:
pte_unmap_unlock(dst_pte, ptl);
+out:
return ret;
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH mm-unstable fix] mm: userfaultfd: add new UFFDIO_POISON ioctl: fix
2023-07-12 1:27 [PATCH mm-unstable fix] mm: userfaultfd: add new UFFDIO_POISON ioctl: fix Hugh Dickins
@ 2023-07-12 18:16 ` Axel Rasmussen
2023-07-14 2:40 ` Hugh Dickins
0 siblings, 1 reply; 4+ messages in thread
From: Axel Rasmussen @ 2023-07-12 18:16 UTC (permalink / raw)
To: Hugh Dickins; +Cc: Andrew Morton, Dan Carpenter, Peter Xu, linux-mm
On Tue, Jul 11, 2023 at 6:27 PM Hugh Dickins <hughd@google.com> wrote:
>
> Smatch has observed that pte_offset_map_lock() is now allowed to fail,
> and then ptl should not be unlocked. Use -EAGAIN here like elsewhere.
>
> Signed-off-by: Hugh Dickins <hughd@google.com>
Looks correct to me, thanks Hugh! If it's useful, feel free to take:
Reviewed-by: Axel Rasmussen <axelrasmussen@google.com>
> ---
> Axel, Peter: this seems right as a fix to the patch in mm-unstable;
> but in preparing this, I noticed mfill_atomic()'s code before calling
> mfill_atomic_pte(), and think that my original choice of -EFAULT was
> therefore better than -EAGAIN for all of these; and that mfill_atomic()'s
> BUG_ONs there would be better deleted (and is its BUG_ON(folio) safe??).
> Something one of us should address, after this fixup is in akpm's tree.
Agreed, dealing with the BUG_ONs is something I have been meaning to
do as checkpatch bothers me about it frequently.
What this code is trying to do is to enforce the contract that: if
mfill_atomic_pte failed, then it must have released *folio and set it
to NULL. But, you're exactly right that if we had such a bug, it would
mean we leaked one page in an unusual error case - not great, but not
worth crashing the kernel either.
For UFFDIO_POISON this doesn't really apply because it doesn't
allocate or get a reference to a page in any case.
For other cases like UFFDIO_COPY where it does matter, I think it's
fine as is regardless of the error code returned (as long as it's not
-ENOENT :) ). mfill_atomic_pte_copy() is sure to set `*foliop = NULL`
before it attempts this lock (in mfill_atomic_install_pte). So -EAGAIN
or -EFAULT should work equally well at least from that perspective. I
somewhat prefer -EAGAIN, but maybe I'm missing something.
>
> mm/userfaultfd.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -300,7 +300,10 @@ static int mfill_atomic_pte_poison(pmd_t *dst_pmd,
> spinlock_t *ptl;
>
> _dst_pte = make_pte_marker(PTE_MARKER_POISONED);
> + ret = -EAGAIN;
> dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
> + if (!dst_pte)
> + goto out;
>
> if (mfill_file_over_size(dst_vma, dst_addr)) {
> ret = -EFAULT;
> @@ -319,6 +322,7 @@ static int mfill_atomic_pte_poison(pmd_t *dst_pmd,
> ret = 0;
> out_unlock:
> pte_unmap_unlock(dst_pte, ptl);
> +out:
> return ret;
> }
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH mm-unstable fix] mm: userfaultfd: add new UFFDIO_POISON ioctl: fix
2023-07-12 18:16 ` Axel Rasmussen
@ 2023-07-14 2:40 ` Hugh Dickins
2023-07-19 21:53 ` Peter Xu
0 siblings, 1 reply; 4+ messages in thread
From: Hugh Dickins @ 2023-07-14 2:40 UTC (permalink / raw)
To: Axel Rasmussen
Cc: Hugh Dickins, Andrew Morton, Dan Carpenter, Peter Xu, linux-mm
[-- Attachment #1: Type: text/plain, Size: 2635 bytes --]
On Wed, 12 Jul 2023, Axel Rasmussen wrote:
> On Tue, Jul 11, 2023 at 6:27 PM Hugh Dickins <hughd@google.com> wrote:
> >
> > Smatch has observed that pte_offset_map_lock() is now allowed to fail,
> > and then ptl should not be unlocked. Use -EAGAIN here like elsewhere.
> >
> > Signed-off-by: Hugh Dickins <hughd@google.com>
>
> Looks correct to me, thanks Hugh! If it's useful, feel free to take:
>
> Reviewed-by: Axel Rasmussen <axelrasmussen@google.com>
Thanks, that will have helped Andrew (but would vanish into the merge
with your original when it moves from mm-unstable to mm-stable).
>
> > ---
> > Axel, Peter: this seems right as a fix to the patch in mm-unstable;
> > but in preparing this, I noticed mfill_atomic()'s code before calling
> > mfill_atomic_pte(), and think that my original choice of -EFAULT was
> > therefore better than -EAGAIN for all of these; and that mfill_atomic()'s
> > BUG_ONs there would be better deleted (and is its BUG_ON(folio) safe??).
> > Something one of us should address, after this fixup is in akpm's tree.
>
> Agreed, dealing with the BUG_ONs is something I have been meaning to
> do as checkpatch bothers me about it frequently.
>
> What this code is trying to do is to enforce the contract that: if
> mfill_atomic_pte failed, then it must have released *folio and set it
> to NULL. But, you're exactly right that if we had such a bug, it would
> mean we leaked one page in an unusual error case - not great, but not
> worth crashing the kernel either.
>
> For UFFDIO_POISON this doesn't really apply because it doesn't
> allocate or get a reference to a page in any case.
>
> For other cases like UFFDIO_COPY where it does matter, I think it's
> fine as is regardless of the error code returned (as long as it's not
> -ENOENT :) ). mfill_atomic_pte_copy() is sure to set `*foliop = NULL`
> before it attempts this lock (in mfill_atomic_install_pte). So -EAGAIN
> or -EFAULT should work equally well at least from that perspective. I
> somewhat prefer -EAGAIN, but maybe I'm missing something.
Right, when I said -EFAULT better than -EAGAIN, I was only basing that
on -EFAULT being the code which was already used for pmd_trans_huge()
in the check above mfill_atomic()'s call to mfill_atomic_pte().
I don't disagree with you, and Peter too preferred -EAGAIN: it's just
better if they all use the same code (or maybe mfill_atomic()'s first
check for pmd_trans_huge() can be deleted along with the BUG_ONs - but
I have not checked through the cases, there may be very good reason to
keep that preliminary check there).
Hugh
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH mm-unstable fix] mm: userfaultfd: add new UFFDIO_POISON ioctl: fix
2023-07-14 2:40 ` Hugh Dickins
@ 2023-07-19 21:53 ` Peter Xu
0 siblings, 0 replies; 4+ messages in thread
From: Peter Xu @ 2023-07-19 21:53 UTC (permalink / raw)
To: Hugh Dickins; +Cc: Axel Rasmussen, Andrew Morton, Dan Carpenter, linux-mm
Hello, Hugh, Axel,
Sorry for a very late reply after a long PTO..
On Thu, Jul 13, 2023 at 07:40:30PM -0700, Hugh Dickins wrote:
> On Wed, 12 Jul 2023, Axel Rasmussen wrote:
> > On Tue, Jul 11, 2023 at 6:27 PM Hugh Dickins <hughd@google.com> wrote:
> > >
> > > Smatch has observed that pte_offset_map_lock() is now allowed to fail,
> > > and then ptl should not be unlocked. Use -EAGAIN here like elsewhere.
> > >
> > > Signed-off-by: Hugh Dickins <hughd@google.com>
> >
> > Looks correct to me, thanks Hugh! If it's useful, feel free to take:
> >
> > Reviewed-by: Axel Rasmussen <axelrasmussen@google.com>
>
> Thanks, that will have helped Andrew (but would vanish into the merge
> with your original when it moves from mm-unstable to mm-stable).
>
> >
> > > ---
> > > Axel, Peter: this seems right as a fix to the patch in mm-unstable;
> > > but in preparing this, I noticed mfill_atomic()'s code before calling
> > > mfill_atomic_pte(), and think that my original choice of -EFAULT was
> > > therefore better than -EAGAIN for all of these; and that mfill_atomic()'s
> > > BUG_ONs there would be better deleted (and is its BUG_ON(folio) safe??).
> > > Something one of us should address, after this fixup is in akpm's tree.
> >
> > Agreed, dealing with the BUG_ONs is something I have been meaning to
> > do as checkpatch bothers me about it frequently.
> >
> > What this code is trying to do is to enforce the contract that: if
> > mfill_atomic_pte failed, then it must have released *folio and set it
> > to NULL. But, you're exactly right that if we had such a bug, it would
> > mean we leaked one page in an unusual error case - not great, but not
> > worth crashing the kernel either.
Yes I also agree the BUG_ON might be a bit too aggressive, even if still
accurate (so we should really not trigger that). WARN_ON_ONCE() should be
enough.
> >
> > For UFFDIO_POISON this doesn't really apply because it doesn't
> > allocate or get a reference to a page in any case.
> >
> > For other cases like UFFDIO_COPY where it does matter, I think it's
> > fine as is regardless of the error code returned (as long as it's not
> > -ENOENT :) ). mfill_atomic_pte_copy() is sure to set `*foliop = NULL`
> > before it attempts this lock (in mfill_atomic_install_pte). So -EAGAIN
> > or -EFAULT should work equally well at least from that perspective. I
> > somewhat prefer -EAGAIN, but maybe I'm missing something.
>
> Right, when I said -EFAULT better than -EAGAIN, I was only basing that
> on -EFAULT being the code which was already used for pmd_trans_huge()
> in the check above mfill_atomic()'s call to mfill_atomic_pte().
>
> I don't disagree with you, and Peter too preferred -EAGAIN: it's just
> better if they all use the same code (or maybe mfill_atomic()'s first
> check for pmd_trans_huge() can be deleted along with the BUG_ONs - but
> I have not checked through the cases, there may be very good reason to
> keep that preliminary check there).
It's just that -EFAULT will definitely fail most of the uffd based apps,
because no app can handle an -EFAULT over any ioctl(UFFDIO_*). So if we'd
delete the 1st pmd_trans_huge() check we may want to make the 2nd return
-EAGAIN.
I think this -EFAULT (of 2nd pmd_trans_huge() check) should really also be
an -EAGAIN, I'd bet ten dollars if it's really hit somewhere before it'll
crash the app as explained.
With Hugh's recent rework on pte_offset_map_lock() (which should contain a
thp check within the map_lock()) IMHO we can safely drop the 2nd check as a
whole (while keeping the 1st check as a fast path to detect existing thps),
and then we should reliably return an -EAGAIN if a thp raced with us, so
the userapp should just retry when race with anything else.
Thanks,
--
Peter Xu
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-07-19 21:53 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-12 1:27 [PATCH mm-unstable fix] mm: userfaultfd: add new UFFDIO_POISON ioctl: fix Hugh Dickins
2023-07-12 18:16 ` Axel Rasmussen
2023-07-14 2:40 ` Hugh Dickins
2023-07-19 21:53 ` Peter Xu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox