Page 2 of 4

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 8:05 am
by Brendan
Hi,
gerryg400 wrote:
Brendan wrote:For IO ports there's 3 options:
  • Use IO permission bitmap in TSS
    Emulate instructions that use IO ports in the general protection fault handler
    Provide syscalls for IO port accesses (so a driver asks kernel to access the IO port)
Setting IOPL to 3 doesn't quite work, as you'd be giving a driver access to all IO ports and it'd be able to interfere with things it shouldn't be able to (e.g. disable A20 gate and crash the OS, etc).
Brendan, I think your 4th option is actually quite reasonable and deserves to be considered. Even if it doesn't prevent driver processes from accessing pretty much anything they like, it is possible to limit the number of processes that get IO privilege to a small set of trusted processes. It's still better protection than monolithic kernels provide. Drivers are often easier to review and test then say filesystems so there is still a win.
A micro-kernel sacrifices some performance (due to IPC costs), and the only reason to do this is to avoid the need for "trusted drivers".

You should be able to download a "binary blob" device driver via. a Chinese peer to peer file sharing site (that was uploaded by a guy who calls himself "PawninU"), and use that driver on a server for an international bank without worrying about anything (other than the driver crashing or not working with the device) because you're using a micro-kernel. 8)
gerryg400 wrote:How does the kernel decide which processes are allowed to access which ports? How does it know what the conditions for access are?
That information is trivial to obtain from PCI configuration space BARs. Of course I'd have a "device manager" process that does device enumeration, etc (and starts drivers, and tells kernel which driver should be allowed to use which resources).
gerryg400 wrote:How does the kernel store this information?
It's also trivial to add a few fields to whatever the kernel uses as a "process data structure".


Cheers,

Brendan

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 5:05 pm
by physecfed
gerryg400 wrote:Using system calls for IO adds a lot of complexity to the kernel. I presume you intend to limit access to various ports on a process by process basis. I think this means that need to have a system call that provides that access under certain conditions. How does the kernel decide which processes are allowed to access which ports? How does it know what the conditions for access are? How does the kernel store this information? To be honest I can't see any benefit using kernel calls to do IO. No complexity is saved and no gain is made by this method that I can see.
At this point, I see three advantages to that method:
  • It's intuitive. It'll probably be easier to plumb the driver-hardware I/O through the kernel at first, and later change or rewrite those services later on. As I've never had a working kernel before, I'm putting priority on one that works, rather than one that works quickly.
  • The security implications are a little better. It makes a little more sense to me, at least at this point, to leave I/O and memory-map permissions to the kernel as the kernel is already part of the trusted computing base and allowing the devices to abstract over their own access might violate that "total security" somewhat. It's hard to say for sure without a good look at the structure of existing microkernels.
  • Portability. If the kernel abstracts much of the I/O and memory/paging access, less has to be changed to port the kernel to a new architecture. In fact, there'd be a significant possibility some drivers, such as PCIe cards, might be able to port over their drivers completely unchanged, or slightly changed for endianness' sake.
Using kernel facilities to limit I/O access also means I can pursue other means of performing the I/O permissions. Such as establishing a table with bases and limits, rather than an individual bitmap like the TSS uses. Putting that faculty in the device manager subprocesses of the kernel also means that each process need not have its own - drivers can query for their permissions from the master on initialization, and they can be updated via IPC when or if it changes. Things such as segmenting various ports into groups, and assigning processes to permission groups during config and changing via IPC.

I'm open for discussion on that idea. The first reason I was looking at doing syscall-based I/O was that it made enough sense, and it was low-speed enough that the performance losses aren't likely to be egregious.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 5:37 pm
by gerryg400
Brendan wrote:A micro-kernel sacrifices some performance (due to IPC costs), and the only reason to do this is to avoid the need for "trusted drivers".

You should be able to download a "binary blob" device driver via. a Chinese peer to peer file sharing site (that was uploaded by a guy who calls himself "PawninU"), and use that driver on a server for an international bank without worrying about anything (other than the driver crashing or not working with the device) because you're using a micro-kernel. 8)
When the blob says "I'm a keyboard driver, give me access to the IO ports related to the keyboard" how do you know to trust the blob?
Brendan wrote:That information is trivial to obtain from PCI configuration space BARs. Of course I'd have a "device manager" process that does device enumeration, etc (and starts drivers, and tells kernel which driver should be allowed to use which resources).

It's also trivial to add a few fields to whatever the kernel uses as a "process data structure".
Of course, linked lists, bitmaps, dynamic memory management and the like are trivial. But so is setting up the IO bitmap. The point is that this method saves no complexity over the other methods.

Also, is there really no concern that the timing requirements of some devices may not be able to be met with this scheme? And if IO is required to be done while processing an interrupt message (prior to sending the EOI at the end of processing) wouldn't there be a concern about the extra time taken to make all the system calls required to process the interrupt under this scheme. I'm really thinking that this method is probably unworkable.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 7:03 pm
by physecfed
gerryg400 wrote:
Brendan wrote:A micro-kernel sacrifices some performance (due to IPC costs), and the only reason to do this is to avoid the need for "trusted drivers".

You should be able to download a "binary blob" device driver via. a Chinese peer to peer file sharing site (that was uploaded by a guy who calls himself "PawninU"), and use that driver on a server for an international bank without worrying about anything (other than the driver crashing or not working with the device) because you're using a micro-kernel. 8)
When the blob says "I'm a keyboard driver, give me access to the IO ports related to the keyboard" how do you know to trust the blob?
Cryptographically sign or hash the driver. MD5/SHA1, for example.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 8:12 pm
by physecfed
Cryptographically signing or verifying drivers works for at least production code. There's a bigger security standpoint with respect to I/O permissioning by the kernel, however.

As Brendan said, one should be able to download a questionable driver from a questionable source without worrying about the system being compromised. For example, let's assume that keyboard driver was a keylogger designed to record any key traffic that it processes. It would declare itself as a keyboard driver, via some sort of class code or what not (somewhat like the PCI/PCIe BARs) in a data structure of the driver. That class code would give the driver permission to handle I/O abstraction (and possibly memory interaction) only in the port and/or MMU map ranges as specified by the kernel as appropriate for a driver class of "keyboard".

So what if it logs keystrokes? In order to do anything with these keystrokes, it would have to have access to faculties that are outside of the I/O scope it is designated, namely hard disk or networking processes. Because of the fact that the keylogging driver would only be given permissions to keyboard-related interactions, even a backdoored or compromised driver would not result in the compromise of the system or its users.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 8:14 pm
by FallenAvatar
physecfed wrote:Cryptographically sign or hash the driver. MD5/SHA1, for example.
Just FYI, neither MD5 or SHA1 are cryptographically secure anymore. I mean, SHA3 is "out" at this point...

- Monk

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 8:15 pm
by physecfed
tjmonk15 wrote:
physecfed wrote:Cryptographically sign or hash the driver. MD5/SHA1, for example.
Just FYI, neither MD5 or SHA1 are cryptographically secure anymore. I mean, SHA3 is "out" at this point...

- Monk
Right, but because of the avalanche effect in these hashes, a MD5 or SHA-1 sum is still quite useful in determining if a file has been altered or not.

You could sign a driver with a crypto algorithm such as a block cipher, but RSA invokes the issues of efficient large prime number generation and key factorization whereas AES raises the issue of securely transmitting and storing a key within a kernel. It also raises an ethical question (especially regarding open-source projects) because such encryption of drivers could become developer lockout.

MD5 or SHA-1 summing of a driver module for verification/integrity purposes is a relatively passive protection, but it works and I don't think I've ever seen a circumstance where a file has been compromised in a unique way as to yield a collision and therefore the same hash.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 8:29 pm
by FallenAvatar
physecfed wrote:
tjmonk15 wrote:
physecfed wrote:Cryptographically sign or hash the driver. MD5/SHA1, for example.
Just FYI, neither MD5 or SHA1 are cryptographically secure anymore. I mean, SHA3 is "out" at this point...

- Monk
Right, but because of the avalanche effect in these hashes, a MD5 or SHA-1 sum is still quite useful in determining if a file has been altered or not.

You could sign a driver with a crypto algorithm such as a block cipher, but RSA invokes the issues of efficient large prime number generation and key factorization whereas AES raises the issue of securely transmitting and storing a key within a kernel. It also raises an ethical question (especially regarding open-source projects) because such encryption of drivers could become developer lockout.

MD5 or SHA-1 summing of a driver module for verification/integrity purposes is a relatively passive protection, but it works and I don't think I've ever seen a circumstance where a file has been compromised in a unique way as to yield a collision and therefore the same hash.
It's pretty easy to make the changes an attacker might want, and then add garbage after the file in an "unused" section to cause a hash collision in MD5 or SHA1. Don't use them anymore for anything. MD5 has been completely broken for 5+ years (10?) and SHA1 about half that time.

- Monk

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 9:16 pm
by gerryg400
physecfed wrote:Cryptographically signing or verifying drivers works for at least production code. There's a bigger security standpoint with respect to I/O permissioning by the kernel, however.

As Brendan said, one should be able to download a questionable driver from a questionable source without worrying about the system being compromised. For example, let's assume that keyboard driver was a keylogger designed to record any key traffic that it processes. It would declare itself as a keyboard driver, via some sort of class code or what not (somewhat like the PCI/PCIe BARs) in a data structure of the driver. That class code would give the driver permission to handle I/O abstraction (and possibly memory interaction) only in the port and/or MMU map ranges as specified by the kernel as appropriate for a driver class of "keyboard".

So what if it logs keystrokes? In order to do anything with these keystrokes, it would have to have access to faculties that are outside of the I/O scope it is designated, namely hard disk or networking processes. Because of the fact that the keylogging driver would only be given permissions to keyboard-related interactions, even a backdoored or compromised driver would not result in the compromise of the system or its users.
Cryptographically signing the driver might work or might not work. If it does work then there is no need for the kernel API for IO at all and it would be possible to simply use in and out instructions from the certified userspace driver.

I'm still not sure how using a kernel API is a feasible approach. It's slower than any other method, it's certainly no less complex than any other method and it requires a cryptographically signed binary anyway to achieve security.
  • To address your 3 points directly
  • It's intuitive. No, it's much easier to use in and out instructions than pass those parameter to the kernel via a software interrupt or syscall.
  • The security implications are a little better. No, we now know that we need cryptographically signed binaries anyway so there is no gain there.
  • Portability. No, the kernel is not required for abstraction. Userspace libraries can do that too.

I'm still not convinced and am still worried about the performance and timing implications. I wonder has anyone on the list made this type of scheme work.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 11:00 pm
by physecfed
gerryg400 wrote:No, it's much easier to use in and out instructions than pass those parameter to the kernel via a software interrupt or syscall.
It would be no harder in the long run, once the system call framework is in place, to enable specific I/O input and output operations that accept port data, calling process ID and a string of data than it would be to directly enable the driver to do so directly.
gerryg400 wrote:No, we now know that we need cryptographically signed binaries anyway so there is no gain there.
Cryptographically signing the driver binaries and using hashes as a passive verification mechanism on initial driver load is a separate issue entirely to the use of the kernel to establish (and enforce) proper I/O permissions at the software-level for that driver.
gerryg400 wrote:No, the kernel is not required for abstraction. Userspace libraries can do that too.
Now you have to change and recompile the kernel, the libs, and the drivers for a different architecture, even in light of a common expansion unit or I/O device.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 11:01 pm
by FallenAvatar
gerryg400 wrote:
  • It's intuitive. No, it's much easier to use in and out instructions than pass those parameter to the kernel via a software interrupt or syscall.
I think the OP was saying that it was intuitive for them.
gerryg400 wrote:
  • The security implications are a little better. No, we now know that we need cryptographically signed binaries anyway so there is no gain there.
If you/OP/anyone is using a kernel API for in/out, a cryptographic hash isn't necessary. "Permissions" would be more than enough.
gerryg400 wrote:
  • Portability. No, the kernel is not required for abstraction. Userspace libraries can do that too.
Any OS that requires Userspace to deal with portability is a failure in this day and age (IMHO, IL of some sort is the way to go, compiled at install time) At the very least, it should be as easy as compiling multiple binaries from one codebase without any "#ifdef"s for arch(s).

- Monk

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 11:17 pm
by Boris
gerryg400 wrote:When the blob says "I'm a keyboard driver, give me access to the IO ports related to the keyboard" how do you know to trust the blob?
That's the beauty of it. you can always have a manifest of sorts which would list which is ports / IPC services the module requires.
If for example a keyboard driver requires something it is not supposed to ( network stack , filesystem) then don't load it.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 11:32 pm
by Rusky
gerryg400 wrote:When the blob says "I'm a keyboard driver, give me access to the IO ports related to the keyboard" how do you know to trust the blob?
That's missing the point. You have to trust some code to be your keyboard driver, no matter what kernel architecture you use. The benefit of a microkernel is that you don't have to trust the blob with anything else.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 11:39 pm
by physecfed
Boris wrote:
gerryg400 wrote:When the blob says "I'm a keyboard driver, give me access to the IO ports related to the keyboard" how do you know to trust the blob?
That's the beauty of it. you can always have a manifest of sorts which would list which is ports / IPC services the module requires.
If for example a keyboard driver requires something it is not supposed to ( network stack , filesystem) then don't load it.
This was exactly my line of thinking. If the driver identifies itself as belonging to a class (say "keyboard", to keep with the discussion), only grant it permissions for keyboard access. If it attempts to access services that it is not granted permissions to, the OS could either deny those requests or unload the driver entirely, depending on how critical the operation it performs is.

Of course, this doesn't prevent some odd behavior, such as a driver that simply transmutes the data (i.e. when an "A" is pressed, forward a "Q" to the kernel). In practice though, there is no reasonable precaution to be taken against that.

This also allows for the kernel to have some interesting/novel features to aid the programmer, as Brendan alluded to awhile back - the kernel could be instructed to log all driver I/O activity, for example, which would greatly aid in debugging new or experimental drivers.

Re: Monolithic vs. Microkernel hardware boot drivers

Posted: Sun Jul 10, 2016 11:42 pm
by gerryg400
tjmonk15 wrote:
gerryg400 wrote:
  • It's intuitive. No, it's much easier to use in and out instructions than pass those parameter to the kernel via a software interrupt or syscall.
I think the OP was saying that it was intuitive for them.
His full quote began " It's intuitive. It'll probably be easier to plumb the driver-hardware I/O through the kernel at first, and later change or rewrite those services later on." I was just pointing out that it's not easier.
tjmonk15 wrote:
gerryg400 wrote:
  • The security implications are a little better. No, we now know that we need cryptographically signed binaries anyway so there is no gain there.
If you/OP/anyone is using a kernel API for in/out, a cryptographic hash isn't necessary. "Permissions" would be more than enough.
It was the OP who offered that he is going to use cryptographic hashes to protect his kernel API. I never considered such a thing but since he is using them I thought that the kernel API was not necessary.
tjmonk15 wrote:
gerryg400 wrote:
  • Portability. No, the kernel is not required for abstraction. Userspace libraries can do that too.
Any OS that requires Userspace to deal with portability is a failure in this day and age (IMHO, IL of some sort is the way to go, compiled at install time) At the very least, it should be as easy as compiling multiple binaries from one codebase without any "#ifdef"s for arch(s).
Here we disagree. And I think that's okay. Remember we are talking about a microkernel here. Device drivers are not part of the kernel and so userspace and userspace libraries by design have more responsibility in this area than in a system with a monolithic kernel.