diff mbox series

[v2,1/5] elf: Define note name macros

Message ID 20250104-elf-v2-1-77dc2e06db4e@daynix.com (mailing list archive)
State New
Headers show
Series elf: Define note name macros | expand

Commit Message

Akihiko Odaki Jan. 4, 2025, 2:38 p.m. UTC
elf.h had a comment saying:
> Notes used in ET_CORE. Architectures export some of the arch register
> sets using the corresponding note types via the PTRACE_GETREGSET and
> PTRACE_SETREGSET requests.
> The note name for these types is "LINUX", except NT_PRFPREG that is
> named "CORE".

However, NT_PRSTATUS is also named "CORE". It is also unclear what
"these types" refers to.

To fix these problems, define a name for each note type. The added
definitions are macros so the kernel and userspace can directly refer to
them.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 include/uapi/linux/elf.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 83 insertions(+), 3 deletions(-)

Comments

Baoquan He Jan. 6, 2025, 2:21 a.m. UTC | #1
On 01/04/25 at 11:38pm, Akihiko Odaki wrote:
> elf.h had a comment saying:
> > Notes used in ET_CORE. Architectures export some of the arch register
> > sets using the corresponding note types via the PTRACE_GETREGSET and
> > PTRACE_SETREGSET requests.
> > The note name for these types is "LINUX", except NT_PRFPREG that is
> > named "CORE".
> 
> However, NT_PRSTATUS is also named "CORE". It is also unclear what
> "these types" refers to.
> 
> To fix these problems, define a name for each note type. The added
> definitions are macros so the kernel and userspace can directly refer to
> them.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/uapi/linux/elf.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 83 insertions(+), 3 deletions(-)
> 
> diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
> index b44069d29cec..014b705b97d7 100644
> --- a/include/uapi/linux/elf.h
> +++ b/include/uapi/linux/elf.h
> @@ -372,8 +372,6 @@ typedef struct elf64_shdr {
>   * Notes used in ET_CORE. Architectures export some of the arch register sets
>   * using the corresponding note types via the PTRACE_GETREGSET and
>   * PTRACE_SETREGSET requests.
> - * The note name for these types is "LINUX", except NT_PRFPREG that is named
> - * "CORE".
>   */
>  #define NT_PRSTATUS	1
>  #define NT_PRFPREG	2
> @@ -460,9 +458,91 @@ typedef struct elf64_shdr {
>  #define NT_LOONGARCH_HW_BREAK	0xa05   /* LoongArch hardware breakpoint registers */
>  #define NT_LOONGARCH_HW_WATCH	0xa06   /* LoongArch hardware watchpoint registers */
>  
> -/* Note types with note name "GNU" */
> +/* Note used in ET_EXEC and ET_DYN. */
>  #define NT_GNU_PROPERTY_TYPE_0	5
>  
> +/* Note names */
> +#define NN_PRSTATUS	"CORE"
> +#define NN_PRFPREG	"CORE"
> +#define NN_PRPSINFO	"CORE"
> +#define NN_TASKSTRUCT	"CORE"
> +#define NN_AUXV	"CORE"
> +#define NN_SIGINFO	"CORE"
> +#define NN_FILE	"CORE"
> +#define NN_PRXFPREG	"LINUX"

No objection to make them clearer. Thanks for the effort.

Wondering where below arch specific macros are used. So you just
added all NN_xxx for the corresponding NT_xxx? Not sure if this is
needed if we don't use them at all in the current kernel.

> +#define NN_PPC_VMX	"LINUX"
> +#define NN_PPC_SPE	"LINUX"
> +#define NN_PPC_VSX	"LINUX"
> +#define NN_PPC_TAR	"LINUX"
> +#define NN_PPC_PPR	"LINUX"
> +#define NN_PPC_DSCR	"LINUX"
> +#define NN_PPC_EBB	"LINUX"
> +#define NN_PPC_PMU	"LINUX"
> +#define NN_PPC_TM_CGPR	"LINUX"
> +#define NN_PPC_TM_CFPR	"LINUX"
> +#define NN_PPC_TM_CVMX	"LINUX"
> +#define NN_PPC_TM_CVSX	"LINUX"
> +#define NN_PPC_TM_SPR	"LINUX"
> +#define NN_PPC_TM_CTAR	"LINUX"
> +#define NN_PPC_TM_CPPR	"LINUX"
> +#define NN_PPC_TM_CDSCR	"LINUX"
> +#define NN_PPC_PKEY	"LINUX"
> +#define NN_PPC_DEXCR	"LINUX"
> +#define NN_PPC_HASHKEYR	"LINUX"
> +#define NN_386_TLS	"LINUX"
> +#define NN_386_IOPERM	"LINUX"
> +#define NN_X86_XSTATE	"LINUX"
> +#define NN_X86_SHSTK	"LINUX"
> +#define NN_X86_XSAVE_LAYOUT	"LINUX"
> +#define NN_S390_HIGH_GPRS	"LINUX"
> +#define NN_S390_TIMER	"LINUX"
> +#define NN_S390_TODCMP	"LINUX"
> +#define NN_S390_TODPREG	"LINUX"
> +#define NN_S390_CTRS	"LINUX"
> +#define NN_S390_PREFIX	"LINUX"
> +#define NN_S390_LAST_BREAK	"LINUX"
> +#define NN_S390_SYSTEM_CALL	"LINUX"
> +#define NN_S390_TDB	"LINUX"
> +#define NN_S390_VXRS_LOW	"LINUX"
> +#define NN_S390_VXRS_HIGH	"LINUX"
> +#define NN_S390_GS_CB	"LINUX"
> +#define NN_S390_GS_BC	"LINUX"
> +#define NN_S390_RI_CB	"LINUX"
> +#define NN_S390_PV_CPU_DATA	"LINUX"
> +#define NN_ARM_VFP	"LINUX"
> +#define NN_ARM_TLS	"LINUX"
> +#define NN_ARM_HW_BREAK	"LINUX"
> +#define NN_ARM_HW_WATCH	"LINUX"
> +#define NN_ARM_SYSTEM_CALL	"LINUX"
> +#define NN_ARM_SVE	"LINUX"
> +#define NN_ARM_PAC_MASK	"LINUX"
> +#define NN_ARM_PACA_KEYS	"LINUX"
> +#define NN_ARM_PACG_KEYS	"LINUX"
> +#define NN_ARM_TAGGED_ADDR_CTRL	"LINUX"
> +#define NN_ARM_PAC_ENABLED_KEYS	"LINUX"
> +#define NN_ARM_SSVE	"LINUX"
> +#define NN_ARM_ZA	"LINUX"
> +#define NN_ARM_ZT	"LINUX"
> +#define NN_ARM_FPMR	"LINUX"
> +#define NN_ARM_POE	"LINUX"
> +#define NN_ARM_GCS	"LINUX"
> +#define NN_ARC_V2	"LINUX"
> +#define NN_VMCOREDD	"LINUX"
> +#define NN_MIPS_DSP	"LINUX"
> +#define NN_MIPS_FP_MODE	"LINUX"
> +#define NN_MIPS_MSA	"LINUX"
> +#define NN_RISCV_CSR	"LINUX"
> +#define NN_RISCV_VECTOR	"LINUX"
> +#define NN_RISCV_TAGGED_ADDR_CTRL	"LINUX"
> +#define NN_LOONGARCH_CPUCFG	"LINUX"
> +#define NN_LOONGARCH_CSR	"LINUX"
> +#define NN_LOONGARCH_LSX	"LINUX"
> +#define NN_LOONGARCH_LASX	"LINUX"
> +#define NN_LOONGARCH_LBT	"LINUX"
> +#define NN_LOONGARCH_HW_BREAK	"LINUX"
> +#define NN_LOONGARCH_HW_WATCH	"LINUX"
> +#define NN_GNU_PROPERTY_TYPE_0	"GNU"
> +
>  /* Note header in a PT_NOTE section */
>  typedef struct elf32_note {
>    Elf32_Word	n_namesz;	/* Name size */
> 
> -- 
> 2.47.1
>
Akihiko Odaki Jan. 6, 2025, 5:07 a.m. UTC | #2
On 2025/01/06 11:21, Baoquan He wrote:
> On 01/04/25 at 11:38pm, Akihiko Odaki wrote:
>> elf.h had a comment saying:
>>> Notes used in ET_CORE. Architectures export some of the arch register
>>> sets using the corresponding note types via the PTRACE_GETREGSET and
>>> PTRACE_SETREGSET requests.
>>> The note name for these types is "LINUX", except NT_PRFPREG that is
>>> named "CORE".
>>
>> However, NT_PRSTATUS is also named "CORE". It is also unclear what
>> "these types" refers to.
>>
>> To fix these problems, define a name for each note type. The added
>> definitions are macros so the kernel and userspace can directly refer to
>> them.
>>
>> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
>> ---
>>   include/uapi/linux/elf.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 83 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
>> index b44069d29cec..014b705b97d7 100644
>> --- a/include/uapi/linux/elf.h
>> +++ b/include/uapi/linux/elf.h
>> @@ -372,8 +372,6 @@ typedef struct elf64_shdr {
>>    * Notes used in ET_CORE. Architectures export some of the arch register sets
>>    * using the corresponding note types via the PTRACE_GETREGSET and
>>    * PTRACE_SETREGSET requests.
>> - * The note name for these types is "LINUX", except NT_PRFPREG that is named
>> - * "CORE".
>>    */
>>   #define NT_PRSTATUS	1
>>   #define NT_PRFPREG	2
>> @@ -460,9 +458,91 @@ typedef struct elf64_shdr {
>>   #define NT_LOONGARCH_HW_BREAK	0xa05   /* LoongArch hardware breakpoint registers */
>>   #define NT_LOONGARCH_HW_WATCH	0xa06   /* LoongArch hardware watchpoint registers */
>>   
>> -/* Note types with note name "GNU" */
>> +/* Note used in ET_EXEC and ET_DYN. */
>>   #define NT_GNU_PROPERTY_TYPE_0	5
>>   
>> +/* Note names */
>> +#define NN_PRSTATUS	"CORE"
>> +#define NN_PRFPREG	"CORE"
>> +#define NN_PRPSINFO	"CORE"
>> +#define NN_TASKSTRUCT	"CORE"
>> +#define NN_AUXV	"CORE"
>> +#define NN_SIGINFO	"CORE"
>> +#define NN_FILE	"CORE"
>> +#define NN_PRXFPREG	"LINUX"
> 
> No objection to make them clearer. Thanks for the effort.
> 
> Wondering where below arch specific macros are used. So you just
> added all NN_xxx for the corresponding NT_xxx? Not sure if this is
> needed if we don't use them at all in the current kernel.

Indeed I just added all NN_xxx. The kernel won't use the macros that are 
defined as "LINUX"; fs/binfmt_elf.c uses "LINUX" by default as the notes 
named "CORE" or "GNU" are exceptional.

Userspace applications may still be interested in these macros as 
demonstrated in:
https://lore.kernel.org/r/Z3f7zJwu8bu8HYln@e133380.arm.com

These macros also serve as documentation; correcting and clarifying the 
documentation is the main purpose of this series.

> 
>> +#define NN_PPC_VMX	"LINUX"
>> +#define NN_PPC_SPE	"LINUX"
>> +#define NN_PPC_VSX	"LINUX"
>> +#define NN_PPC_TAR	"LINUX"
>> +#define NN_PPC_PPR	"LINUX"
>> +#define NN_PPC_DSCR	"LINUX"
>> +#define NN_PPC_EBB	"LINUX"
>> +#define NN_PPC_PMU	"LINUX"
>> +#define NN_PPC_TM_CGPR	"LINUX"
>> +#define NN_PPC_TM_CFPR	"LINUX"
>> +#define NN_PPC_TM_CVMX	"LINUX"
>> +#define NN_PPC_TM_CVSX	"LINUX"
>> +#define NN_PPC_TM_SPR	"LINUX"
>> +#define NN_PPC_TM_CTAR	"LINUX"
>> +#define NN_PPC_TM_CPPR	"LINUX"
>> +#define NN_PPC_TM_CDSCR	"LINUX"
>> +#define NN_PPC_PKEY	"LINUX"
>> +#define NN_PPC_DEXCR	"LINUX"
>> +#define NN_PPC_HASHKEYR	"LINUX"
>> +#define NN_386_TLS	"LINUX"
>> +#define NN_386_IOPERM	"LINUX"
>> +#define NN_X86_XSTATE	"LINUX"
>> +#define NN_X86_SHSTK	"LINUX"
>> +#define NN_X86_XSAVE_LAYOUT	"LINUX"
>> +#define NN_S390_HIGH_GPRS	"LINUX"
>> +#define NN_S390_TIMER	"LINUX"
>> +#define NN_S390_TODCMP	"LINUX"
>> +#define NN_S390_TODPREG	"LINUX"
>> +#define NN_S390_CTRS	"LINUX"
>> +#define NN_S390_PREFIX	"LINUX"
>> +#define NN_S390_LAST_BREAK	"LINUX"
>> +#define NN_S390_SYSTEM_CALL	"LINUX"
>> +#define NN_S390_TDB	"LINUX"
>> +#define NN_S390_VXRS_LOW	"LINUX"
>> +#define NN_S390_VXRS_HIGH	"LINUX"
>> +#define NN_S390_GS_CB	"LINUX"
>> +#define NN_S390_GS_BC	"LINUX"
>> +#define NN_S390_RI_CB	"LINUX"
>> +#define NN_S390_PV_CPU_DATA	"LINUX"
>> +#define NN_ARM_VFP	"LINUX"
>> +#define NN_ARM_TLS	"LINUX"
>> +#define NN_ARM_HW_BREAK	"LINUX"
>> +#define NN_ARM_HW_WATCH	"LINUX"
>> +#define NN_ARM_SYSTEM_CALL	"LINUX"
>> +#define NN_ARM_SVE	"LINUX"
>> +#define NN_ARM_PAC_MASK	"LINUX"
>> +#define NN_ARM_PACA_KEYS	"LINUX"
>> +#define NN_ARM_PACG_KEYS	"LINUX"
>> +#define NN_ARM_TAGGED_ADDR_CTRL	"LINUX"
>> +#define NN_ARM_PAC_ENABLED_KEYS	"LINUX"
>> +#define NN_ARM_SSVE	"LINUX"
>> +#define NN_ARM_ZA	"LINUX"
>> +#define NN_ARM_ZT	"LINUX"
>> +#define NN_ARM_FPMR	"LINUX"
>> +#define NN_ARM_POE	"LINUX"
>> +#define NN_ARM_GCS	"LINUX"
>> +#define NN_ARC_V2	"LINUX"
>> +#define NN_VMCOREDD	"LINUX"
>> +#define NN_MIPS_DSP	"LINUX"
>> +#define NN_MIPS_FP_MODE	"LINUX"
>> +#define NN_MIPS_MSA	"LINUX"
>> +#define NN_RISCV_CSR	"LINUX"
>> +#define NN_RISCV_VECTOR	"LINUX"
>> +#define NN_RISCV_TAGGED_ADDR_CTRL	"LINUX"
>> +#define NN_LOONGARCH_CPUCFG	"LINUX"
>> +#define NN_LOONGARCH_CSR	"LINUX"
>> +#define NN_LOONGARCH_LSX	"LINUX"
>> +#define NN_LOONGARCH_LASX	"LINUX"
>> +#define NN_LOONGARCH_LBT	"LINUX"
>> +#define NN_LOONGARCH_HW_BREAK	"LINUX"
>> +#define NN_LOONGARCH_HW_WATCH	"LINUX"
>> +#define NN_GNU_PROPERTY_TYPE_0	"GNU"
>> +
>>   /* Note header in a PT_NOTE section */
>>   typedef struct elf32_note {
>>     Elf32_Word	n_namesz;	/* Name size */
>>
>> -- 
>> 2.47.1
>>
>
Baoquan He Jan. 6, 2025, 6:06 a.m. UTC | #3
On 01/06/25 at 02:07pm, Akihiko Odaki wrote:
> On 2025/01/06 11:21, Baoquan He wrote:
> > On 01/04/25 at 11:38pm, Akihiko Odaki wrote:
> > > elf.h had a comment saying:
> > > > Notes used in ET_CORE. Architectures export some of the arch register
> > > > sets using the corresponding note types via the PTRACE_GETREGSET and
> > > > PTRACE_SETREGSET requests.
> > > > The note name for these types is "LINUX", except NT_PRFPREG that is
> > > > named "CORE".
> > > 
> > > However, NT_PRSTATUS is also named "CORE". It is also unclear what
> > > "these types" refers to.
> > > 
> > > To fix these problems, define a name for each note type. The added
> > > definitions are macros so the kernel and userspace can directly refer to
> > > them.
> > > 
> > > Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> > > ---
> > >   include/uapi/linux/elf.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++--
> > >   1 file changed, 83 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
> > > index b44069d29cec..014b705b97d7 100644
> > > --- a/include/uapi/linux/elf.h
> > > +++ b/include/uapi/linux/elf.h
> > > @@ -372,8 +372,6 @@ typedef struct elf64_shdr {
> > >    * Notes used in ET_CORE. Architectures export some of the arch register sets
> > >    * using the corresponding note types via the PTRACE_GETREGSET and
> > >    * PTRACE_SETREGSET requests.
> > > - * The note name for these types is "LINUX", except NT_PRFPREG that is named
> > > - * "CORE".
> > >    */
> > >   #define NT_PRSTATUS	1
> > >   #define NT_PRFPREG	2
> > > @@ -460,9 +458,91 @@ typedef struct elf64_shdr {
> > >   #define NT_LOONGARCH_HW_BREAK	0xa05   /* LoongArch hardware breakpoint registers */
> > >   #define NT_LOONGARCH_HW_WATCH	0xa06   /* LoongArch hardware watchpoint registers */
> > > -/* Note types with note name "GNU" */
> > > +/* Note used in ET_EXEC and ET_DYN. */
> > >   #define NT_GNU_PROPERTY_TYPE_0	5
> > > +/* Note names */
> > > +#define NN_PRSTATUS	"CORE"
> > > +#define NN_PRFPREG	"CORE"
> > > +#define NN_PRPSINFO	"CORE"
> > > +#define NN_TASKSTRUCT	"CORE"
> > > +#define NN_AUXV	"CORE"
> > > +#define NN_SIGINFO	"CORE"
> > > +#define NN_FILE	"CORE"
> > > +#define NN_PRXFPREG	"LINUX"
> > 
> > No objection to make them clearer. Thanks for the effort.
> > 
> > Wondering where below arch specific macros are used. So you just
> > added all NN_xxx for the corresponding NT_xxx? Not sure if this is
> > needed if we don't use them at all in the current kernel.
> 
> Indeed I just added all NN_xxx. The kernel won't use the macros that are
> defined as "LINUX"; fs/binfmt_elf.c uses "LINUX" by default as the notes
> named "CORE" or "GNU" are exceptional.
> 
> Userspace applications may still be interested in these macros as
> demonstrated in:
> https://lore.kernel.org/r/Z3f7zJwu8bu8HYln@e133380.arm.com
> 
> These macros also serve as documentation; correcting and clarifying the
> documentation is the main purpose of this series.

I see, thanks. Then the overall series looks good to me.
Dave Martin Jan. 6, 2025, 2:39 p.m. UTC | #4
On Sat, Jan 04, 2025 at 11:38:34PM +0900, Akihiko Odaki wrote:
> elf.h had a comment saying:
> > Notes used in ET_CORE. Architectures export some of the arch register
> > sets using the corresponding note types via the PTRACE_GETREGSET and
> > PTRACE_SETREGSET requests.
> > The note name for these types is "LINUX", except NT_PRFPREG that is
> > named "CORE".
> 
> However, NT_PRSTATUS is also named "CORE". It is also unclear what
> "these types" refers to.
> 
> To fix these problems, define a name for each note type. The added
> definitions are macros so the kernel and userspace can directly refer to
> them.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
> ---
>  include/uapi/linux/elf.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 83 insertions(+), 3 deletions(-)
> 
> diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
> index b44069d29cec..014b705b97d7 100644
> --- a/include/uapi/linux/elf.h
> +++ b/include/uapi/linux/elf.h
> @@ -372,8 +372,6 @@ typedef struct elf64_shdr {
>   * Notes used in ET_CORE. Architectures export some of the arch register sets
>   * using the corresponding note types via the PTRACE_GETREGSET and
>   * PTRACE_SETREGSET requests.
> - * The note name for these types is "LINUX", except NT_PRFPREG that is named
> - * "CORE".

Maybe most people would find it obvious, but is it worth saying what
the NT_ and NN_ macros are for?  They can easily be explained in terms
of the elfXX_note struct fields.

>   */
>  #define NT_PRSTATUS	1
>  #define NT_PRFPREG	2
> @@ -460,9 +458,91 @@ typedef struct elf64_shdr {
>  #define NT_LOONGARCH_HW_BREAK	0xa05   /* LoongArch hardware breakpoint registers */
>  #define NT_LOONGARCH_HW_WATCH	0xa06   /* LoongArch hardware watchpoint registers */
>  
> -/* Note types with note name "GNU" */
> +/* Note used in ET_EXEC and ET_DYN. */

May just "other notes"?  I think that the comment might bitrot
over time.

>  #define NT_GNU_PROPERTY_TYPE_0	5
>  
> +/* Note names */
> +#define NN_PRSTATUS	"CORE"

Can these be interleaved with the NT_ definitions?  I think this would
make the resulting header (and the diff) easier to read.

> +#define NN_PRFPREG	"CORE"

[...]

> +#define NN_GNU_PROPERTY_TYPE_0	"GNU"

[...]

Cheers
---Dave
Kees Cook Jan. 6, 2025, 4:48 p.m. UTC | #5
On Sat, Jan 04, 2025 at 11:38:34PM +0900, Akihiko Odaki wrote:
> elf.h had a comment saying:
> > Notes used in ET_CORE. Architectures export some of the arch register
> > sets using the corresponding note types via the PTRACE_GETREGSET and
> > PTRACE_SETREGSET requests.
> > The note name for these types is "LINUX", except NT_PRFPREG that is
> > named "CORE".
> 
> However, NT_PRSTATUS is also named "CORE". It is also unclear what
> "these types" refers to.
> 
> To fix these problems, define a name for each note type. The added
> definitions are macros so the kernel and userspace can directly refer to
> them.

While ELF is specified in the Tool Interface Standard[1], the core dump
format doesn't have an official specification. It does follow a lot of
agreed rules, though, and the "note name" is intended to help coredump
consumers distinguish between "common" things ("CORE") and Linux-specific
things ("LINUX").

I think this should be explicitly spelled out in the UAPI header,
even if we have "mistakes" for this mapping.

I'm not convinced we need these macros, though: everything is "LINUX"
expect the common types. And the GNU types are "GNU". There are only 7
types under the "CORE" name. :)

For the macros, I'd much prefer NN_CORE, NN_LINUX, and NN_GNU.

If you really want to be able to examine the name from the type, then
yeah, I guess we need something like the macros you have, but I'd much
prefer also adding a macro like Dave suggested[2], and then replace the
fill_note() with a macro that can unwrap it:

	fill_note(note, NT_SIGINFO, size..., data...);

The repetition of NN_type, NT_type doesn't feel robust if we have a
programmatic mapping: only the "type" is needed to determine both, so
why supply both?

-Kees

[1] https://refspecs.linuxfoundation.org/elf/elf.pdf
[2] https://lore.kernel.org/lkml/Z3vuBTiQvnRvv9DQ@e133380.arm.com/
Dave Martin Jan. 6, 2025, 5:23 p.m. UTC | #6
Hi all,

On Mon, Jan 06, 2025 at 08:48:05AM -0800, Kees Cook wrote:
> On Sat, Jan 04, 2025 at 11:38:34PM +0900, Akihiko Odaki wrote:
> > elf.h had a comment saying:
> > > Notes used in ET_CORE. Architectures export some of the arch register
> > > sets using the corresponding note types via the PTRACE_GETREGSET and
> > > PTRACE_SETREGSET requests.
> > > The note name for these types is "LINUX", except NT_PRFPREG that is
> > > named "CORE".
> > 
> > However, NT_PRSTATUS is also named "CORE". It is also unclear what
> > "these types" refers to.
> > 
> > To fix these problems, define a name for each note type. The added
> > definitions are macros so the kernel and userspace can directly refer to
> > them.
> 
> While ELF is specified in the Tool Interface Standard[1], the core dump
> format doesn't have an official specification. It does follow a lot of
> agreed rules, though, and the "note name" is intended to help coredump
> consumers distinguish between "common" things ("CORE") and Linux-specific
> things ("LINUX").
> 
> I think this should be explicitly spelled out in the UAPI header,
> even if we have "mistakes" for this mapping.

This seems reasonable.

> I'm not convinced we need these macros, though: everything is "LINUX"
> expect the common types. And the GNU types are "GNU". There are only 7
> types under the "CORE" name. :)

My starting point for suggesting the new macros was that the current
usage seems to be a historical accident; there doesn't seem to be an
underlying logic to it, except that arch-independent core note types
defined by Linux are named "CORE" ... except when they aren't.

Although the number of exceptional cases is small today, this doesn't
make for a robust rule -- nothing really prevents more unintentional
anomalies being added in future, so it seems prone to bitrot.

If the names are arbitrary, having a table rather than trying to
describe a rule seems the best way to avoid confusion.

Documenting these in a regular way may also encourage people to treat
the name as a formal part of the identifier, rather than a sort of
"comment" that nobody is quite sure what to do with (even if [1] makes
it clear).

That said, software does cope with the situation today; it's just a bit
gross.

> 
> For the macros, I'd much prefer NN_CORE, NN_LINUX, and NN_GNU.

What would be the point of these?

#define NN_CORE "CORE" doesn't convey any information at all, though I
suppose it does provide a layer of typo-resistance.

> If you really want to be able to examine the name from the type, then
> yeah, I guess we need something like the macros you have, but I'd much
> prefer also adding a macro like Dave suggested[2], and then replace the
> fill_note() with a macro that can unwrap it:
> 
> 	fill_note(note, NT_SIGINFO, size..., data...);
> 
> The repetition of NN_type, NT_type doesn't feel robust if we have a
> programmatic mapping: only the "type" is needed to determine both, so
> why supply both?
> 
> -Kees
> 
> [1] https://refspecs.linuxfoundation.org/elf/elf.pdf
> [2] https://lore.kernel.org/lkml/Z3vuBTiQvnRvv9DQ@e133380.arm.com/

Although not "robust", it should at least be obvious to the eye of
anyone pasting and repurposing an existing snippet of code that the
"type" is probably supposed to match in a single call.

I suppose we could have a kernel helper function containing a big
switch that gives you the name for each recognised note type though.
At the source code level, that would avoid specifying the "NN_"
arguments explicitly.  But if we still want a canonical way to describe
this mapping in elf.h, the "NN_" macros still serve a purpose.


With a literal string instead, I would expect then when adapting

	fill_note(note, NT_SIGINFO, "CORE", ...)

to

	fill_note(note, NT_WIZZFOO, ???, ...)

it's not clear what ??? should be.  I think people have tended to shrug
and just leave it unchanged -- so, it depends on which bit of code was
randomly chosen to serve as a template.  I could be guessing wrongly
about that, but if that's how the name gets chosen for new notes then
it doesn't feel ideal.

Cheers
---Dave
diff mbox series

Patch

diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index b44069d29cec..014b705b97d7 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -372,8 +372,6 @@  typedef struct elf64_shdr {
  * Notes used in ET_CORE. Architectures export some of the arch register sets
  * using the corresponding note types via the PTRACE_GETREGSET and
  * PTRACE_SETREGSET requests.
- * The note name for these types is "LINUX", except NT_PRFPREG that is named
- * "CORE".
  */
 #define NT_PRSTATUS	1
 #define NT_PRFPREG	2
@@ -460,9 +458,91 @@  typedef struct elf64_shdr {
 #define NT_LOONGARCH_HW_BREAK	0xa05   /* LoongArch hardware breakpoint registers */
 #define NT_LOONGARCH_HW_WATCH	0xa06   /* LoongArch hardware watchpoint registers */
 
-/* Note types with note name "GNU" */
+/* Note used in ET_EXEC and ET_DYN. */
 #define NT_GNU_PROPERTY_TYPE_0	5
 
+/* Note names */
+#define NN_PRSTATUS	"CORE"
+#define NN_PRFPREG	"CORE"
+#define NN_PRPSINFO	"CORE"
+#define NN_TASKSTRUCT	"CORE"
+#define NN_AUXV	"CORE"
+#define NN_SIGINFO	"CORE"
+#define NN_FILE	"CORE"
+#define NN_PRXFPREG	"LINUX"
+#define NN_PPC_VMX	"LINUX"
+#define NN_PPC_SPE	"LINUX"
+#define NN_PPC_VSX	"LINUX"
+#define NN_PPC_TAR	"LINUX"
+#define NN_PPC_PPR	"LINUX"
+#define NN_PPC_DSCR	"LINUX"
+#define NN_PPC_EBB	"LINUX"
+#define NN_PPC_PMU	"LINUX"
+#define NN_PPC_TM_CGPR	"LINUX"
+#define NN_PPC_TM_CFPR	"LINUX"
+#define NN_PPC_TM_CVMX	"LINUX"
+#define NN_PPC_TM_CVSX	"LINUX"
+#define NN_PPC_TM_SPR	"LINUX"
+#define NN_PPC_TM_CTAR	"LINUX"
+#define NN_PPC_TM_CPPR	"LINUX"
+#define NN_PPC_TM_CDSCR	"LINUX"
+#define NN_PPC_PKEY	"LINUX"
+#define NN_PPC_DEXCR	"LINUX"
+#define NN_PPC_HASHKEYR	"LINUX"
+#define NN_386_TLS	"LINUX"
+#define NN_386_IOPERM	"LINUX"
+#define NN_X86_XSTATE	"LINUX"
+#define NN_X86_SHSTK	"LINUX"
+#define NN_X86_XSAVE_LAYOUT	"LINUX"
+#define NN_S390_HIGH_GPRS	"LINUX"
+#define NN_S390_TIMER	"LINUX"
+#define NN_S390_TODCMP	"LINUX"
+#define NN_S390_TODPREG	"LINUX"
+#define NN_S390_CTRS	"LINUX"
+#define NN_S390_PREFIX	"LINUX"
+#define NN_S390_LAST_BREAK	"LINUX"
+#define NN_S390_SYSTEM_CALL	"LINUX"
+#define NN_S390_TDB	"LINUX"
+#define NN_S390_VXRS_LOW	"LINUX"
+#define NN_S390_VXRS_HIGH	"LINUX"
+#define NN_S390_GS_CB	"LINUX"
+#define NN_S390_GS_BC	"LINUX"
+#define NN_S390_RI_CB	"LINUX"
+#define NN_S390_PV_CPU_DATA	"LINUX"
+#define NN_ARM_VFP	"LINUX"
+#define NN_ARM_TLS	"LINUX"
+#define NN_ARM_HW_BREAK	"LINUX"
+#define NN_ARM_HW_WATCH	"LINUX"
+#define NN_ARM_SYSTEM_CALL	"LINUX"
+#define NN_ARM_SVE	"LINUX"
+#define NN_ARM_PAC_MASK	"LINUX"
+#define NN_ARM_PACA_KEYS	"LINUX"
+#define NN_ARM_PACG_KEYS	"LINUX"
+#define NN_ARM_TAGGED_ADDR_CTRL	"LINUX"
+#define NN_ARM_PAC_ENABLED_KEYS	"LINUX"
+#define NN_ARM_SSVE	"LINUX"
+#define NN_ARM_ZA	"LINUX"
+#define NN_ARM_ZT	"LINUX"
+#define NN_ARM_FPMR	"LINUX"
+#define NN_ARM_POE	"LINUX"
+#define NN_ARM_GCS	"LINUX"
+#define NN_ARC_V2	"LINUX"
+#define NN_VMCOREDD	"LINUX"
+#define NN_MIPS_DSP	"LINUX"
+#define NN_MIPS_FP_MODE	"LINUX"
+#define NN_MIPS_MSA	"LINUX"
+#define NN_RISCV_CSR	"LINUX"
+#define NN_RISCV_VECTOR	"LINUX"
+#define NN_RISCV_TAGGED_ADDR_CTRL	"LINUX"
+#define NN_LOONGARCH_CPUCFG	"LINUX"
+#define NN_LOONGARCH_CSR	"LINUX"
+#define NN_LOONGARCH_LSX	"LINUX"
+#define NN_LOONGARCH_LASX	"LINUX"
+#define NN_LOONGARCH_LBT	"LINUX"
+#define NN_LOONGARCH_HW_BREAK	"LINUX"
+#define NN_LOONGARCH_HW_WATCH	"LINUX"
+#define NN_GNU_PROPERTY_TYPE_0	"GNU"
+
 /* Note header in a PT_NOTE section */
 typedef struct elf32_note {
   Elf32_Word	n_namesz;	/* Name size */