Netdev List
 help / color / mirror / Atom feed
* Re: [BUG] from x86: Support kmap_local() forced debugging
       [not found]   ` <20210106180132.41dc249d@gandalf.local.home>
@ 2021-01-07  1:03     ` Linus Torvalds
  2021-01-07  1:16       ` Steven Rostedt
                         ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Linus Torvalds @ 2021-01-07  1:03 UTC (permalink / raw)
  To: Steven Rostedt, Willem de Bruijn, Jakub Kicinski, David Miller,
	Jonathan Lemon
  Cc: Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

[-- Attachment #1: Type: text/plain, Size: 4491 bytes --]

On Wed, Jan 6, 2021 at 3:01 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> I triggered the following crash on x86_32 by simply doing a:
>
> (ssh'ing into the box)
>
>   # head -100 /tmp/output-file
>
> Where the /tmp/output-file was the output of a trace-cmd report.
> Even after rebooting and not running the tracing code, simply doing the
> head command still crashed.

The code decodes to

   0:   3b 5d e8                cmp    -0x18(%ebp),%ebx
   3:   0f 47 5d e8             cmova  -0x18(%ebp),%ebx
   7:   c7 45 e0 00 00 00 00    movl   $0x0,-0x20(%ebp)
   e:   8b 7d e0                mov    -0x20(%ebp),%edi
  11:   39 7d e8                cmp    %edi,-0x18(%ebp)
  14:   76 3a                   jbe    0x50
  16:   8b 45 d4                mov    -0x2c(%ebp),%eax
  19:   e8 a4 e4 ff ff          call   0xffffe4c2
  1e:   8b 55 e4                mov    -0x1c(%ebp),%edx
  21:   03 55 e0                add    -0x20(%ebp),%edx
  24:   89 d9                   mov    %ebx,%ecx
  26:   01 c6                   add    %eax,%esi
  28:   89 d7                   mov    %edx,%edi
  2a:*  f3 a4                   rep movsb %ds:(%esi),%es:(%edi)
 <-- trapping instruction
  2c:   e8 c9 e4 ff ff          call   0xffffe4fa
  31:   01 5d e0                add    %ebx,-0x20(%ebp)
  34:   8b 5d e8                mov    -0x18(%ebp),%ebx
  37:   b8 00 10 00 00          mov    $0x1000,%eax
  3c:   2b 5d e0                sub    -0x20(%ebp),%ebx

and while it would be good to see the output of
scripts/decode_stacktrace.sh, I strongly suspect that the above is

                                vaddr = kmap_atomic(p);
                                memcpy(to + copied, vaddr + p_off, p_len);
                                kunmap_atomic(vaddr);

(although I wonder how/why the heck you've enabled
CC_OPTIMIZE_FOR_SIZE=y, which is what causes "memcpy()" to be done as
that "rep movsb". I thought we disabled it because it's so bad on most
cpus).

So that first "call" instruction is the kmap_atomic(), the "rep movs"
is the memcpy(), and the "call" instruction immediately after is the
kunmap_atomic().

Anyway, you can see vaddr in register state:

        EAX: fff57000

so we've kmapped that one page at fff57000, but we're accessing past
it into the next page:

> BUG: unable to handle page fault for address: fff58000

with the current source address being (ESI: fff58000) and we still
have 248 bytes to go (ECX: 000000f8) even though we've already
overflowed into the next page.

You can see the original count still (EBX: 000005a8), so it really
looks like that skb_frag_foreach_page() logic

                        skb_frag_foreach_page(f,
                                              skb_frag_off(f) + offset - start,
                                              copy, p, p_off, p_len, copied) {
                                vaddr = kmap_atomic(p);
                                memcpy(to + copied, vaddr + p_off, p_len);
                                kunmap_atomic(vaddr);
                        }

must be wrong, and doesn't handle the "each page" part properly. It
must have started in the middle of the page, and p_len (that 0x5a8)
was wrong.

IOW, it really looks like p_off + p_len had the value 0x10f8, which is
larger than one page. And looking at the code, in
skb_frag_foreach_page(), I see:

             p_off = (f_off) & (PAGE_SIZE - 1),                         \
             p_len = skb_frag_must_loop(p) ?                            \
             min_t(u32, f_len, PAGE_SIZE - p_off) : f_len,              \

where that "min_t(u32, f_len, PAGE_SIZE - p_off)" looks correct, but
then presumably skb_frag_must_loop() must be wrong.

Oh, and when I look at that, I see

    static inline bool skb_frag_must_loop(struct page *p)
    {
    #if defined(CONFIG_HIGHMEM)
            if (PageHighMem(p))
                    return true;
    #endif
            return false;
    }

and that is no longer true. With the kmap debugging, even non-highmem
pages need that "do one page at a time" code, because even non-highmem
pages get remapped by kmap().

IOW, I think the patch to fix this might be something like the attached.

I wonder whether there is other code that "knows" about kmap() only
affecting PageHighmem() pages thing that is no longer true.

Looking at some other code, skb_gro_reset_offset() looks suspiciously
like it also thinks highmem pages are special.

Adding the networking people involved in this area to the cc too.

               Linus

[-- Attachment #2: patch --]
[-- Type: application/octet-stream, Size: 544 bytes --]

 include/linux/skbuff.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 333bcdc39635..c858adfb5a82 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -366,7 +366,7 @@ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta)
 static inline bool skb_frag_must_loop(struct page *p)
 {
 #if defined(CONFIG_HIGHMEM)
-	if (PageHighMem(p))
+	if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP) || PageHighMem(p))
 		return true;
 #endif
 	return false;

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07  1:03     ` [BUG] from x86: Support kmap_local() forced debugging Linus Torvalds
@ 2021-01-07  1:16       ` Steven Rostedt
  2021-01-07  1:49       ` Steven Rostedt
  2021-01-07  1:49       ` Jakub Kicinski
  2 siblings, 0 replies; 9+ messages in thread
From: Steven Rostedt @ 2021-01-07  1:16 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Willem de Bruijn, Jakub Kicinski, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Wed, 6 Jan 2021 17:03:48 -0800
Linus Torvalds <torvalds@linux-foundation.org> wrote:

> (although I wonder how/why the heck you've enabled
> CC_OPTIMIZE_FOR_SIZE=y, which is what causes "memcpy()" to be done as
> that "rep movsb". I thought we disabled it because it's so bad on most
> cpus).

Why?

Because to test x86_32, I have a Fedora Core 13 (yes 13!) partition
(baremetal) that I use. And the .config I use for it hasn't changed
since that time ;-) (except to add new features that I want to test on
x86_32).

Anyway, I'll test out your patch. Thanks for investigating this.

-- Steve

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07  1:03     ` [BUG] from x86: Support kmap_local() forced debugging Linus Torvalds
  2021-01-07  1:16       ` Steven Rostedt
@ 2021-01-07  1:49       ` Steven Rostedt
  2021-01-07  1:49       ` Jakub Kicinski
  2 siblings, 0 replies; 9+ messages in thread
From: Steven Rostedt @ 2021-01-07  1:49 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Willem de Bruijn, Jakub Kicinski, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Wed, 6 Jan 2021 17:03:48 -0800
Linus Torvalds <torvalds@linux-foundation.org> wrote:

> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -366,7 +366,7 @@ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta)
>  static inline bool skb_frag_must_loop(struct page *p)
>  {
>  #if defined(CONFIG_HIGHMEM)
> -	if (PageHighMem(p))
> +	if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP) || PageHighMem(p))
>  		return true;
>  #endif
>  	return false;

I applied this and I haven't been able to crash it again.

Thanks,

-- Steve

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07  1:03     ` [BUG] from x86: Support kmap_local() forced debugging Linus Torvalds
  2021-01-07  1:16       ` Steven Rostedt
  2021-01-07  1:49       ` Steven Rostedt
@ 2021-01-07  1:49       ` Jakub Kicinski
  2021-01-07  2:11         ` Willem de Bruijn
  2 siblings, 1 reply; 9+ messages in thread
From: Jakub Kicinski @ 2021-01-07  1:49 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Steven Rostedt, Willem de Bruijn, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Wed, 6 Jan 2021 17:03:48 -0800 Linus Torvalds wrote:
> I wonder whether there is other code that "knows" about kmap() only
> affecting PageHighmem() pages thing that is no longer true.
> 
> Looking at some other code, skb_gro_reset_offset() looks suspiciously
> like it also thinks highmem pages are special.
> 
> Adding the networking people involved in this area to the cc too.

Thanks for the detailed analysis! skb_gro_reset_offset() checks if
kernel can read data in the fragments directly as an optimization, 
in case the entire header is in a fragment. 

IIUC DEBUG_KMAP_LOCAL_FORCE_MAP only affects the mappings from
explicit kmap calls, which GRO won't make - it will fall back to
pulling the header out of the fragment and end up in skb_copy_bits(),
i.e. the loop you fixed. So GRO should be good. I think..

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07  1:49       ` Jakub Kicinski
@ 2021-01-07  2:11         ` Willem de Bruijn
  2021-01-07  4:44           ` Willem de Bruijn
  0 siblings, 1 reply; 9+ messages in thread
From: Willem de Bruijn @ 2021-01-07  2:11 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Linus Torvalds, Steven Rostedt, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Wed, Jan 6, 2021 at 8:49 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed, 6 Jan 2021 17:03:48 -0800 Linus Torvalds wrote:
> > I wonder whether there is other code that "knows" about kmap() only
> > affecting PageHighmem() pages thing that is no longer true.
> >
> > Looking at some other code, skb_gro_reset_offset() looks suspiciously
> > like it also thinks highmem pages are special.
> >
> > Adding the networking people involved in this area to the cc too.
>
> Thanks for the detailed analysis! skb_gro_reset_offset() checks if
> kernel can read data in the fragments directly as an optimization,
> in case the entire header is in a fragment.
>
> IIUC DEBUG_KMAP_LOCAL_FORCE_MAP only affects the mappings from
> explicit kmap calls, which GRO won't make - it will fall back to
> pulling the header out of the fragment and end up in skb_copy_bits(),
> i.e. the loop you fixed. So GRO should be good. I think..

Agreed. That code in skb_gro_reset_offset skips the GRO frag0
optimization in various cases, including if the first fragment is in
high mem.

That specific check goes back to the introduction of the frag0
optimization in commit 86911732d399 ("gro: Avoid copying headers of
unmerged packets"), at the time in helper skb_gro_header().

Very glad to hear that the fix addresses the crash in
skb_frag_foreach_page. Thanks!

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07  2:11         ` Willem de Bruijn
@ 2021-01-07  4:44           ` Willem de Bruijn
  2021-01-07 19:47             ` Linus Torvalds
  0 siblings, 1 reply; 9+ messages in thread
From: Willem de Bruijn @ 2021-01-07  4:44 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Linus Torvalds, Steven Rostedt, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Wed, Jan 6, 2021 at 9:11 PM Willem de Bruijn <willemb@google.com> wrote:
>
> On Wed, Jan 6, 2021 at 8:49 PM Jakub Kicinski <kuba@kernel.org> wrote:
> >
> > On Wed, 6 Jan 2021 17:03:48 -0800 Linus Torvalds wrote:
> > > I wonder whether there is other code that "knows" about kmap() only
> > > affecting PageHighmem() pages thing that is no longer true.
> > >
> > > Looking at some other code, skb_gro_reset_offset() looks suspiciously
> > > like it also thinks highmem pages are special.
> > >
> > > Adding the networking people involved in this area to the cc too.

But there are three other kmap_atomic callers under net/ that do not
loop at all, so assume non-compound pages. In esp_output_head,
esp6_output_head and skb_seq_read. The first two directly use
skb_page_frag_refill, which can allocate compound (but not
__GFP_HIGHMEM) pages, and the third can be inserted with
netfilter xt_string in the path of tcp transmit skbs, which can also
have compound pages. I think that these could similarly access
data beyond the end of the kmap_atomic mapped page. I'll take
a closer look.

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07  4:44           ` Willem de Bruijn
@ 2021-01-07 19:47             ` Linus Torvalds
  2021-01-07 20:52               ` Steven Rostedt
  0 siblings, 1 reply; 9+ messages in thread
From: Linus Torvalds @ 2021-01-07 19:47 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: Jakub Kicinski, Steven Rostedt, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Wed, Jan 6, 2021 at 8:45 PM Willem de Bruijn <willemb@google.com> wrote:
>
> But there are three other kmap_atomic callers under net/ that do not
> loop at all, so assume non-compound pages. In esp_output_head,
> esp6_output_head and skb_seq_read. The first two directly use
> skb_page_frag_refill, which can allocate compound (but not
> __GFP_HIGHMEM) pages, and the third can be inserted with
> netfilter xt_string in the path of tcp transmit skbs, which can also
> have compound pages. I think that these could similarly access
> data beyond the end of the kmap_atomic mapped page. I'll take
> a closer look.

Thanks.

Note that I have flushed my random one-liner patch from my system, and
expect to get a proper fix through the normal networking pulls.

And _if_ the networking people feel that my one-liner was the proper
fix, you can use it and add my sign-off if you want to, but it really
was more of a "this is the quick ugly fix for testing" rather than
anything else.

          Linus

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07 19:47             ` Linus Torvalds
@ 2021-01-07 20:52               ` Steven Rostedt
  2021-01-07 21:07                 ` Willem de Bruijn
  0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2021-01-07 20:52 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Willem de Bruijn, Jakub Kicinski, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Thu, 7 Jan 2021 11:47:02 -0800
Linus Torvalds <torvalds@linux-foundation.org> wrote:

> On Wed, Jan 6, 2021 at 8:45 PM Willem de Bruijn <willemb@google.com> wrote:
> >
> > But there are three other kmap_atomic callers under net/ that do not
> > loop at all, so assume non-compound pages. In esp_output_head,
> > esp6_output_head and skb_seq_read. The first two directly use
> > skb_page_frag_refill, which can allocate compound (but not
> > __GFP_HIGHMEM) pages, and the third can be inserted with
> > netfilter xt_string in the path of tcp transmit skbs, which can also
> > have compound pages. I think that these could similarly access
> > data beyond the end of the kmap_atomic mapped page. I'll take
> > a closer look.  
> 
> Thanks.
> 
> Note that I have flushed my random one-liner patch from my system, and
> expect to get a proper fix through the normal networking pulls.
> 
> And _if_ the networking people feel that my one-liner was the proper
> fix, you can use it and add my sign-off if you want to, but it really
> was more of a "this is the quick ugly fix for testing" rather than
> anything else.
> 

Please add:

  Link: https://lore.kernel.org/linux-mm/20210106180132.41dc249d@gandalf.local.home/
  Reported-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

And if you take Linus's patch, please add my:

  Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

and if you come up with another patch, please send it to me for testing.

Thanks!

-- Steve

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

* Re: [BUG] from x86: Support kmap_local() forced debugging
  2021-01-07 20:52               ` Steven Rostedt
@ 2021-01-07 21:07                 ` Willem de Bruijn
  0 siblings, 0 replies; 9+ messages in thread
From: Willem de Bruijn @ 2021-01-07 21:07 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Linus Torvalds, Jakub Kicinski, David Miller, Jonathan Lemon,
	Thomas Gleixner, LKML, the arch/x86 maintainers,
	Christoph Hellwig, Matthew Wilcox, Daniel Vetter, Andrew Morton,
	Linux-MM, Peter Zijlstra, Ingo Molnar, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Netdev

On Thu, Jan 7, 2021 at 3:53 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Thu, 7 Jan 2021 11:47:02 -0800
> Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
> > On Wed, Jan 6, 2021 at 8:45 PM Willem de Bruijn <willemb@google.com> wrote:
> > >
> > > But there are three other kmap_atomic callers under net/ that do not
> > > loop at all, so assume non-compound pages. In esp_output_head,
> > > esp6_output_head and skb_seq_read. The first two directly use
> > > skb_page_frag_refill, which can allocate compound (but not
> > > __GFP_HIGHMEM) pages, and the third can be inserted with
> > > netfilter xt_string in the path of tcp transmit skbs, which can also
> > > have compound pages. I think that these could similarly access
> > > data beyond the end of the kmap_atomic mapped page. I'll take
> > > a closer look.
> >
> > Thanks.
> >
> > Note that I have flushed my random one-liner patch from my system, and
> > expect to get a proper fix through the normal networking pulls.
> >
> > And _if_ the networking people feel that my one-liner was the proper
> > fix, you can use it and add my sign-off if you want to, but it really
> > was more of a "this is the quick ugly fix for testing" rather than
> > anything else.

I do think it is the proper fix as is. If no one else has comments, I
can submit it through the net tree.

It won't address the other issues that became apparent only as a
result of this. I'm preparing separate patches for those.

> Please add:
>
>   Link: https://lore.kernel.org/linux-mm/20210106180132.41dc249d@gandalf.local.home/
>   Reported-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
>
> And if you take Linus's patch, please add my:
>
>   Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
>
> and if you come up with another patch, please send it to me for testing.
>
> Thanks!

Will do, thanks.

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

end of thread, other threads:[~2021-01-07 21:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20201118194838.753436396@linutronix.de>
     [not found] ` <20201118204007.169209557@linutronix.de>
     [not found]   ` <20210106180132.41dc249d@gandalf.local.home>
2021-01-07  1:03     ` [BUG] from x86: Support kmap_local() forced debugging Linus Torvalds
2021-01-07  1:16       ` Steven Rostedt
2021-01-07  1:49       ` Steven Rostedt
2021-01-07  1:49       ` Jakub Kicinski
2021-01-07  2:11         ` Willem de Bruijn
2021-01-07  4:44           ` Willem de Bruijn
2021-01-07 19:47             ` Linus Torvalds
2021-01-07 20:52               ` Steven Rostedt
2021-01-07 21:07                 ` Willem de Bruijn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox