* [PATCH] x86/mm: Simplify redundant overlap calculation @ 2024-01-23 16:36 Dave Hansen 2024-01-23 16:47 ` Dave Hansen ` (2 more replies) 0 siblings, 3 replies; 6+ messages in thread From: Dave Hansen @ 2024-01-23 16:36 UTC (permalink / raw) To: linux-kernel Cc: Dave Hansen, David Binderman, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86 There have been a couple of reports that the two sides of the overlaps() calculation are redundant. I spent way too much time looking at this, but I became convinced that they are redundant when a little test program of mine produced identical disassembly for both versions of the check. Remove the second condition. It is exactly the same as the first. Fixes: 91ee8f5c1f50 ("x86/mm/cpa: Allow range check for static protections") Reported-by: David Binderman <dcb314@hotmail.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: x86@kernel.org --- arch/x86/mm/pat/set_memory.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index e9b448d1b1b70..fdc00516c0b54 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -435,8 +435,7 @@ static void cpa_flush(struct cpa_data *data, int cache) static bool overlaps(unsigned long r1_start, unsigned long r1_end, unsigned long r2_start, unsigned long r2_end) { - return (r1_start <= r2_end && r1_end >= r2_start) || - (r2_start <= r1_end && r2_end >= r1_start); + return (r1_start <= r2_end && r1_end >= r2_start); } #ifdef CONFIG_PCI_BIOS -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/mm: Simplify redundant overlap calculation 2024-01-23 16:36 [PATCH] x86/mm: Simplify redundant overlap calculation Dave Hansen @ 2024-01-23 16:47 ` Dave Hansen 2024-01-23 16:54 ` David Binderman 2024-01-23 19:28 ` Sohil Mehta 2 siblings, 0 replies; 6+ messages in thread From: Dave Hansen @ 2024-01-23 16:47 UTC (permalink / raw) To: Dave Hansen, linux-kernel Cc: David Binderman, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86 On 1/23/24 08:36, Dave Hansen wrote: > There have been a couple of reports that the two sides of the > overlaps() calculation are redundant. I spent way too much time > looking at this, but I became convinced that they are redundant > when a little test program of mine produced identical disassembly > for both versions of the check. > > Remove the second condition. It is exactly the same as the first. > > Fixes: 91ee8f5c1f50 ("x86/mm/cpa: Allow range check for static protections") > Reported-by: David Binderman <dcb314@hotmail.com> Gah, that one escaped a moment too soon: Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> ... obviously ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/mm: Simplify redundant overlap calculation 2024-01-23 16:36 [PATCH] x86/mm: Simplify redundant overlap calculation Dave Hansen 2024-01-23 16:47 ` Dave Hansen @ 2024-01-23 16:54 ` David Binderman 2024-01-23 17:00 ` Dave Hansen 2024-01-23 19:28 ` Sohil Mehta 2 siblings, 1 reply; 6+ messages in thread From: David Binderman @ 2024-01-23 16:54 UTC (permalink / raw) To: Dave Hansen, linux-kernel@vger.kernel.org Cc: Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86@kernel.org Hello there, >Remove the second condition. It is exactly the same as the first. I don't think the first condition is sufficient. I suspect something like return (r2_start <= r1_start && r1_start <= r2_end) || (r2_start <= r1_end && r1_end <= r2_end); Given the range [r2_start .. r2_end], then if r1_start or r1_end are in that range, you have overlap. Unless you know different. Regards David Binderman Fixes: 91ee8f5c1f50 ("x86/mm/cpa: Allow range check for static protections") Reported-by: David Binderman <dcb314@hotmail.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: x86@kernel.org --- arch/x86/mm/pat/set_memory.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index e9b448d1b1b70..fdc00516c0b54 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -435,8 +435,7 @@ static void cpa_flush(struct cpa_data *data, int cache) static bool overlaps(unsigned long r1_start, unsigned long r1_end, unsigned long r2_start, unsigned long r2_end) { - return (r1_start <= r2_end && r1_end >= r2_start) || - (r2_start <= r1_end && r2_end >= r1_start); + return (r1_start <= r2_end && r1_end >= r2_start); } #ifdef CONFIG_PCI_BIOS -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/mm: Simplify redundant overlap calculation 2024-01-23 16:54 ` David Binderman @ 2024-01-23 17:00 ` Dave Hansen 2024-01-23 19:19 ` Sohil Mehta 0 siblings, 1 reply; 6+ messages in thread From: Dave Hansen @ 2024-01-23 17:00 UTC (permalink / raw) To: David Binderman, Dave Hansen, linux-kernel@vger.kernel.org Cc: Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86@kernel.org On 1/23/24 08:54, David Binderman wrote: >> Remove the second condition. It is exactly the same as the first. > I don't think the first condition is sufficient. I suspect something like > > return (r2_start <= r1_start && r1_start <= r2_end) || > (r2_start <= r1_end && r1_end <= r2_end); > > Given the range [r2_start .. r2_end], then if r1_start or r1_end > are in that range, you have overlap. > > Unless you know different. First of all, I've gotten these bounds checks wrong in code more times than I can count. I have zero trust that I'll get them right. :) But the compiler seems to know different at least: int overlaps1(unsigned long r1_start, unsigned long r1_end, unsigned long r2_start, unsigned long r2_end) { return (r1_start <= r2_end && r1_end >= r2_start) || (r2_start <= r1_end && r2_end >= r1_start); } int overlaps2(unsigned long r1_start, unsigned long r1_end, unsigned long r2_start, unsigned long r2_end) { return (r1_start <= r2_end && r1_end >= r2_start); } Results in: 0000000000001180 <overlaps1>: 1180: f3 0f 1e fa endbr64 1184: 48 39 cf cmp %rcx,%rdi 1187: 49 89 d0 mov %rdx,%r8 118a: 0f 96 c2 setbe %dl 118d: 31 c0 xor %eax,%eax 118f: 4c 39 c6 cmp %r8,%rsi 1192: 0f 93 c0 setae %al 1195: 21 d0 and %edx,%eax 1197: c3 ret 1198: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 119f: 00 00000000000011a0 <overlaps2>: 11a0: f3 0f 1e fa endbr64 11a4: 48 39 cf cmp %rcx,%rdi 11a7: 49 89 d0 mov %rdx,%r8 11aa: 0f 96 c2 setbe %dl 11ad: 31 c0 xor %eax,%eax 11af: 4c 39 c6 cmp %r8,%rsi 11b2: 0f 93 c0 setae %al 11b5: 21 d0 and %edx,%eax 11b7: c3 ret 11b8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 11bf: 00 I also wrote a quick program to throw random numbers into both versions and see if they differ. They never did, which they obviously can't if they're the exact same instructions. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/mm: Simplify redundant overlap calculation 2024-01-23 17:00 ` Dave Hansen @ 2024-01-23 19:19 ` Sohil Mehta 0 siblings, 0 replies; 6+ messages in thread From: Sohil Mehta @ 2024-01-23 19:19 UTC (permalink / raw) To: Dave Hansen, David Binderman, Dave Hansen, linux-kernel@vger.kernel.org Cc: Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86@kernel.org On 1/23/2024 9:00 AM, Dave Hansen wrote: > On 1/23/24 08:54, David Binderman wrote: >>> Remove the second condition. It is exactly the same as the first. >> I don't think the first condition is sufficient. I suspect something like >> >> return (r2_start <= r1_start && r1_start <= r2_end) || >> (r2_start <= r1_end && r1_end <= r2_end); >> This check seems accurate however Dave's single line check below also looks accurate to me. See the analysis below. >> Given the range [r2_start .. r2_end], then if r1_start or r1_end >> are in that range, you have overlap. >> >> Unless you know different. > > First of all, I've gotten these bounds checks wrong in code more times > than I can count. I have zero trust that I'll get them right. :) > > But the compiler seems to know different at least: > > int overlaps1(unsigned long r1_start, unsigned long r1_end, > unsigned long r2_start, unsigned long r2_end) > { > return (r1_start <= r2_end && r1_end >= r2_start) || > (r2_start <= r1_end && r2_end >= r1_start); > } Dave, I think if you change the order of the && in the 2nd check it makes it easier to visually realize that both of these checks are indeed the same: (r1_start <= r2_end ) && (r1_end >= r2_start) || (r2_end >= r1_start) && (r2_start <= r1_end ) The first operation in () on both lines is exactly the same. Same is true for the second operation after the &&. > > int overlaps2(unsigned long r1_start, unsigned long r1_end, > unsigned long r2_start, unsigned long r2_end) > { > return (r1_start <= r2_end && r1_end >= r2_start); > } > I completely agree that overlap1() and overlap2() are expected to generate the same output for any input. However, the next question is whether overlap2() is enough to detect there is indeed an overlap between the ranges. I find that would be true based on the assumption that the end is always greater than or equal to the start in both ranges. I have now spent way too much time on this. But if you rearrange the check in overlaps2() as below then I find it easier to put it in words: (r1_start <= r2_end && r2_start <= r1_end) "Both of the ranges have to start before either of ranges end for there to be an overlap". Sohil ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/mm: Simplify redundant overlap calculation 2024-01-23 16:36 [PATCH] x86/mm: Simplify redundant overlap calculation Dave Hansen 2024-01-23 16:47 ` Dave Hansen 2024-01-23 16:54 ` David Binderman @ 2024-01-23 19:28 ` Sohil Mehta 2 siblings, 0 replies; 6+ messages in thread From: Sohil Mehta @ 2024-01-23 19:28 UTC (permalink / raw) To: Dave Hansen, linux-kernel Cc: David Binderman, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86 On 1/23/2024 8:36 AM, Dave Hansen wrote: > There have been a couple of reports that the two sides of the > overlaps() calculation are redundant. I spent way too much time > looking at this, but I became convinced that they are redundant > when a little test program of mine produced identical disassembly > for both versions of the check. > > Remove the second condition. It is exactly the same as the first. > > Fixes: 91ee8f5c1f50 ("x86/mm/cpa: Allow range check for static protections") > Reported-by: David Binderman <dcb314@hotmail.com> > Cc: Andy Lutomirski <luto@kernel.org> > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Ingo Molnar <mingo@redhat.com> > Cc: Borislav Petkov <bp@alien8.de> > Cc: x86@kernel.org > --- > arch/x86/mm/pat/set_memory.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > Reviewed-by: Sohil Mehta <sohil.mehta@intel.com> > diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c > index e9b448d1b1b70..fdc00516c0b54 100644 > --- a/arch/x86/mm/pat/set_memory.c > +++ b/arch/x86/mm/pat/set_memory.c > @@ -435,8 +435,7 @@ static void cpa_flush(struct cpa_data *data, int cache) > static bool overlaps(unsigned long r1_start, unsigned long r1_end, > unsigned long r2_start, unsigned long r2_end) > { > - return (r1_start <= r2_end && r1_end >= r2_start) || > - (r2_start <= r1_end && r2_end >= r1_start); > + return (r1_start <= r2_end && r1_end >= r2_start); > } > > #ifdef CONFIG_PCI_BIOS ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-01-23 19:28 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-01-23 16:36 [PATCH] x86/mm: Simplify redundant overlap calculation Dave Hansen 2024-01-23 16:47 ` Dave Hansen 2024-01-23 16:54 ` David Binderman 2024-01-23 17:00 ` Dave Hansen 2024-01-23 19:19 ` Sohil Mehta 2024-01-23 19:28 ` Sohil Mehta
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).