Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1603515 > unrolled thread

Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel

Started byLinus Torvalds <torvalds@linux-foundation.org>
First post2017-03-17 19:00 +0100
Last post2017-03-17 22:50 +0100
Articles 7 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-17 19:00 +0100
    Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-17 19:10 +0100
      Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-17 19:10 +0100
        Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Andy Lutomirski <luto@kernel.org> - 2017-03-17 19:30 +0100
          Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Andy Lutomirski <luto@amacapital.net> - 2017-03-17 21:20 +0100
            Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-17 22:20 +0100
          Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-17 22:50 +0100

#1603515 — Re: [x86] 45fc8757d1: BUG:unable_to_handle_kernel

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-03-17 19:00 +0100
SubjectRe: [x86] 45fc8757d1: BUG:unable_to_handle_kernel
Message-ID<tm4kr-1GF-49@gated-at.bofh.it>
On Fri, Mar 17, 2017 at 4:59 AM, kernel test robot
<xiaolong.ye@intel.com> wrote:
>
> FYI, we noticed the following commit:
>
> commit: 45fc8757d1d2128e342b4e7ef39adedf7752faac ("x86: Make the GDT remapping read-only on 64-bit")
> https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git x86/mm
>
> in testcase: boot
>
> [    4.347219] BUG: unable to handle kernel paging request at ffffffffff577060
> [    4.360480] Oops: 0003 [#1] SMP
> [    4.373550] RIP: 0023:0xf77e91ed
> [    4.375284] RSP: 002b:00000000ffed034c EFLAGS: 00010246

Heh. That's actually in user space, but the error code (0003) means
"protection fault on a write, not a user access".

So it's almost certainly something that tries to access a segment
descriptor in the GDT, but that segment was marked as "not accessed",
and the CPU was trying to set the accessed bit.

I *thought* we always maked everything accessed when we initialize it,
but something clearly is not.

That's why there's no kernel call trace or anything like that: it is a
system page fault, but it's triggered directly from user mode.

The linear address can be used to look up which entry it is. I assume
the GDT starts at ffffffffff577000, and that this is at offset 0x60
from that. Whatever descriptor that would be..

             Linus

[toc] | [next] | [standalone]


#1603518

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-03-17 19:10 +0100
Message-ID<tm4u5-21N-5@gated-at.bofh.it>
In reply to#1603515
On Fri, Mar 17, 2017 at 10:49 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> The linear address can be used to look up which entry it is. I assume
> the GDT starts at ffffffffff577000, and that this is at offset 0x60
> from that. Whatever descriptor that would be..

Hmm. That should be gdt index 12, aka GDT_ENTRY_TLS_MIN.

I guess user space can set almost anything there. Including setting a
segment type that isn't accessed, and that the CPU will change on the
first actual access.

We do have code to verify the limits and types etc iirc, I guess we
can make sure to set the accessed bit too.

              Linus

[toc] | [prev] | [next] | [standalone]


#1603522

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-03-17 19:10 +0100
Message-ID<tm4u6-21N-25@gated-at.bofh.it>
In reply to#1603518
On Fri, Mar 17, 2017 at 11:00 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Fri, Mar 17, 2017 at 10:49 AM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
>>
>> The linear address can be used to look up which entry it is. I assume
>> the GDT starts at ffffffffff577000, and that this is at offset 0x60
>> from that. Whatever descriptor that would be..
>
> Hmm. That should be gdt index 12, aka GDT_ENTRY_TLS_MIN.
>
> I guess user space can set almost anything there. Including setting a
> segment type that isn't accessed, and that the CPU will change on the
> first actual access.
>
> We do have code to verify the limits and types etc iirc, I guess we
> can make sure to set the accessed bit too.

Hmm. "fill_ldt()" does this:

        desc->type              = (info->read_exec_only ^ 1) << 1;
        desc->type             |= info->contents << 2;

which always leaves bit #0 of ->type clear. That's the A bit.

Does the problem go away if we just add a

        desc->type             |= 1;

to the end there?

But it is entirely possible that I'm missing something here. It's been
_years_ since I looked at descriptor table entries.

                Linus

[toc] | [prev] | [next] | [standalone]


#1603531

FromAndy Lutomirski <luto@kernel.org>
Date2017-03-17 19:30 +0100
Message-ID<tm4Ns-29P-21@gated-at.bofh.it>
In reply to#1603522
On Fri, Mar 17, 2017 at 11:07 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Fri, Mar 17, 2017 at 11:00 AM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
>> On Fri, Mar 17, 2017 at 10:49 AM, Linus Torvalds
>> <torvalds@linux-foundation.org> wrote:
>>>
>>> The linear address can be used to look up which entry it is. I assume
>>> the GDT starts at ffffffffff577000, and that this is at offset 0x60
>>> from that. Whatever descriptor that would be..
>>
>> Hmm. That should be gdt index 12, aka GDT_ENTRY_TLS_MIN.
>>
>> I guess user space can set almost anything there. Including setting a
>> segment type that isn't accessed, and that the CPU will change on the
>> first actual access.
>>
>> We do have code to verify the limits and types etc iirc, I guess we
>> can make sure to set the accessed bit too.
>
> Hmm. "fill_ldt()" does this:
>
>         desc->type              = (info->read_exec_only ^ 1) << 1;
>         desc->type             |= info->contents << 2;
>
> which always leaves bit #0 of ->type clear. That's the A bit.
>
> Does the problem go away if we just add a
>
>         desc->type             |= 1;
>
> to the end there?

I can easily imagine that breaking WINE or DOSEMU because it'll affect
the LDT, too.

How about this:

https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/commit/?h=x86/fixes&id=df8110544c6e899897e1b2ec3ab53d9e4ee40f65

I'll see why selftests didn't catch this, too.

[toc] | [prev] | [next] | [standalone]


#1603604

FromAndy Lutomirski <luto@amacapital.net>
Date2017-03-17 21:20 +0100
Message-ID<tm6vT-3sM-5@gated-at.bofh.it>
In reply to#1603531
On Fri, Mar 17, 2017 at 12:36 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Fri, Mar 17, 2017 at 11:20 AM, Andy Lutomirski <luto@kernel.org> wrote:
>>
>> I can easily imagine that breaking WINE or DOSEMU because it'll affect
>> the LDT, too.
>
> Can they even *read* the LDT contents, though? The whole accessed bit
> doesn't show up in 'struct user_desc', so you can neither set it nor
> read it.

LAR.  I've learned to never underestimate the absurdity of the games
played by 16-bit apps.  (See, for example, the fact that some of them
apparently use SGDT just to find a page that's guaranteed not to be
accessible.)

>
>> How about this:
>
> I don't think that's _wrong_, but..
>
> I'd really rather just do it in fill_ldt() itself, unless you can
> explain how it would be visible to anybody..

See above :(

(Also, your approach would probably break some selftests.)

--Andy

[toc] | [prev] | [next] | [standalone]


#1603626

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-03-17 22:20 +0100
Message-ID<tm7rY-495-1@gated-at.bofh.it>
In reply to#1603604
On Fri, Mar 17, 2017 at 1:18 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Fri, Mar 17, 2017 at 12:36 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
>>
>> Can they even *read* the LDT contents, though? The whole accessed bit
>> doesn't show up in 'struct user_desc', so you can neither set it nor
>> read it.
>
> LAR.  I've learned to never underestimate the absurdity of the games
> played by 16-bit apps.  (See, for example, the fact that some of them
> apparently use SGDT just to find a page that's guaranteed not to be
> accessible.)

Ugh. Right you are, LAR will return those type bits.

Of course, maybe somebody cares about them in the GDT already?  So
it's visible even with your patch, isn't it. We give users four
entries to play with...

                Linus

[toc] | [prev] | [next] | [standalone]


#1603641

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-03-17 22:50 +0100
Message-ID<tm6vT-3sM-7@gated-at.bofh.it>
In reply to#1603531
On Fri, Mar 17, 2017 at 11:20 AM, Andy Lutomirski <luto@kernel.org> wrote:
>
> I can easily imagine that breaking WINE or DOSEMU because it'll affect
> the LDT, too.

Can they even *read* the LDT contents, though? The whole accessed bit
doesn't show up in 'struct user_desc', so you can neither set it nor
read it.

> How about this:

I don't think that's _wrong_, but..

I'd really rather just do it in fill_ldt() itself, unless you can
explain how it would be visible to anybody..

               Linus

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web