All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e()
@ 2022-04-27 14:04 Andrew Cooper
  2022-04-27 14:07 ` Jan Beulich
  2022-05-26 15:31 ` Jan Beulich
  0 siblings, 2 replies; 4+ messages in thread
From: Andrew Cooper @ 2022-04-27 14:04 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Jan Beulich, Roger Pau Monné, Wei Liu

mfn_valid() is not a trivially simple, and contains an evaluate_nospec() for
speculative defence.  Avoid calling it redundantly, and just store the result
of the first call.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Wei Liu <wl@xen.org>
---
 xen/arch/x86/mm.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 72dbce43b13a..31b9f96dc0df 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -887,7 +887,7 @@ get_page_from_l1e(
     uint32_t l1f = l1e_get_flags(l1e);
     struct vcpu *curr = current;
     struct domain *real_pg_owner;
-    bool write;
+    bool write, valid;
 
     if ( unlikely(!(l1f & _PAGE_PRESENT)) )
     {
@@ -902,13 +902,15 @@ get_page_from_l1e(
         return -EINVAL;
     }
 
-    if ( !mfn_valid(_mfn(mfn)) ||
+    valid = mfn_valid(_mfn(mfn));
+
+    if ( !valid ||
          (real_pg_owner = page_get_owner_and_reference(page)) == dom_io )
     {
         int flip = 0;
 
         /* Only needed the reference to confirm dom_io ownership. */
-        if ( mfn_valid(_mfn(mfn)) )
+        if ( valid )
             put_page(page);
 
         /* DOMID_IO reverts to caller for privilege checks. */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e()
  2022-04-27 14:04 [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e() Andrew Cooper
@ 2022-04-27 14:07 ` Jan Beulich
  2022-05-26 15:31 ` Jan Beulich
  1 sibling, 0 replies; 4+ messages in thread
From: Jan Beulich @ 2022-04-27 14:07 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Roger Pau Monné, Wei Liu, Xen-devel

On 27.04.2022 16:04, Andrew Cooper wrote:
> mfn_valid() is not a trivially simple, and contains an evaluate_nospec() for
> speculative defence.  Avoid calling it redundantly, and just store the result
> of the first call.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e()
  2022-04-27 14:04 [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e() Andrew Cooper
  2022-04-27 14:07 ` Jan Beulich
@ 2022-05-26 15:31 ` Jan Beulich
  2022-05-26 16:52   ` Andrew Cooper
  1 sibling, 1 reply; 4+ messages in thread
From: Jan Beulich @ 2022-05-26 15:31 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Roger Pau Monné, Wei Liu, Xen-devel

On 27.04.2022 16:04, Andrew Cooper wrote:
> mfn_valid() is not a trivially simple, and contains an evaluate_nospec() for
> speculative defence.  Avoid calling it redundantly, and just store the result
> of the first call.

Since it took quite some time for this to actually be committed, I did
notice it among more recent commits, and I've grown a question: Isn't
the latching of the result in a local variable undermining the supposed
speculative defense? It's not as if I could point out a particular
gadget here, but it feels like the adjustment should have specifically
justified the speculative safety ... But I guess my understanding of
all of this might still be somewhat flaky?

Jan

> @@ -902,13 +902,15 @@ get_page_from_l1e(
>          return -EINVAL;
>      }
>  
> -    if ( !mfn_valid(_mfn(mfn)) ||
> +    valid = mfn_valid(_mfn(mfn));
> +
> +    if ( !valid ||
>           (real_pg_owner = page_get_owner_and_reference(page)) == dom_io )
>      {
>          int flip = 0;
>  
>          /* Only needed the reference to confirm dom_io ownership. */
> -        if ( mfn_valid(_mfn(mfn)) )
> +        if ( valid )
>              put_page(page);
>  
>          /* DOMID_IO reverts to caller for privilege checks. */



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e()
  2022-05-26 15:31 ` Jan Beulich
@ 2022-05-26 16:52   ` Andrew Cooper
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Cooper @ 2022-05-26 16:52 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Roger Pau Monne, Wei Liu, Xen-devel

On 26/05/2022 16:31, Jan Beulich wrote:
> On 27.04.2022 16:04, Andrew Cooper wrote:
>> mfn_valid() is not a trivially simple, and contains an evaluate_nospec() for
>> speculative defence.  Avoid calling it redundantly, and just store the result
>> of the first call.
> Since it took quite some time for this to actually be committed, I did
> notice it among more recent commits, and I've grown a question: Isn't
> the latching of the result in a local variable undermining the supposed
> speculative defense? It's not as if I could point out a particular
> gadget here, but it feels like the adjustment should have specifically
> justified the speculative safety ... But I guess my understanding of
> all of this might still be somewhat flaky?

The eval_nospec() in mfn_valid() is to avoid a speculative over-read of
pdx_group_valid[].

It does not provide any protection for any other logic.

In particular, it does not provide any safety whatsoever in
get_page_from_l1e() because the lfence is the wrong side of the
conditional jump.  i.e. you've got:

    ...
    call mfn_valid // lfence in here
    test %al, %al
    je 1f
    ...                    // lfence missing from here
1:
    ...                    // and here


The change I've made is simply CSE that a compiler could do
automatically. if it could be persuaded that __mfn_valid() was pure
(which it logically is.)

If logic in get_page_from_l1e() needs Spectre protections for any
reason, it needs its own eval_nospec()/array_access_nospec()/etc because
it is specifically not safe to rely on incidental lfence's from
unrelated protections.

~Andrew

P.S. I need to add this to the list of reasons of why we need a "coding
& speculation safety" doc in the tree.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-05-26 16:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 14:04 [PATCH] x86/mm: Remove unnecessary mfn_valid() call from get_page_from_l1e() Andrew Cooper
2022-04-27 14:07 ` Jan Beulich
2022-05-26 15:31 ` Jan Beulich
2022-05-26 16:52   ` Andrew Cooper

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.