Implement syscall user memory validation #30
Reference in New Issue
Block a user
No description provided.
Delete Branch "user-memory"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
In addition to the checks previously implemented, we also needed to check the memory is accessible using either a page check, or a page fault check.
I opted for the page fault check simply because (as per spec) it has better performance. This stems from relying on the CPU MMU to interrupt rather than checking via the page table.
Changes:
sizeof (unsigned)instead of1when gettingsyscall_number.uint32_texplicitly when retrieving arguments (instead ofuintptr_t), since spec mentions 32-bit words.get_userandput_userchecks intovalidate_user_pointer, but make the write check optional.validate_user_pointerNOT callthread_exit ()itself, because once we implement other syscalls, according to the spec we will endup with some mallocs and locks which will need to be freed beforethread_exit ()is called, but after the pointer is found to be invalid usingvalidate_user_pointer.TODO:
requested review from @td1223
I see this is related to system calls. I will have a look tomorrow and reply accordingly.
changed the description
changed the description
changed the description
changed the description
I realise now this implementation doesn't handle ranges very well (e.g. buffers, strings). It feels like we have to do a for-loop for those, but that just feels wrong... what do you think?
changed the description
Hi Gleb,
Thanks for the comments! Really appreciated.
Yes, we forgot to check that the user address does map to a kernel address. This will be added in the checks in the next commits.
I am not sure about the page fault check to be honest. Not only does it complicate reading the code but it feels (at least to me) like very bad practice. I will however give it a thought before the final PR of system-calls.
As for the changes:
As for your last question, the current way would be (assume validate_user_ptr does its job correctly) is to just call validate_user_ptr on the size required of the buffer / string.
Again, many thanks for your comments. I will fix / consider all these points in the final PR of system calls.
LMK what you think.
Sorry for being unclear. I meant that we did indeed forget the check that the user address is mapped (page_get_page != NULL). We have just added this into the branch.
As it stands, system-calls passes all systems calls tests!
For 1&2, please don't worry about it I will implement it myself later on but thanks!
But yes, validate_user_ptr will have to be changed definitely. I will write another implementation into the file this weekend along with the system call PR.
For (2), I am not sure what do you mean to be honest. If the user passes 100 arguments that should be fine. We will only read how many 32-bits uints we need based on the number. This cannot lead to any problems because 1. syscall number is guaranteed to be correct by this point 2. the memory must be valid and have at least these arguments (assuming validate_user_ptr works). So the case when more arguments are handled is implicitly handled by just ignoring these arguments (which is easily testable by adding any number of args to any of the tests and verifying they do pass which they do). Did you mean the thread should be killed in that case? It feels very weird to me if I am being honest. The stack may have other things for subsequent system calls.
(5) Yes as I said I will have a look at the function later and reimplement. I will make the reviewer of the PR for the fix.
Thx.
Ah okay I’ll keep this MR on hold then, we can discuss whether there’s any point using the page fault method later.
About the arguments - yes the memory is valid, BUT we are copying it to the args[3] array, which is obviously limited to 3 arguments. So with 4+ arguments args[i] eventually overflows the array into whatever.
I’m not saying we should fail these cases, but simply that we should ONLY save up to 3 arguments to the args[3] array (as in my implementation).
added 54 commits
master83e044cf- Let kernel handle its own page faults44f6a851- Add get_user and put_user provided by spec.9a6abab9- Check access to user memory using page fault method (via get_user and put_user).Compare with previous version
added 1 commit
cf4bf90c- Implement user pointer checking for C stringsCompare with previous version
requested review from @sb3923 and removed review request for @td1223
resolved all threads
marked the checklist item How do we handle memory ranges (buffers, strings, ...)? Literally just a for loop checking every pointer within, or what? as completed
added 1 commit
59e7a64f- Only check user pages rather than all bytes in-between, for known-size pointersCompare with previous version
This isn't needed anymore in favour of the first method, which is a bit cleaner exception-handling wise.
Pull request closed