Parameter validation in long mode vs segmented mode
Posted: Mon Dec 31, 2012 6:33 am
I'm trying to design safe strategies for long mode applications so they cannot pass pointers to kernel and let kernel do operations the application itself cannot do.. This seems a lot more complex than I first thought.
Some problems:
1. Application could forge pointer to kernel space
2. Application could pass pointers to unallocated memory
3. Application could pass buffers that are only partially valid
For my 32-bit flat applications, most of these issues are solved by limiting the scope of the flat application selector to only cover valid application space. Particularly, this solves the issue of forging kernel-space pointers, and partly also issue #3. Issue #2 is solved in the page fault handler. A draw-back for 32-bit is that faults will occur in kernel or driver on behalf of the application, but the logic is fast and require no validation of APIs at all.
For 64-bit it is quite different. The kernel cannot automatically detect that a pointer is outside of the valid region of the application, but must check it's limits. Not only that, but it must know the size of the buffer, and at least must know that the end of the buffer is also within application space. Two solve #2, it seems more practical to validate each page-table entry that the buffer covers for validity. In fact, the overhead needed when running a 64-bit application under a 32-bit OS seems to be needed even when running a 64-bit application under a 64-bit OS. It doesn't take much longer to validate page-table entries of a buffer compared to validating and copying them to below 4G. A definite advantage of this is that the kernel could refuse to do requests that involve invalid buffers, and that faults no longer would occur in kernel-space on behalf of the application.
How do others solve these issues?
Some problems:
1. Application could forge pointer to kernel space
2. Application could pass pointers to unallocated memory
3. Application could pass buffers that are only partially valid
For my 32-bit flat applications, most of these issues are solved by limiting the scope of the flat application selector to only cover valid application space. Particularly, this solves the issue of forging kernel-space pointers, and partly also issue #3. Issue #2 is solved in the page fault handler. A draw-back for 32-bit is that faults will occur in kernel or driver on behalf of the application, but the logic is fast and require no validation of APIs at all.
For 64-bit it is quite different. The kernel cannot automatically detect that a pointer is outside of the valid region of the application, but must check it's limits. Not only that, but it must know the size of the buffer, and at least must know that the end of the buffer is also within application space. Two solve #2, it seems more practical to validate each page-table entry that the buffer covers for validity. In fact, the overhead needed when running a 64-bit application under a 32-bit OS seems to be needed even when running a 64-bit application under a 64-bit OS. It doesn't take much longer to validate page-table entries of a buffer compared to validating and copying them to below 4G. A definite advantage of this is that the kernel could refuse to do requests that involve invalid buffers, and that faults no longer would occur in kernel-space on behalf of the application.
How do others solve these issues?