[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
- Gnumach and I/O,
Samuel Thibault <=