Linux kernel GDT layout

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
growlnx
Posts: 15
Joined: Sun Jan 05, 2020 5:51 pm
Libera.chat IRC: growlnx
Location: 0.0.0.0
Contact:

Linux kernel GDT layout

Post by growlnx »

Hi all,

A way to "disable" segmentation is use on big segment (flat model), right?
Image from book "Understanding the LINUX KERNEL THIRD EDITION"
Image from book "Understanding the LINUX KERNEL THIRD EDITION"
Image from book "Understanding the LINUX KERNEL THIRD EDITION"
Image from book "Understanding the LINUX KERNEL THIRD EDITION"
Why dont' use only one segment?

Does the DPL will really make difference here?
Regards,
Growlnx.
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Linux kernel GDT layout

Post by nexos »

No matter what, you will always need 4 segments. Note that these segments are all flat. The reason why is because all instruction access implicitly use the CS register, all data access use the DS register, and all stack access use the SS register. DS and SS can share a segment, but CS requires its own format. This means that a ring 0 only OS will need two segments, kernel code and kernel data. User mode requires two segments as well, user code and user data. User code / data must have a different segment then kernel code / data, as otherwise, user code could trap into kernel mode with ease, hence destroying security. Also, every CPU requires its own descriptor for the TSS, which goes into the TR register. The TSS is needed for user mode to kernel mode transitions.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
User avatar
growlnx
Posts: 15
Joined: Sun Jan 05, 2020 5:51 pm
Libera.chat IRC: growlnx
Location: 0.0.0.0
Contact:

Re: Linux kernel GDT layout

Post by growlnx »

nexos wrote:User code / data must have a different segment then kernel code / data, as otherwise, user code could trap into kernel mode with ease, hence destroying security. Also, every CPU requires its own descriptor for the TSS, which goes into the TR register. The TSS is needed for user mode to kernel mode transitions.
With this layout of GDT will the user be able to read kerneland instructions (ignoring the paging protections)?

The DPL flag will restrict the user to execute ring 0 instructions, but what about change?
Regards,
Growlnx.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Linux kernel GDT layout

Post by nullplan »

growlnx wrote:With this layout of GDT will the user be able to read kerneland instructions (ignoring the paging protections)?

The DPL flag will restrict the user to execute ring 0 instructions, but what about change?
Not entirely sure what you mean here but user code will run at CPL 3, and thus not qualify for supervisor pages, which is why access to kernel code and data will trap. User code can also not change the CPL without simultaneously changing rIP. And user code cannot even read supervisor pages, never mind changing them.
Carpe diem!
User avatar
growlnx
Posts: 15
Joined: Sun Jan 05, 2020 5:51 pm
Libera.chat IRC: growlnx
Location: 0.0.0.0
Contact:

Re: Linux kernel GDT layout

Post by growlnx »

nullplan wrote:
growlnx wrote:With this layout of GDT will the user be able to read kerneland instructions (ignoring the paging protections)?

The DPL flag will restrict the user to execute ring 0 instructions, but what about change?
Not entirely sure what you mean here but user code will run at CPL 3, and thus not qualify for supervisor pages, which is why access to kernel code and data will trap. User code can also not change the CPL without simultaneously changing rIP. And user code cannot even read supervisor pages, never mind changing them.
I'm imagining a fictional scenario where the kernel does not implement pagination/virtual memory, where it only has this GDT segmentation layout.

In this scenario, will the user be able to edit kerneland code/instructions?
Regards,
Growlnx.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Linux kernel GDT layout

Post by nullplan »

growlnx wrote:In this scenario, will the user be able to edit kerneland code/instructions?
Well, yes. If you throw away all paging protection yes, the user is able to write anywhere. That's rather like saying "if you remove the lock from my door, the door will be insecure", but there you go.
Carpe diem!
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Linux kernel GDT layout

Post by bzt »

growlnx wrote:I'm imagining a fictional scenario where the kernel does not implement pagination/virtual memory, where it only has this GDT segmentation layout.

In this scenario, will the user be able to edit kerneland code/instructions?
Your question is wrong. The privilege level is set up when the CS register is loaded. You simply cannot load CS with DPL 3 if it's pointing to a GDT entry with RPL 0, that would trigger a general protection fault. The reason for the two separated segment descriptors in GDT is because user code points to one, and kernel code to another, that's what actually creates the separation between user space space (ring 3) and kernel space (ring 0) with different CPLs. Add to that that there's a need for separated code and data segments, and you'll have 4 segments at minimum: user data, user code, kernel data, kernel code.

Cheers,
bzt
rdos
Member
Member
Posts: 3297
Joined: Wed Oct 01, 2008 1:55 pm

Re: Linux kernel GDT layout

Post by rdos »

nullplan wrote:
growlnx wrote:In this scenario, will the user be able to edit kerneland code/instructions?
Well, yes. If you throw away all paging protection yes, the user is able to write anywhere. That's rather like saying "if you remove the lock from my door, the door will be insecure", but there you go.
Yes, and so userland CS & DS should not map kernelland. If the kernel is loaded in upper memory, this is easily fixed by setting a lower limit for the userland flat selector.

Also, if pointers from userland use userland flat selectors that don't map kernelland this also means that pointers passed to kernel with syscalls cannot be used to sabotage kernel space data or code.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Linux kernel GDT layout

Post by bzt »

I'm still not sure if we understand the question, it's wage. Segmentation and paging are two totally independent things, and the CPL is defined by the segment, so it works even without paging.

In protected mode, the segment descriptors also specify the base and the size of the segment. We are only talking about "flat model", when all the segments have base 0 and size -1.
In non-flat model, you can configure each segment to point to a different area in memory, so you can separate user space and kernel space without paging.

But, because you can use flat model and still want to separate user and kernel space, you can also enable paging, and force a more finely granulated, page-based security via the mapping.

That was all for protected mode. In long mode, segments are not used, so there's no point in "disabling" the segmentation in the first place. It is already disabled, and you can't enable it. Segment descriptors are merely loaded to set the CPL flag in CS, and it is totally irrelevant what the other bits are, what you set up in base and size, you'll always get the flat model. Also unlike in protected mode, paging must be enabled (so you can't disable it), therefore security via mapping is the one and only (and mandatory) way to separate which memory can be accessed from user land.

Does this makes sense to you?

Cheers,
bzt
User avatar
growlnx
Posts: 15
Joined: Sun Jan 05, 2020 5:51 pm
Libera.chat IRC: growlnx
Location: 0.0.0.0
Contact:

Re: Linux kernel GDT layout

Post by growlnx »

bzt wrote:
growlnx wrote:I'm imagining a fictional scenario where the kernel does not implement pagination/virtual memory, where it only has this GDT segmentation layout.

In this scenario, will the user be able to edit kerneland code/instructions?
Your question is wrong. The privilege level is set up when the CS register is loaded. You simply cannot load CS with DPL 3 if it's pointing to a GDT entry with RPL 0, that would trigger a general protection fault. The reason for the two separated segment descriptors in GDT is because user code points to one, and kernel code to another, that's what actually creates the separation between user space space (ring 3) and kernel space (ring 0) with different CPLs. Add to that that there's a need for separated code and data segments, and you'll have 4 segments at minimum: user data, user code, kernel data, kernel code.

Cheers,
bzt
Cool, now I understand the real reason for having a segment with the same mapping for ring 3. It is because of the general protection fault.
Regards,
Growlnx.
Post Reply