Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
.eh_frame: Read user stacks from kernel context
Context ======= If frame pointers are available not things are easier because you don't have to implement a DWARF-custom format and an unwinder but also because `bpf_get_stackid` with the `BPF_F_USER_STACK` flag to fetch user stacks does most of the work for us. This includes handling user stacks when we are in a kernel context, such as when we are executing a system call. What happens in this case is that the registers get saved at a particular memory location and the registers that the kernels pass us are the current registers, with all the state set in the kernel, as we are executing kernel code. Hence, we need a way to recover said stored registers. If we were building a kernel extension we would use the `task_pt_regs` macro. There's a new helper [1] to achieve exactly this, `bpf_task_pt_regs`, but unfortunately we can't always rely on it's included only in v5.15 or greater. Proposed solution ================= We walk the internal kernel datastructures until we can read the x86_64 registers we need. In case we are in kernel context, and current thread is not a kernel process (kworker), we read the saved task's registers and continue the normal unwinding process. Notes ===== For some reason, not really sure about why; needs more investigation, writing this code has not been a walk in the park. The verifier didn't allow me to do direct pointer dereferences, that's why the code is littered with manual ones. Mostly complained with > `avoid R0 invalid mem access 'scalar'` The other interesting bit is that I can't make the verifier pass when checking for the return value of `set_initial_state` and returning if there is an issue. > dereference of modified ctx ptr R6 off=32 disallowed Additonally, the full `vmlinux.h` has been dumped as we need the definition of a bunch of structs. Future changes / areas of improvement ===================================== - Once we have automatic feature calibration we can use the new helper, if available, which will be more reliable; - This code is pretty fragile. Any changes in the running box, such as running with KASAN=on, will make it fail, resulting in missing kernel stacks; Test Plan ========= Ran it for 1h without issues. The kernel stacks now appear and look reasonable. See PR for more. **kernel tests** ``` ============= Test results: ============= - ✅ 5.4 - ✅ 5.10 - ✅ 5.18 - ✅ 5.19 ``` - [0]: https://github.com/torvalds/linux/blob/3d7cb6b04c3f3115719235cc6866b10326de34cd/arch/x86/include/asm/processor.h#L758-L763 - [1]: torvalds/linux@dd6e10f Signed-off-by: Francisco Javier Honduvilla Coto <[email protected]>
- Loading branch information