Linux kernel GDT layout
- 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
Hi all,
A way to "disable" segmentation is use on big segment (flat model), right?
Why dont' use only one segment?
Does the DPL will really make difference here?
A way to "disable" segmentation is use on big segment (flat model), right?
Why dont' use only one segment?
Does the DPL will really make difference here?
Regards,
Growlnx.
Growlnx.
Re: Linux kernel GDT layout
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.
- 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
With this layout of GDT will the user be able to read kerneland instructions (ignoring the paging protections)?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.
The DPL flag will restrict the user to execute ring 0 instructions, but what about change?
Regards,
Growlnx.
Growlnx.
Re: Linux kernel GDT layout
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.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?
Carpe diem!
- 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
I'm imagining a fictional scenario where the kernel does not implement pagination/virtual memory, where it only has this GDT segmentation layout.nullplan wrote: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.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?
In this scenario, will the user be able to edit kerneland code/instructions?
Regards,
Growlnx.
Growlnx.
Re: Linux kernel GDT layout
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.growlnx wrote:In this scenario, will the user be able to edit kerneland code/instructions?
Carpe diem!
Re: Linux kernel GDT layout
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.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?
Cheers,
bzt
Re: Linux kernel GDT layout
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.nullplan wrote: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.growlnx wrote:In this scenario, will the user be able to edit kerneland code/instructions?
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.
Re: Linux kernel GDT layout
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
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
- 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
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.bzt wrote: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.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?
Cheers,
bzt
Regards,
Growlnx.
Growlnx.