Re: Securely removing the LDT restrictions (was: DOS4WG under dosemu)

Linus Torvalds (torvalds@cs.helsinki.fi)
Sat, 8 Jun 1996 12:30:48 +0300 (EET DST)


On Sat, 8 Jun 1996, Jamie Lokier wrote:
>
> Linus, a patch is enclosed preceded by plenty of explanation.
>
> The idea is to securely allow LDT entries that cover any address range,
> which appears to be required by some software running under dosemu.
> Notably, DOS4/GW which is used by many popular games, and some graphics
> software using DJGPP. Disregard or use as you wish. Ta.

Disregard.

DEFINITELY.

The page table changes are ok, and I'll probably do that for 2.1
regardless for other reasons. The kernel page tables have the USER bit
set for purely historical reasons that aren't true any more.

However, the idea to just get rid of the LDT sanity check is just silly.
Just make sure _before_ the system call that the application doesn't get
the full segment it's asking for: if it's not going to use the whole
segment anyway (like you claim), then there is no reason to give it the
segment in the first place.

In short, the change to make the kernel accept bad segments simply
doesn't make sense. Rethink your needs.

> Note that without this, your emumodule hack to simply remove the LDT
> restriction for root means that anyone can hack the kernel if they can
> run dosemu. They just run the kernel-scrubbing DPMI client of their
> choice.

Also, I'd suggest people re-think the whole emumodule stuff. It seems it's
all totally broken wrt LDT handling, and it's doing the wrong things with
no regard to security of good taste.

If you want to emulate DOS so well that you have an insecure system, why
the hell do you want to have Linux in the first place?

Ok, I've told some people about this already (Hi Hans), but let me spell
it out once more for those that haven't heard my position on it before.

The emumodule does lots of things that are totally broken.

This LDT stuff, for example, is so damn STUPID, that I can't really see
why you are doing it this way in the first place.

Dosemu people GET YOUR ACT TOGETHER! Don't do something just because it
fixes some silly problem you have, THINK about it first! Are you all
microsoft programmers?

For example, the mapping of the kernel LDT into user space with the
emumodule stuff. That is so stupid that it makes a grown man cry..

The _real_ way to handle this is that your DPMI stuff does something like
this when a program asks for a new segment:

- cache the LDT in USER space. Don't ask the kernel to do it for you:
you know what you want the LDT to contain, so _you_ should keep track
of the read-only segment descriptor table. The kernel keeps track of
it's own version of the LDT, and you shouldn't mess with that. Judicious
use of "mmap/mprotect/shmem" recommended to change your local cached
copy while still make it read-only to the DPMI client.

- do the kernel "set_ldt()" system call, and modify the parameters to be
safe _first_ so that it works with the kernel even though the kernel
checks that your parameters make sense). If you want to, you can use
the "unsafe" version in your local LDT cache (the one that the kernel
doesn't need to know anything about), so if the program then checks
what the LDT looks like it thinks it got the same segment it asked for
(but in _real_ life the kernel has the "safe" version).

Note, the above needs _no_ kernel support, and no emumodule braindamage.

In short, if you want to map in the LDT into user space, do it by hand.
Don't go crying for the kernel to do it - you have complete control over
the LDT anyway, so it doesn't make sense to have the kernel map in the
LDT read-only into user space because that would be just telling you
something you know already. You can create the user mapping by hand in
the same routine that does the kernel system call.

Linus