-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix potential bad pointer deref in minix fs #1793
Conversation
If minix_bread fails, bh will be NULL, and the loop simply advances to the next directory entry. During the next iteration, index won't be at a block boundary, so won't try to set bh, yet minix_match() will dereference it.
Nice catch! I'm assuming you're using your more sophisticated analysis tools on the kernel now? While this fix definitely solves the NULL
The 2nd change might be a bit easier due to its loop design. Both bigger changes would likely need to be heavily tested to ensure correctness. If this sounds like more than you'd like to jump into at the moment, we can accept this PR as-is and I'll make a note to perform the above changes at a later date. |
After I opened this PR, I was thinking about the repeated tries as you point out, but also thinking that it's strange that a kernel function could silently fail. I suppose that in some scenario, a user program could end up seeing ENOENT instead of EIO. I'll take your suggestion, and think about this more. This would be fun to make robust. |
Due to the way that the kernel filesystem code interacts with the async- and shared- block I/O subsystem, along with multi-tasking issues around simultaneously accessed blocks, it is very tricky to report back filesystem-related block I/O errors to an individual application. This is because it can't be guaranteed that the application that requested a given block I/O transaction is the same one that first or eventually gets the buffer header, and this a known area of tricky race conditions. I don't recommend going overboard trying to "fix" this, as the entire filesystem codebase has the same issues. Frankly, given your insight about the possibility of ENOENT rather than EIO above, which I hadn't fully considered, and the already-existing problem of the kernel being on the verge of being too large, it might be worth considering the idea of aborting the directory search immediately upon encountering a getblk I/O error and returning NULL. The user (if watching) would see the kernel error display and accept an incompleted result as OK, rather than continuation across a bad block read. That said, it's quite tricky to second guess kernel semantics without an extensive test suite that can simulate I/O errors, something we don't yet have. Looking at the Linux 2.0 source, which I sometimes do in cases like this, I see that the bug was noticed and resolved by attempting continuation, rather than aborting. Perhaps this is under the idea its better to complete a task if possible, rather than aborting early with a particular error code: Linux 2.0 fs/minix/namei.c:
I suppose after looking at this code, I would suggest not trying to get into a heavy kernel rewrite for error correctness at the expense of kernel size and continuation of execution if possible if not required; early termination could result in an otherwise usable filesystem becoming unusable for all directory entries past a bad sector, for instance. What do you think? |
If minix_bread fails, bh will be NULL, and the loop simply advances to the next directory entry. During the next iteration, index won't be at a block boundary, so won't try to set bh, yet minix_match() will dereference it.
Found by static analysis.