linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: x86@kernel.org, Peter Zijlstra <peterz@infradead.org>,
	 Steven Rostedt <rostedt@goodmis.org>,
	Ingo Molnar <mingo@kernel.org>,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	linux-kernel@vger.kernel.org,
	 Indu Bhagat <indu.bhagat@oracle.com>,
	Mark Rutland <mark.rutland@arm.com>,
	 Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>,  Namhyung Kim <namhyung@kernel.org>,
	Ian Rogers <irogers@google.com>,
	 Adrian Hunter <adrian.hunter@intel.com>,
	linux-perf-users@vger.kernel.org,
	 Mark Brown <broonie@kernel.org>,
	linux-toolchains@vger.kernel.org,
	 Jordan Rome <jordalgo@meta.com>, Sam James <sam@gentoo.org>,
	linux-trace-kernel@vger.kernel.org,
	 Jens Remus <jremus@linux.ibm.com>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
	 Florian Weimer <fweimer@redhat.com>,
	Andy Lutomirski <luto@kernel.org>,
	 Masami Hiramatsu <mhiramat@kernel.org>,
	Weinan Liu <wnliu@google.com>
Subject: Re: [PATCH v4 19/39] unwind_user/sframe: Add support for reading .sframe contents
Date: Mon, 27 Jan 2025 16:39:04 -0800	[thread overview]
Message-ID: <CAEf4BzYqDk5pGbmCz3XX1a-RXRKSLw9QwD+wUEABinVG+HZ1qQ@mail.gmail.com> (raw)
In-Reply-To: <20250124214107.ycccp4gapbdudzux@jpoimboe>

On Fri, Jan 24, 2025 at 1:41 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> On Fri, Jan 24, 2025 at 10:02:46AM -0800, Andrii Nakryiko wrote:
> > On Tue, Jan 21, 2025 at 6:32 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
> > > +static __always_inline int __read_fde(struct sframe_section *sec,
> > > +                                     unsigned int fde_num,
> > > +                                     struct sframe_fde *fde)
> > > +{
> > > +       unsigned long fde_addr, ip;
> > > +
> > > +       fde_addr = sec->fdes_start + (fde_num * sizeof(struct sframe_fde));
> > > +       unsafe_copy_from_user(fde, (void __user *)fde_addr,
> > > +                             sizeof(struct sframe_fde), Efault);
> > > +
> > > +       ip = sec->sframe_start + fde->start_addr;
> > > +       if (ip < sec->text_start || ip > sec->text_end)
> >
> > ip >= sec->test_end ? ip == sec->test_end doesn't make sense, no?
>
> Believe it or not, this may have been intentional: 'text_end' can
> actually be a valid stack return address if the last instruction of the
> section is a call to a noreturn function.  The unwinder still needs to
> know the state of the stack at that point.
>

TIL...

> That said, there would be no reason to put an FDE at the end.  So yeah,
> it should be '>='.
>
> > > +static __always_inline int __read_fre(struct sframe_section *sec,
> > > +                                     struct sframe_fde *fde,
> > > +                                     unsigned long fre_addr,
> > > +                                     struct sframe_fre *fre)
> > > +{
> > > +       unsigned char fde_type = SFRAME_FUNC_FDE_TYPE(fde->info);
> > > +       unsigned char fre_type = SFRAME_FUNC_FRE_TYPE(fde->info);
> > > +       unsigned char offset_count, offset_size;
> > > +       s32 ip_off, cfa_off, ra_off, fp_off;
> > > +       unsigned long cur = fre_addr;
> > > +       unsigned char addr_size;
> > > +       u8 info;
> > > +
> > > +       addr_size = fre_type_to_size(fre_type);
> > > +       if (!addr_size)
> > > +               return -EFAULT;
> > > +
> > > +       if (fre_addr + addr_size + 1 > sec->fres_end)
> >
> > nit: isn't this the same as `fre_addr + addr_size >= sec->fres_end` ?
>
> Yes, but that would further obfuscate the fact that this is validating
> that the next two reads don't go past sec->fres_end:
>
>         UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault);
>         UNSAFE_GET_USER_INC(info, cur, 1, Efault);
>
> The explicit "1" is for that second read.
>
> I'll do something like SFRAME_FRE_INFO_SIZE instead of 1 to make that
> clearer.

yeah, I definitely didn't connect 1 with the size of fre info byte,
named #define makes sense, thanks!

>
> > > +               return -EFAULT;
> > > +
> > > +       UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault);
> > > +       if (fde_type == SFRAME_FDE_TYPE_PCINC && ip_off > fde->func_size)
> >
> > is ip_off == fde->func_size allowable?
>
> This was another one where I was probably thinking about the whole "last
> insn could be a call to noreturn" scenario.
>
> But even in that case, the frame would be unchanged after the call, so
> there shouldn't need to be an FRE there.
>
> In fact, for the unwinder to deal with that scenario, for a call frame
> (as opposed to an interrupted one), it should always subtract one from
> the return address before calling into sframe so that it points to the
> calling instruction.  </me makes note to go do that>
>
> So yeah, this looks like another off-by-one, caused by overthinking yet
> not thinking enough.
>
> > > +               return -EFAULT;
> > > +
> > > +       UNSAFE_GET_USER_INC(info, cur, 1, Efault);
> > > +       offset_count = SFRAME_FRE_OFFSET_COUNT(info);
> > > +       offset_size  = offset_size_enum_to_size(SFRAME_FRE_OFFSET_SIZE(info));
> > > +       if (!offset_count || !offset_size)
> > > +               return -EFAULT;
> > > +
> > > +       if (cur + (offset_count * offset_size) > sec->fres_end)
> >
> > offset_count * offset_size done in u8 can overflow, no? maybe upcast
> > to unsigned long or use check_add_overflow?
>
> offset_size is <= 2 as returned by offset_size_enum_to_size().
>
> offset_count is expected to be <= 3, enforced by the !offset_count check
> at the bottom.
>
> An overflow here would be harmless as it would be caught by the
> !offset_count anyway.  Though I also notice offset_count isn't big
> enough to hold the 2-byte SFRAME_FRE_OFFSET_COUNT() value.  Which is
> harmless for the same reason, but yeah I'll make offset_count an
> unsigned int.

yeah, the less whoever is reading has to worry about overflows, the
better, thanks!

>
> > > +static __always_inline int __find_fre(struct sframe_section *sec,
> > > +                                     struct sframe_fde *fde, unsigned long ip,
> > > +                                     struct unwind_user_frame *frame)
> > > +{
> > > +       unsigned char fde_type = SFRAME_FUNC_FDE_TYPE(fde->info);
> > > +       struct sframe_fre *fre, *prev_fre = NULL;
> > > +       struct sframe_fre fres[2];
> >
> > you only need prev_fre->ip_off, so why all this `which` and `fres[2]`
> > business if all you need is prev_fre_off and a bool whether you have
> > prev_fre at all?
>
> So this cleverness probably needs a comment.  prev_fre is actually
> needed after the loop:
>
> > > +       if (!prev_fre)
> > > +               return -EINVAL;
> > > +       fre = prev_fre;
>
> In the body of the loop, prev_fre is a tentative match, unless the next
> fre also matches, in which case that one becomes the new tentative
> match.
>
> I'll add a comment.  Also it'll probably be less confusing if I rename
> "prev_fre" to "fre", and "fre" to "next_fre".

ah, yeah, I missed that, you are right

>
> > > +       unsigned long fre_addr;
> > > +       bool which = false;
> > > +       unsigned int i;
> > > +       s32 ip_off;
> > > +
> > > +       ip_off = (s32)(ip - sec->sframe_start) - fde->start_addr;
> > > +
> > > +       if (fde_type == SFRAME_FDE_TYPE_PCMASK)
> > > +               ip_off %= fde->rep_size;
> >
> > did you check that fde->rep_size is not zero?
>
> I did not, good catch!
>
> > > +       fre_addr = sec->fres_start + fde->fres_off;
> > > +
> > > +       for (i = 0; i < fde->fres_num; i++) {
> >
> > why not binary search? seem more logical to guard against cases with
> > lots of FREs and be pretty fast in common case anyways.
>
> That would be nice, but the FREs are variable-sized and you don't know
> how big one is until you start reading it.

ah, another non-obvious thing, yeah... do you think it's worth fixing
this and making FREs binary searchable in v3?

Indu, do you have some stats on distribution of FRE count per FDE in practice?

Tbh, FRE format is bothering me quite a lot... but let's discuss that
in another thread with you and Indu

>
> --
> Josh

  reply	other threads:[~2025-01-28  0:39 UTC|newest]

Thread overview: 161+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-22  2:30 [PATCH v4 00/39] unwind, perf: sframe user space unwinding Josh Poimboeuf
2025-01-22  2:30 ` [PATCH v4 01/39] task_work: Fix TWA_NMI_CURRENT error handling Josh Poimboeuf
2025-01-22 12:28   ` Peter Zijlstra
2025-01-22 20:47     ` Josh Poimboeuf
2025-01-23  8:14       ` Peter Zijlstra
2025-01-23 17:15         ` Josh Poimboeuf
2025-01-23 22:19           ` Peter Zijlstra
2025-04-22 16:14     ` Steven Rostedt
2025-01-22  2:30 ` [PATCH v4 02/39] task_work: Fix TWA_NMI_CURRENT race with __schedule() Josh Poimboeuf
2025-01-22 12:23   ` Peter Zijlstra
2025-01-22 12:42   ` Peter Zijlstra
2025-01-22 21:03     ` Josh Poimboeuf
2025-01-22 22:14       ` Josh Poimboeuf
2025-01-23  8:15         ` Peter Zijlstra
2025-04-22 16:15     ` Steven Rostedt
2025-04-22 17:20       ` Josh Poimboeuf
2025-01-22  2:30 ` [PATCH v4 03/39] mm: Add guard for mmap_read_lock Josh Poimboeuf
2025-01-22  2:30 ` [PATCH v4 04/39] x86/vdso: Fix DWARF generation for getrandom() Josh Poimboeuf
2025-01-22  2:30 ` [PATCH v4 05/39] x86/asm: Avoid emitting DWARF CFI for non-VDSO Josh Poimboeuf
2025-01-24 16:08   ` Jens Remus
2025-01-24 16:47     ` Josh Poimboeuf
2025-01-22  2:30 ` [PATCH v4 06/39] x86/asm: Fix VDSO DWARF generation with kernel IBT enabled Josh Poimboeuf
2025-01-22  2:30 ` [PATCH v4 07/39] x86/vdso: Use SYM_FUNC_{START,END} in __kernel_vsyscall() Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 08/39] x86/vdso: Use CFI macros in __vdso_sgx_enter_enclave() Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 09/39] x86/vdso: Enable sframe generation in VDSO Josh Poimboeuf
2025-01-24 16:00   ` Jens Remus
2025-01-24 16:43     ` Josh Poimboeuf
2025-01-24 16:53       ` Josh Poimboeuf
2025-04-22 17:44       ` Steven Rostedt
2025-01-24 16:30   ` Jens Remus
2025-01-24 16:56     ` Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 10/39] x86/uaccess: Add unsafe_copy_from_user() implementation Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 11/39] unwind_user: Add user space unwinding API Josh Poimboeuf
2025-01-24 16:41   ` Jens Remus
2025-01-24 17:09     ` Josh Poimboeuf
2025-01-24 17:59   ` Andrii Nakryiko
2025-01-24 18:08     ` Josh Poimboeuf
2025-01-24 20:02   ` Steven Rostedt
2025-01-24 22:05     ` Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 12/39] unwind_user: Add frame pointer support Josh Poimboeuf
2025-01-24 17:59   ` Andrii Nakryiko
2025-01-24 18:16     ` Josh Poimboeuf
2025-04-24 13:41       ` Steven Rostedt
2025-01-22  2:31 ` [PATCH v4 13/39] unwind_user/x86: Enable frame pointer unwinding on x86 Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 14/39] perf/x86: Rename get_segment_base() and make it global Josh Poimboeuf
2025-01-22 12:51   ` Peter Zijlstra
2025-01-22 21:37     ` Josh Poimboeuf
2025-01-24 20:09   ` Steven Rostedt
2025-01-24 22:06     ` Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 15/39] unwind_user: Add compat mode frame pointer support Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 16/39] unwind_user/x86: Enable compat mode frame pointer unwinding on x86 Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 17/39] unwind_user/sframe: Add support for reading .sframe headers Josh Poimboeuf
2025-01-24 18:00   ` Andrii Nakryiko
2025-01-24 19:21     ` Josh Poimboeuf
2025-01-24 20:13       ` Steven Rostedt
2025-01-24 22:39         ` Josh Poimboeuf
2025-01-24 22:13       ` Indu Bhagat
2025-01-28  1:10         ` Andrii Nakryiko
2025-01-29  2:02           ` Josh Poimboeuf
2025-01-30  0:02             ` Andrii Nakryiko
2025-02-04 18:26               ` Josh Poimboeuf
2025-01-30 21:39             ` Indu Bhagat
2025-02-05  0:57               ` Josh Poimboeuf
2025-02-06  1:10                 ` Indu Bhagat
2025-02-05 13:56             ` Jens Remus
2025-02-07 21:13               ` Josh Poimboeuf
2025-01-30 21:21           ` Indu Bhagat
2025-02-04 19:59             ` Josh Poimboeuf
2025-02-05 23:16             ` Andrii Nakryiko
2025-02-05 11:01           ` Jens Remus
2025-02-05 23:05             ` Andrii Nakryiko
2025-01-24 20:31     ` Indu Bhagat
2025-01-22  2:31 ` [PATCH v4 18/39] unwind_user/sframe: Store sframe section data in per-mm maple tree Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 19/39] unwind_user/sframe: Add support for reading .sframe contents Josh Poimboeuf
2025-01-24 16:36   ` Jens Remus
2025-01-24 17:07     ` Josh Poimboeuf
2025-01-24 18:02   ` Andrii Nakryiko
2025-01-24 21:41     ` Josh Poimboeuf
2025-01-28  0:39       ` Andrii Nakryiko [this message]
2025-01-28 10:50         ` Jens Remus
2025-01-29  2:04           ` Josh Poimboeuf
2025-01-28 10:54         ` Jens Remus
2025-01-30 19:51       ` Weinan Liu
2025-02-04 19:42         ` Josh Poimboeuf
2025-01-30 15:07   ` Indu Bhagat
2025-02-04 18:38     ` Josh Poimboeuf
2025-01-30 15:47   ` Jens Remus
2025-02-04 18:51     ` Josh Poimboeuf
2025-02-05  9:47       ` Jens Remus
2025-02-07 21:06         ` Josh Poimboeuf
2025-02-10 15:56           ` Jens Remus
2025-01-22  2:31 ` [PATCH v4 20/39] unwind_user/sframe: Detect .sframe sections in executables Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 21/39] unwind_user/sframe: Add prctl() interface for registering .sframe sections Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 22/39] unwind_user/sframe: Wire up unwind_user to sframe Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 23/39] unwind_user/sframe/x86: Enable sframe unwinding on x86 Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 24/39] unwind_user/sframe: Remove .sframe section on detected corruption Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 25/39] unwind_user/sframe: Show file name in debug output Josh Poimboeuf
2025-01-30 16:17   ` Jens Remus
2025-02-04 19:10     ` Josh Poimboeuf
2025-02-05 10:04       ` Jens Remus
2025-01-22  2:31 ` [PATCH v4 26/39] unwind_user/sframe: Enable debugging in uaccess regions Josh Poimboeuf
2025-01-30 16:38   ` Jens Remus
2025-02-04 19:33     ` Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 27/39] unwind_user/sframe: Add .sframe validation option Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 28/39] unwind_user/deferred: Add deferred unwinding interface Josh Poimboeuf
2025-01-22 13:37   ` Peter Zijlstra
2025-01-22 14:16     ` Peter Zijlstra
2025-01-22 22:51       ` Josh Poimboeuf
2025-01-23  8:17         ` Peter Zijlstra
2025-01-23 18:30           ` Josh Poimboeuf
2025-01-23 21:58             ` Peter Zijlstra
2025-01-22 21:38     ` Josh Poimboeuf
2025-01-22 13:44   ` Peter Zijlstra
2025-01-22 21:52     ` Josh Poimboeuf
2025-01-22 20:13   ` Mathieu Desnoyers
2025-01-23  4:05     ` Josh Poimboeuf
2025-01-23  8:25       ` Peter Zijlstra
2025-01-23 18:43         ` Josh Poimboeuf
2025-01-23 22:13           ` Peter Zijlstra
2025-01-24 21:58             ` Steven Rostedt
2025-01-24 22:46               ` Josh Poimboeuf
2025-01-24 22:50                 ` Josh Poimboeuf
2025-01-24 23:57                   ` Steven Rostedt
2025-01-30 20:21                     ` Steven Rostedt
2025-02-05  2:25                       ` Josh Poimboeuf
2025-01-24 16:35   ` Jens Remus
2025-01-24 16:57     ` Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 29/39] unwind_user/deferred: Add unwind cache Josh Poimboeuf
2025-01-22 13:57   ` Peter Zijlstra
2025-01-22 22:36     ` Josh Poimboeuf
2025-01-23  8:31       ` Peter Zijlstra
2025-01-23 18:45         ` Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 30/39] unwind_user/deferred: Make unwind deferral requests NMI-safe Josh Poimboeuf
2025-01-22 14:15   ` Peter Zijlstra
2025-01-22 22:49     ` Josh Poimboeuf
2025-01-23  8:40       ` Peter Zijlstra
2025-01-23 19:48         ` Josh Poimboeuf
2025-01-23 19:54           ` Josh Poimboeuf
2025-01-23 22:17           ` Peter Zijlstra
2025-01-23 23:34             ` Josh Poimboeuf
2025-01-24 11:58               ` Peter Zijlstra
2025-01-22 14:24   ` Peter Zijlstra
2025-01-22 22:52     ` Josh Poimboeuf
2025-01-23  8:42       ` Peter Zijlstra
2025-01-22  2:31 ` [PATCH v4 31/39] perf: Remove get_perf_callchain() 'init_nr' argument Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 32/39] perf: Remove get_perf_callchain() 'crosstask' argument Josh Poimboeuf
2025-01-24 18:13   ` Andrii Nakryiko
2025-01-24 22:00     ` Josh Poimboeuf
2025-01-28  0:39       ` Andrii Nakryiko
2025-01-22  2:31 ` [PATCH v4 33/39] perf: Simplify get_perf_callchain() user logic Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 34/39] perf: Skip user unwind if !current->mm Josh Poimboeuf
2025-01-22 14:29   ` Peter Zijlstra
2025-01-22 23:08     ` Josh Poimboeuf
2025-01-23  8:44       ` Peter Zijlstra
2025-01-22  2:31 ` [PATCH v4 35/39] perf: Support deferred user callchains Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 36/39] perf tools: Minimal CALLCHAIN_DEFERRED support Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 37/39] perf record: Enable defer_callchain for user callchains Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 38/39] perf script: Display PERF_RECORD_CALLCHAIN_DEFERRED Josh Poimboeuf
2025-01-22  2:31 ` [PATCH v4 39/39] perf tools: Merge deferred user callchains Josh Poimboeuf
2025-01-22  2:35 ` [PATCH v4 00/39] unwind, perf: sframe user space unwinding Josh Poimboeuf
2025-01-22 16:13 ` Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAEf4BzYqDk5pGbmCz3XX1a-RXRKSLw9QwD+wUEABinVG+HZ1qQ@mail.gmail.com \
    --to=andrii.nakryiko@gmail.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=broonie@kernel.org \
    --cc=fweimer@redhat.com \
    --cc=indu.bhagat@oracle.com \
    --cc=irogers@google.com \
    --cc=jolsa@kernel.org \
    --cc=jordalgo@meta.com \
    --cc=jpoimboe@kernel.org \
    --cc=jremus@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux-toolchains@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=sam@gentoo.org \
    --cc=wnliu@google.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).