2

Some Background:

I have an embedded Linux ARM 4.1.33 system that has been patched with the preempt real-time patch. This system contains some custom modified kernel code, and was sporadically experiencing a kernel oops. After some debugging it was discovered that one of the developers didn't understand the distinction between kernel and user space, and that they were dereferencing user space pointers without using the functions defined in uaccess.h.

I have since modified the problematic functions to use the functions defined in uaccess.h, to prevent further kernel oops from occurring. I am now attempting to verify that fix was successful. However, since the original kernel oops happened randomly, sometimes not occurring for days at a time, I'd like to identify some method to reliably recreate it in the original code, and then verify that it no longer occurs in the updated code.

Although the problematic function was using the pointer incorrectly, it did appear to correctly modify the user space value using the pointer (excluding when the kernel oops occurred). This would indicate to me that the pointer's address "meant the same thing" in both user and kernel space. Given this fact, the only reason that I'm aware of that this dereferencing could cause a kernel oops would be if the page containing the address was sent to swap, resulting in a page fault. However, our system has swap disabled due to the limited longevity of our flash storage, making this scenario seem unlikely.

The Question(s):

What are the potential causes for a Linux kernel oops relating to dereferencing a user space pointer from within kernel space? How could I reliably cause such a kernel oops to occur, in order to verify that it no longer occurs after applying fixes?

4
  • 1
    Can you reliably pass in a NULL pointer from the user space?
    – thrig
    Oct 17, 2017 at 16:20
  • I can modify the user space code to force the supplied pointer to be NULL, yes. However, the original function contained a NULL check, something which I should probably have mentioned previously. The kernel space function appears to only ever be called with the address of user space local variable provided. So the function should never actually receive a NULL pointer. Most of the time the function works exactly as expected, despite being written in an unsafe manner. Sometimes however, despite the user space caller seemingly changing nothing, a kernel oops occurs.
    – Echo404
    Oct 17, 2017 at 17:39
  • 1
    Depending on your architecture, using a user pointer directly could provoke alignment exceptions, whereas code using copy_from_user() would probably anticipate such a need and provide destination space that is appropriately aligned (or bad code might provide it by accident, eg on the stack as a local variable).
    – meuh
    Oct 17, 2017 at 17:52
  • 1
    Even with no swap, the cpu may have limited hardware pte's, page table entries. This might make the automated conversion of the virtual address to the physical address fail, which would normally be handled within the copy_from_user() code.
    – meuh
    Oct 17, 2017 at 17:58

3 Answers 3

1

In addition to possibility of page being swapped out there are two other reasons why this could fail.

  1. If reading from user address, the page must be readable. Similarly for writing and executing.
  2. User space address doesn't belong to that process. Although kernel addresses have consistent one-to-one mapping with physical addresses, same virtual address in user space could point to a different physical address, depending upong current process.
0

It's possible to compile a 32 bit kernel so that processes get 4GB of address space (minus a few pages). If you had done this, all userspace pointers are invalid* in kernel space. But you would know you have done this.

*They might not crash; they might just point to arbitrary kernel memory, but writing to them is a recipe for an oops.

0

I don't have the capability to check at the moment or not, but I believe if the page was currently set to Copy-on-Write (probably by a prior fork() call) it will oops. Kernel pages aren't supposed to be Copy-on-Write.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.