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 _______________________________________________ Bug-hurd mailing list Bug-hurd@gnu.org http://lists.gnu.org/mailman/listinfo/bug-hurd