Download raw body.
Maintain preempted copy(9) state in stacktrace_save_utrace()
Maintain preempted copy(9) state in stacktrace_save_utrace()
Maintain preempted copy(9) state in stacktrace_save_utrace()
On 12/03/25(Wed) 21:42, Christian Ludwig wrote:
> Hi,
>
> A btrace(8) probe can run in interrupt context which preempts copy(9).
> Care must be taken getting userland stacktraces in that situation.
> stacktrace_save_utrace() uses copyin() itself, so we need to save and
> restore the preempted context's copy(9) state.
>
> This approach is less invasive than the previous one
> (https://marc.info/?l=openbsd-tech&m=174136347113129).
I'm still unhappy with this approach because it still uses the generic
copyin(9) entry point. What I suggested earlier was to use a different
entry, like db_copyin(). Otherwise we can't inspect copyin(9) with
btrace(8).
> Tested on amd64 and i386.
>
>
> - Christian
>
> ---
> sys/arch/amd64/amd64/db_trace.c | 7 +++++++
> sys/arch/i386/i386/db_trace.c | 7 +++++++
> 2 files changed, 14 insertions(+)
>
> diff --git a/sys/arch/amd64/amd64/db_trace.c b/sys/arch/amd64/amd64/db_trace.c
> index 1e7fcf2208ad..fe5ff40fa50b 100644
> --- a/sys/arch/amd64/amd64/db_trace.c
> +++ b/sys/arch/amd64/amd64/db_trace.c
> @@ -292,6 +292,7 @@ stacktrace_save_utrace(struct stacktrace *st)
> {
> struct callframe f, *frame, *lastframe;
> struct pcb *pcb = curpcb;
> + caddr_t onfault;
>
> st->st_count = 0;
>
> @@ -302,7 +303,11 @@ stacktrace_save_utrace(struct stacktrace *st)
> KASSERT(INKERNEL(frame));
> f = *frame;
>
> + /* CAREFUL: Might be in interrupt context and/or in copy(9). */
> curcpu()->ci_inatomic++;
> + onfault = pcb->pcb_onfault;
> + pcb->pcb_onfault = NULL;
> +
> while (st->st_count < STACKTRACE_MAX) {
> if (f.f_retaddr != 0 && !INKERNEL(f.f_retaddr))
> st->st_pc[st->st_count++] = f.f_retaddr;
> @@ -323,6 +328,8 @@ stacktrace_save_utrace(struct stacktrace *st)
> if (copyin(frame, &f, sizeof(f)) != 0)
> break;
> }
> +
> + pcb->pcb_onfault = onfault;
> curcpu()->ci_inatomic--;
> }
>
> diff --git a/sys/arch/i386/i386/db_trace.c b/sys/arch/i386/i386/db_trace.c
> index 2e1c9faefca7..4e413dc19245 100644
> --- a/sys/arch/i386/i386/db_trace.c
> +++ b/sys/arch/i386/i386/db_trace.c
> @@ -291,6 +291,7 @@ stacktrace_save_utrace(struct stacktrace *st)
> {
> struct callframe f, *frame, *lastframe;
> struct pcb *pcb = curpcb;
> + caddr_t onfault;
>
> st->st_count = 0;
>
> @@ -301,7 +302,11 @@ stacktrace_save_utrace(struct stacktrace *st)
> KASSERT(INKERNEL(frame));
> f = *frame;
>
> + /* CAREFUL: Might be in interrupt context and/or in copy(9). */
> curcpu()->ci_inatomic++;
> + onfault = pcb->pcb_onfault;
> + pcb->pcb_onfault = NULL;
> +
> while (st->st_count < STACKTRACE_MAX) {
> if (f.f_retaddr != 0 && !INKERNEL(f.f_retaddr))
> st->st_pc[st->st_count++] = f.f_retaddr;
> @@ -322,6 +327,8 @@ stacktrace_save_utrace(struct stacktrace *st)
> if (copyin(frame, &f, sizeof(f)) != 0)
> break;
> }
> +
> + pcb->pcb_onfault = onfault;
> curcpu()->ci_inatomic--;
> }
>
> --
> 2.34.1
Maintain preempted copy(9) state in stacktrace_save_utrace()
Maintain preempted copy(9) state in stacktrace_save_utrace()
Maintain preempted copy(9) state in stacktrace_save_utrace()