bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Gnumach and I/O


From: Samuel Thibault
Subject: Gnumach and I/O
Date: Sun, 8 Jan 2006 18:50:40 +0100
User-agent: Mutt/1.5.9i-nntp

Just for reminding what's on the bts:

Trying to apply [ patches 
http://savannah.gnu.org/patch/download.php?item_id=4737&item_file_id=5662 (user 
tss fixup) , 
http://savannah.gnu.org/bugs/download.php?item_id=15295&item_file_id=3237 (no 
io perms by default), and 
http://savannah.gnu.org/bugs/download.php?item_id=15295&item_file_id=3238 
(device port handling fix) ] does work as expected for single-threaded programs 
like ioport/ioport2/ioport3. I patched my Hurd console to use i386_io_port_add, 
it now works.

However, some illegal instructions still happen because for now, gnumach's io 
permissions are thread-specific, so that only the thread that called 
i386_io_port_all has i/o access. I guess this will be a problem for almost 
every program: people usually expect i/o permissions to be for the whole task, 
not for a single thread. Some libraries will even create threads and call some 
callbacks within them, and these callbacks could potentially need i/o 
permissions (this is what happens with the Hurd console).

So I'd say we should turn gnumach to handle io permissions per task. This 
doesn't pose any technical problem, since until now every task/thread was using 
the kernel tss ; it's just a matter of storing the tss per task, not per thread.

Well, actually, gnumach2 does indeed set i/o port permissions on tasks rather 
than on threads. [ Patch 
http://savannah.gnu.org/bugs/download.php?item_id=15295&item_file_id=3240 (TSS 
is now task-based) makes ] gnumach1 behave that way too.

But what about the interface?

- gnumach1 provides i386_io_port_add(thread, dev) which adds device-defined 
ports to allowed ones: for instance, device "kd" has video registers (I'd add 
speaker ports though, since they are used too) ; device "iopl" has a bunch of 
registers: speaker, game port, sound, printer, video, and gives read-only 
access to any i/o port.
- gnumach2 provides i386_io_perm_create(master, from, to, &new_io_perm) for 
creating an "i/o range" and i386_io_perm_modify(task, io_perm, enable) for 
enabling/disabling access to the range.
- glibc usually provides a mere ioperm(base, count, enable) that just 
sets/clears bits, but how to implement that easily with the two interfaces 
above?

As far as the Hurd is concerned, only the console needs i/o ports: vga & 
speaker access. Using either of the 3 interfaces above is fine ; currently, 
ioperm() is used (and ENOSYS is ignored for the gnumach1 case). I have a small 
patch for making it use the gnumach1 interface.

On the other hand, XFree86 and Xorg actually need hardly any port access: they 
have to poke pci config, pci video registers, etc ; the hook there is hence 
just "enable full I/O access". For this, the current gnumach1 
i386_io_port_add() implementation isn't suited: it would require defining a 
65537-sized array of every numbers between 0 and 65535... While the gnumach2 
and ioperm() interfaces would be fine.

So, what should we do? Gnumach1 was left with an i/o security issue opened for 
years now. It wasn't very serious so far, but there are now hurd boxes on the 
Internet which really deserve fixing that issue on the short term. Here are 
some possibilities:

- I already have small working patches for making gnumach1 i/o protected, 
letting the gnumach1 interface as is, and making the Hurd console use it for 
port access [ See patch 
http://savannah.gnu.org/bugs/download.php?item_id=15295&item_file_id=3241 which 
makes the Hurd console call i386_io_port_add ]. This would be just fine for 
these text-only hurd boxes. XFree86/Xorg will work with ISA video boards (I 
have small working patches), but not with PCI devices (needs full I/O access). 
This is hence sufficient for X to work in qemu -isa.
- Same as above, plus we define an "all I/O ports" gnumach1 device, either with 
an ugly-but-interface-compliant 65537 array, with a special value, or with some 
evil bypass hack. X on PCI devices would then become possible. I still don't 
know how to easily implement glibc's ioperm().
- We backport the gnumach2 interface to gnumach1. It shouldn't be hard, but the 
patch would get quite bigger. Same remarks as just above.
- We define yet another interface, having in mind the future L4/Hurd port.

Gnumach1's interface is interesting in that it could, in a way, arbitrate i/o 
port access between tasks. It could be difficult to really achieve perfect 
separation, though. Gnumach2's design looks much like glibc's raw ioperm(), 
with some sexy "enable/disable this io_perm" shortcut.

I'm not sure whether fancy design makes sense here. Note that current 
implementations in gnumach 1 and 2 have a bug: if a task asks for i/o access to 
speaker+video (represented by some port A), asks i/o access to video (port B), 
and then drops its i/o access to speaker+video (port A), access to video (port 
B) doesn't work! (because the i/o bitmap is blindly modified when dropping port 
A) This would happen with glibc's ioperm() semantic too, but the application 
programmer is aware of that. This example shows how fancy design is tricky to 
implement, and I'm not sure whether we really want to implement that in the 
gnumach kernel. Actual i/o port use is generally quite trivial, and if 
programmers really want fancy i/o bitmaps handling, they can implement it 
themselves in their application with the only help of a raw ioperm()-like call.

[ Patch 
http://savannah.gnu.org/bugs/download.php?item_id=15295&item_file_id=3254 ] 
adds an "io" device representing all IO ports. It uses a special value so as to 
avoid an ugly 65537 array. X on PCI devices now becomes possible [ see patch 
http://savannah.gnu.org/bugs/download.php?item_id=15295&item_file_id=3255 .]

Regards,
Samuel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]