mirror of
https://github.com/dynup/kpatch
synced 2025-01-09 06:39:26 +00:00
2f34cf9a89
This is an attempt to both simplify and improve the correctness of the NMI synchronization code. There's a race in kpatch_ftrace_handler() between the kpatch_get_func() and kpatch_finish_status() calls which could result in func being NULL. The retry was supposed to fix this. However, this race would still be a problem in the repatching case (if the function had already been previously patched), in which case func would not be NULL, but could instead point to the previously patched version of the function. In this case it wouldn't retry and it would be possible for the previous version of the function to run. The fix is to use a memory barrier between accesses of the func hash and the status variable, and then just call kpatch_get_func() *after* accessing the status variable. For OP_PATCH, if status is SUCCESS, then func is guaranteed to point to the new function. If status is FAILURE, func might point to the new function, in which case we can use get_prev_func to get the previous version of the function. I also made some pretty big changes to try to simplify the design so that there are less moving parts and so that it's hopefully easier to understand. I moved the OP field into the kpatch_func struct. This allows us to merge the two global state variables (status + op) into a single global state variable (state), which helps make the code quite a bit simpler. I turned it into a proper state machine and documented the meaning of each state in the comments. Moving the OP field to the kpatch_func struct also paves the way for an upcoming pull request which will allow patch modules to be atomically replaced ("kpatch load --replace <module>"). |
||
---|---|---|
.. | ||
core | ||
patch | ||
Makefile |