diff mbox series

[v3,02/12] ELF: Add ELF program property parsing support

Message ID 1571419545-20401-3-git-send-email-Dave.Martin@arm.com
State New
Headers show
Series arm64: ARMv8.5-A: Branch Target Identification support | expand

Commit Message

Dave Martin Oct. 18, 2019, 5:25 p.m. UTC
ELF program properties will be needed for detecting whether to
enable optional architecture or ABI features for a new ELF process.

For now, there are no generic properties that we care about, so do
nothing unless CONFIG_ARCH_USE_GNU_PROPERTY=y.

Otherwise, the presence of properties using the PT_PROGRAM_PROPERTY
phdrs entry (if any), and notify each property to the arch code.

For now, the added code is not used.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---
 fs/binfmt_elf.c          | 127 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/compat_binfmt_elf.c   |   4 ++
 include/linux/elf.h      |  19 +++++++
 include/uapi/linux/elf.h |   4 ++
 4 files changed, 154 insertions(+)

-- 
2.1.4

Comments

Kees Cook Oct. 29, 2019, 11:14 p.m. UTC | #1
On Fri, Oct 18, 2019 at 06:25:35PM +0100, Dave Martin wrote:
> ELF program properties will be needed for detecting whether to

> enable optional architecture or ABI features for a new ELF process.

> 

> For now, there are no generic properties that we care about, so do

> nothing unless CONFIG_ARCH_USE_GNU_PROPERTY=y.

> 

> Otherwise, the presence of properties using the PT_PROGRAM_PROPERTY

> phdrs entry (if any), and notify each property to the arch code.

> 

> For now, the added code is not used.

> 

> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

> ---

>  fs/binfmt_elf.c          | 127 +++++++++++++++++++++++++++++++++++++++++++++++

>  fs/compat_binfmt_elf.c   |   4 ++

>  include/linux/elf.h      |  19 +++++++

>  include/uapi/linux/elf.h |   4 ++

>  4 files changed, 154 insertions(+)

> 

> diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c

> index c5642bc..ae345f6 100644

> --- a/fs/binfmt_elf.c

> +++ b/fs/binfmt_elf.c

> @@ -39,12 +39,18 @@

>  #include <linux/sched/coredump.h>

>  #include <linux/sched/task_stack.h>

>  #include <linux/sched/cputime.h>

> +#include <linux/sizes.h>

> +#include <linux/types.h>

>  #include <linux/cred.h>

>  #include <linux/dax.h>

>  #include <linux/uaccess.h>

>  #include <asm/param.h>

>  #include <asm/page.h>

>  

> +#ifndef ELF_COMPAT

> +#define ELF_COMPAT 0

> +#endif


Why is "compat" interesting for the arch_ callback? Shouldn't just the
unsigned long size be needed?

> +

>  #ifndef user_long_t

>  #define user_long_t long

>  #endif

> @@ -670,6 +676,111 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,

>   * libraries.  There is no binary dependent code anywhere else.

>   */

>  

> +static int parse_elf_property(const char *data, size_t *off, size_t datasz,

> +			      struct arch_elf_state *arch,

> +			      bool have_prev_type, u32 *prev_type)

> +{

> +	size_t o, step;

> +	const struct gnu_property *pr;

> +	int ret;

> +

> +	if (*off == datasz)

> +		return -ENOENT;

> +

> +	if (WARN_ON(*off > datasz || *off % ELF_GNU_PROPERTY_ALIGN))


I think here and all other places using WARN_ON() in the execve() path
should be using WARN_ON_ONCE() to avoid allowing a user to potentially
flood the system logs with insane binary exec attempts.

-Kees

> +		return -EIO;

> +	o = *off;

> +	datasz -= *off;

> +

> +	if (datasz < sizeof(*pr))

> +		return -EIO;

> +	pr = (const struct gnu_property *)(data + o);

> +	o += sizeof(*pr);

> +	datasz -= sizeof(*pr);

> +

> +	if (pr->pr_datasz > datasz)

> +		return -EIO;

> +

> +	WARN_ON(o % ELF_GNU_PROPERTY_ALIGN);

> +	step = round_up(pr->pr_datasz, ELF_GNU_PROPERTY_ALIGN);

> +	if (step > datasz)

> +		return -EIO;

> +

> +	/* Properties are supposed to be unique and sorted on pr_type: */

> +	if (have_prev_type && pr->pr_type <= *prev_type)

> +		return -EIO;

> +	*prev_type = pr->pr_type;

> +

> +	ret = arch_parse_elf_property(pr->pr_type, data + o,

> +				      pr->pr_datasz, ELF_COMPAT, arch);

> +	if (ret)

> +		return ret;

> +

> +	*off = o + step;

> +	return 0;

> +}

> +

> +#define NOTE_DATA_SZ SZ_1K

> +#define GNU_PROPERTY_TYPE_0_NAME "GNU"

> +#define NOTE_NAME_SZ (sizeof(GNU_PROPERTY_TYPE_0_NAME))

> +

> +static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,

> +				struct arch_elf_state *arch)

> +{

> +	union {

> +		struct elf_note nhdr;

> +		char data[NOTE_DATA_SZ];

> +	} note;

> +	loff_t pos;

> +	ssize_t n;

> +	size_t off, datasz;

> +	int ret;

> +	bool have_prev_type;

> +	u32 prev_type;

> +

> +	if (!IS_ENABLED(CONFIG_ARCH_USE_GNU_PROPERTY) || !phdr)

> +		return 0;

> +

> +	/* load_elf_binary() shouldn't call us unless this is true... */

> +	if (WARN_ON(phdr->p_type != PT_GNU_PROPERTY))

> +		return -EIO;

> +

> +	/* If the properties are crazy large, that's too bad (for now): */

> +	if (phdr->p_filesz > sizeof(note))

> +		return -ENOEXEC;

> +

> +	pos = phdr->p_offset;

> +	n = kernel_read(f, &note, phdr->p_filesz, &pos);

> +

> +	BUILD_BUG_ON(sizeof(note) < sizeof(note.nhdr) + NOTE_NAME_SZ);

> +	if (n < 0 || n < sizeof(note.nhdr) + NOTE_NAME_SZ)

> +		return -EIO;

> +

> +	if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||

> +	    note.nhdr.n_namesz != NOTE_NAME_SZ ||

> +	    strncmp(note.data + sizeof(note.nhdr),

> +		    GNU_PROPERTY_TYPE_0_NAME, n - sizeof(note.nhdr)))

> +		return -EIO;

> +

> +	off = round_up(sizeof(note.nhdr) + NOTE_NAME_SZ,

> +		       ELF_GNU_PROPERTY_ALIGN);

> +	if (off > n)

> +		return -EIO;

> +

> +	if (note.nhdr.n_descsz > n - off)

> +		return -EIO;

> +	datasz = off + note.nhdr.n_descsz;

> +

> +	have_prev_type = false;

> +	do {

> +		ret = parse_elf_property(note.data, &off, datasz, arch,

> +					 have_prev_type, &prev_type);

> +		have_prev_type = true;

> +	} while (!ret);

> +

> +	return ret == -ENOENT ? 0 : ret;

> +}

> +

>  static int load_elf_binary(struct linux_binprm *bprm)

>  {

>  	struct file *interpreter = NULL; /* to shut gcc up */

> @@ -677,6 +788,7 @@ static int load_elf_binary(struct linux_binprm *bprm)

>  	int load_addr_set = 0;

>  	unsigned long error;

>  	struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;

> +	struct elf_phdr *elf_property_phdata = NULL;

>  	unsigned long elf_bss, elf_brk;

>  	int bss_prot = 0;

>  	int retval, i;

> @@ -724,6 +836,11 @@ static int load_elf_binary(struct linux_binprm *bprm)

>  		char *elf_interpreter;

>  		loff_t pos;

>  

> +		if (elf_ppnt->p_type == PT_GNU_PROPERTY) {

> +			elf_property_phdata = elf_ppnt;

> +			continue;

> +		}

> +

>  		if (elf_ppnt->p_type != PT_INTERP)

>  			continue;

>  

> @@ -819,9 +936,14 @@ static int load_elf_binary(struct linux_binprm *bprm)

>  			goto out_free_dentry;

>  

>  		/* Pass PT_LOPROC..PT_HIPROC headers to arch code */

> +		elf_property_phdata = NULL;

>  		elf_ppnt = interp_elf_phdata;

>  		for (i = 0; i < loc->interp_elf_ex.e_phnum; i++, elf_ppnt++)

>  			switch (elf_ppnt->p_type) {

> +			case PT_GNU_PROPERTY:

> +				elf_property_phdata = elf_ppnt;

> +				break;

> +

>  			case PT_LOPROC ... PT_HIPROC:

>  				retval = arch_elf_pt_proc(&loc->interp_elf_ex,

>  							  elf_ppnt, interpreter,

> @@ -832,6 +954,11 @@ static int load_elf_binary(struct linux_binprm *bprm)

>  			}

>  	}

>  

> +	retval = parse_elf_properties(interpreter ?: bprm->file,

> +				      elf_property_phdata, &arch_state);

> +	if (retval)

> +		goto out_free_dentry;

> +

>  	/*

>  	 * Allow arch code to reject the ELF at this point, whilst it's

>  	 * still possible to return an error to the code that invoked

> diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c

> index b7f9ffa..67896e0 100644

> --- a/fs/compat_binfmt_elf.c

> +++ b/fs/compat_binfmt_elf.c

> @@ -17,6 +17,8 @@

>  #include <linux/elfcore-compat.h>

>  #include <linux/time.h>

>  

> +#define ELF_COMPAT	1

> +

>  /*

>   * Rename the basic ELF layout types to refer to the 32-bit class of files.

>   */

> @@ -28,11 +30,13 @@

>  #undef	elf_shdr

>  #undef	elf_note

>  #undef	elf_addr_t

> +#undef	ELF_GNU_PROPERTY_ALIGN

>  #define elfhdr		elf32_hdr

>  #define elf_phdr	elf32_phdr

>  #define elf_shdr	elf32_shdr

>  #define elf_note	elf32_note

>  #define elf_addr_t	Elf32_Addr

> +#define ELF_GNU_PROPERTY_ALIGN	ELF32_GNU_PROPERTY_ALIGN

>  

>  /*

>   * Some data types as stored in coredump.

> diff --git a/include/linux/elf.h b/include/linux/elf.h

> index 459cddc..7bdc6da 100644

> --- a/include/linux/elf.h

> +++ b/include/linux/elf.h

> @@ -22,6 +22,9 @@

>  	SET_PERSONALITY(ex)

>  #endif

>  

> +#define ELF32_GNU_PROPERTY_ALIGN	4

> +#define ELF64_GNU_PROPERTY_ALIGN	8

> +

>  #if ELF_CLASS == ELFCLASS32

>  

>  extern Elf32_Dyn _DYNAMIC [];

> @@ -32,6 +35,7 @@ extern Elf32_Dyn _DYNAMIC [];

>  #define elf_addr_t	Elf32_Off

>  #define Elf_Half	Elf32_Half

>  #define Elf_Word	Elf32_Word

> +#define ELF_GNU_PROPERTY_ALIGN	ELF32_GNU_PROPERTY_ALIGN

>  

>  #else

>  

> @@ -43,6 +47,7 @@ extern Elf64_Dyn _DYNAMIC [];

>  #define elf_addr_t	Elf64_Off

>  #define Elf_Half	Elf64_Half

>  #define Elf_Word	Elf64_Word

> +#define ELF_GNU_PROPERTY_ALIGN	ELF64_GNU_PROPERTY_ALIGN

>  

>  #endif

>  

> @@ -64,4 +69,18 @@ struct gnu_property {

>  	u32 pr_datasz;

>  };

>  

> +struct arch_elf_state;

> +

> +#ifndef CONFIG_ARCH_USE_GNU_PROPERTY

> +static inline int arch_parse_elf_property(u32 type, const void *data,

> +					  size_t datasz, bool compat,

> +					  struct arch_elf_state *arch)

> +{

> +	return 0;

> +}

> +#else

> +extern int arch_parse_elf_property(u32 type, const void *data, size_t datasz,

> +				   bool compat, struct arch_elf_state *arch);

> +#endif

> +

>  #endif /* _LINUX_ELF_H */

> diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h

> index c377314..20900f4 100644

> --- a/include/uapi/linux/elf.h

> +++ b/include/uapi/linux/elf.h

> @@ -368,6 +368,7 @@ 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 all these is "LINUX".

>   */

>  #define NT_PRSTATUS	1

>  #define NT_PRFPREG	2

> @@ -430,6 +431,9 @@ typedef struct elf64_shdr {

>  #define NT_MIPS_FP_MODE	0x801		/* MIPS floating-point mode */

>  #define NT_MIPS_MSA	0x802		/* MIPS SIMD registers */

>  

> +/* Note types with note name "GNU" */

> +#define NT_GNU_PROPERTY_TYPE_0	5

> +

>  /* Note header in a PT_NOTE section */

>  typedef struct elf32_note {

>    Elf32_Word	n_namesz;	/* Name size */

> -- 

> 2.1.4

> 


-- 
Kees Cook
Mark Brown Dec. 11, 2019, 1:58 p.m. UTC | #2
On Tue, Oct 29, 2019 at 04:14:47PM -0700, Kees Cook wrote:
> On Fri, Oct 18, 2019 at 06:25:35PM +0100, Dave Martin wrote:


A bit of a delay, sorry - I've taken this series over from Dave and
wasn't on the CC so only just saw this.

> > +#ifndef ELF_COMPAT

> > +#define ELF_COMPAT 0

> > +#endif


> Why is "compat" interesting for the arch_ callback? Shouldn't just the

> unsigned long size be needed?


The set of properties handled or how they should be handled may vary
depending on the ABI.  For example arm64 supports BTI only for AArch64
but not for AArch32 so we should only handle the property for BTI for
AArch64 binaries.
diff mbox series

Patch

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index c5642bc..ae345f6 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -39,12 +39,18 @@ 
 #include <linux/sched/coredump.h>
 #include <linux/sched/task_stack.h>
 #include <linux/sched/cputime.h>
+#include <linux/sizes.h>
+#include <linux/types.h>
 #include <linux/cred.h>
 #include <linux/dax.h>
 #include <linux/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
 
+#ifndef ELF_COMPAT
+#define ELF_COMPAT 0
+#endif
+
 #ifndef user_long_t
 #define user_long_t long
 #endif
@@ -670,6 +676,111 @@  static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
  * libraries.  There is no binary dependent code anywhere else.
  */
 
+static int parse_elf_property(const char *data, size_t *off, size_t datasz,
+			      struct arch_elf_state *arch,
+			      bool have_prev_type, u32 *prev_type)
+{
+	size_t o, step;
+	const struct gnu_property *pr;
+	int ret;
+
+	if (*off == datasz)
+		return -ENOENT;
+
+	if (WARN_ON(*off > datasz || *off % ELF_GNU_PROPERTY_ALIGN))
+		return -EIO;
+	o = *off;
+	datasz -= *off;
+
+	if (datasz < sizeof(*pr))
+		return -EIO;
+	pr = (const struct gnu_property *)(data + o);
+	o += sizeof(*pr);
+	datasz -= sizeof(*pr);
+
+	if (pr->pr_datasz > datasz)
+		return -EIO;
+
+	WARN_ON(o % ELF_GNU_PROPERTY_ALIGN);
+	step = round_up(pr->pr_datasz, ELF_GNU_PROPERTY_ALIGN);
+	if (step > datasz)
+		return -EIO;
+
+	/* Properties are supposed to be unique and sorted on pr_type: */
+	if (have_prev_type && pr->pr_type <= *prev_type)
+		return -EIO;
+	*prev_type = pr->pr_type;
+
+	ret = arch_parse_elf_property(pr->pr_type, data + o,
+				      pr->pr_datasz, ELF_COMPAT, arch);
+	if (ret)
+		return ret;
+
+	*off = o + step;
+	return 0;
+}
+
+#define NOTE_DATA_SZ SZ_1K
+#define GNU_PROPERTY_TYPE_0_NAME "GNU"
+#define NOTE_NAME_SZ (sizeof(GNU_PROPERTY_TYPE_0_NAME))
+
+static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,
+				struct arch_elf_state *arch)
+{
+	union {
+		struct elf_note nhdr;
+		char data[NOTE_DATA_SZ];
+	} note;
+	loff_t pos;
+	ssize_t n;
+	size_t off, datasz;
+	int ret;
+	bool have_prev_type;
+	u32 prev_type;
+
+	if (!IS_ENABLED(CONFIG_ARCH_USE_GNU_PROPERTY) || !phdr)
+		return 0;
+
+	/* load_elf_binary() shouldn't call us unless this is true... */
+	if (WARN_ON(phdr->p_type != PT_GNU_PROPERTY))
+		return -EIO;
+
+	/* If the properties are crazy large, that's too bad (for now): */
+	if (phdr->p_filesz > sizeof(note))
+		return -ENOEXEC;
+
+	pos = phdr->p_offset;
+	n = kernel_read(f, &note, phdr->p_filesz, &pos);
+
+	BUILD_BUG_ON(sizeof(note) < sizeof(note.nhdr) + NOTE_NAME_SZ);
+	if (n < 0 || n < sizeof(note.nhdr) + NOTE_NAME_SZ)
+		return -EIO;
+
+	if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
+	    note.nhdr.n_namesz != NOTE_NAME_SZ ||
+	    strncmp(note.data + sizeof(note.nhdr),
+		    GNU_PROPERTY_TYPE_0_NAME, n - sizeof(note.nhdr)))
+		return -EIO;
+
+	off = round_up(sizeof(note.nhdr) + NOTE_NAME_SZ,
+		       ELF_GNU_PROPERTY_ALIGN);
+	if (off > n)
+		return -EIO;
+
+	if (note.nhdr.n_descsz > n - off)
+		return -EIO;
+	datasz = off + note.nhdr.n_descsz;
+
+	have_prev_type = false;
+	do {
+		ret = parse_elf_property(note.data, &off, datasz, arch,
+					 have_prev_type, &prev_type);
+		have_prev_type = true;
+	} while (!ret);
+
+	return ret == -ENOENT ? 0 : ret;
+}
+
 static int load_elf_binary(struct linux_binprm *bprm)
 {
 	struct file *interpreter = NULL; /* to shut gcc up */
@@ -677,6 +788,7 @@  static int load_elf_binary(struct linux_binprm *bprm)
 	int load_addr_set = 0;
 	unsigned long error;
 	struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
+	struct elf_phdr *elf_property_phdata = NULL;
 	unsigned long elf_bss, elf_brk;
 	int bss_prot = 0;
 	int retval, i;
@@ -724,6 +836,11 @@  static int load_elf_binary(struct linux_binprm *bprm)
 		char *elf_interpreter;
 		loff_t pos;
 
+		if (elf_ppnt->p_type == PT_GNU_PROPERTY) {
+			elf_property_phdata = elf_ppnt;
+			continue;
+		}
+
 		if (elf_ppnt->p_type != PT_INTERP)
 			continue;
 
@@ -819,9 +936,14 @@  static int load_elf_binary(struct linux_binprm *bprm)
 			goto out_free_dentry;
 
 		/* Pass PT_LOPROC..PT_HIPROC headers to arch code */
+		elf_property_phdata = NULL;
 		elf_ppnt = interp_elf_phdata;
 		for (i = 0; i < loc->interp_elf_ex.e_phnum; i++, elf_ppnt++)
 			switch (elf_ppnt->p_type) {
+			case PT_GNU_PROPERTY:
+				elf_property_phdata = elf_ppnt;
+				break;
+
 			case PT_LOPROC ... PT_HIPROC:
 				retval = arch_elf_pt_proc(&loc->interp_elf_ex,
 							  elf_ppnt, interpreter,
@@ -832,6 +954,11 @@  static int load_elf_binary(struct linux_binprm *bprm)
 			}
 	}
 
+	retval = parse_elf_properties(interpreter ?: bprm->file,
+				      elf_property_phdata, &arch_state);
+	if (retval)
+		goto out_free_dentry;
+
 	/*
 	 * Allow arch code to reject the ELF at this point, whilst it's
 	 * still possible to return an error to the code that invoked
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c
index b7f9ffa..67896e0 100644
--- a/fs/compat_binfmt_elf.c
+++ b/fs/compat_binfmt_elf.c
@@ -17,6 +17,8 @@ 
 #include <linux/elfcore-compat.h>
 #include <linux/time.h>
 
+#define ELF_COMPAT	1
+
 /*
  * Rename the basic ELF layout types to refer to the 32-bit class of files.
  */
@@ -28,11 +30,13 @@ 
 #undef	elf_shdr
 #undef	elf_note
 #undef	elf_addr_t
+#undef	ELF_GNU_PROPERTY_ALIGN
 #define elfhdr		elf32_hdr
 #define elf_phdr	elf32_phdr
 #define elf_shdr	elf32_shdr
 #define elf_note	elf32_note
 #define elf_addr_t	Elf32_Addr
+#define ELF_GNU_PROPERTY_ALIGN	ELF32_GNU_PROPERTY_ALIGN
 
 /*
  * Some data types as stored in coredump.
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 459cddc..7bdc6da 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -22,6 +22,9 @@ 
 	SET_PERSONALITY(ex)
 #endif
 
+#define ELF32_GNU_PROPERTY_ALIGN	4
+#define ELF64_GNU_PROPERTY_ALIGN	8
+
 #if ELF_CLASS == ELFCLASS32
 
 extern Elf32_Dyn _DYNAMIC [];
@@ -32,6 +35,7 @@  extern Elf32_Dyn _DYNAMIC [];
 #define elf_addr_t	Elf32_Off
 #define Elf_Half	Elf32_Half
 #define Elf_Word	Elf32_Word
+#define ELF_GNU_PROPERTY_ALIGN	ELF32_GNU_PROPERTY_ALIGN
 
 #else
 
@@ -43,6 +47,7 @@  extern Elf64_Dyn _DYNAMIC [];
 #define elf_addr_t	Elf64_Off
 #define Elf_Half	Elf64_Half
 #define Elf_Word	Elf64_Word
+#define ELF_GNU_PROPERTY_ALIGN	ELF64_GNU_PROPERTY_ALIGN
 
 #endif
 
@@ -64,4 +69,18 @@  struct gnu_property {
 	u32 pr_datasz;
 };
 
+struct arch_elf_state;
+
+#ifndef CONFIG_ARCH_USE_GNU_PROPERTY
+static inline int arch_parse_elf_property(u32 type, const void *data,
+					  size_t datasz, bool compat,
+					  struct arch_elf_state *arch)
+{
+	return 0;
+}
+#else
+extern int arch_parse_elf_property(u32 type, const void *data, size_t datasz,
+				   bool compat, struct arch_elf_state *arch);
+#endif
+
 #endif /* _LINUX_ELF_H */
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index c377314..20900f4 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -368,6 +368,7 @@  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 all these is "LINUX".
  */
 #define NT_PRSTATUS	1
 #define NT_PRFPREG	2
@@ -430,6 +431,9 @@  typedef struct elf64_shdr {
 #define NT_MIPS_FP_MODE	0x801		/* MIPS floating-point mode */
 #define NT_MIPS_MSA	0x802		/* MIPS SIMD registers */
 
+/* Note types with note name "GNU" */
+#define NT_GNU_PROPERTY_TYPE_0	5
+
 /* Note header in a PT_NOTE section */
 typedef struct elf32_note {
   Elf32_Word	n_namesz;	/* Name size */