Skip to contentSkip to conversation

x86/boot: Add the secdata section to the setup header

RFC PATCH Superseded Gary Lin 4 participants 12 messages May 12, 2017 – Oct 3, 2017 x86

lore
Share & tools
lore

Gary Lin

author
#0 lore raw

RFC PATCH v2 1/1 x86/boot: Add the secdata section to the setup header

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
	__u16 header_length;
	__u32 distro_version;
	__u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup header is limited to around 32KB.
- Restructure the secdata section. The signer is now a null-terminated string. The type of distro_version changes to u32 in case the distro uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28 ++++++++++++++++++++++++++++
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +28 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
 	   If unsure, say N.
 
+config SIGNER_NAME
+	string "Signer name"
+	default ""
+	---help---
+	   This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+	int "Distribution version"
+	default 0
+	range 0 4294967295
+	---help---
+	  This option specifies the distribution version which this
+	  kernel belongs to.
+
+config SECURITY_VERSION
+	int "Security version"
+	default 0
+	range 0 65535
+	---help---
+	   The security version is the version defined by the distribution
+	   to indicate the severe security fixes. The bootloader can maintain
+	   a list of the security versions of the current kernels. After
+	   fixing a severe vulnerability in the kernel, the distribution can
+	   increase the security version to notify the bootloader to update
+	   the list. When booting a kernel with a lower security version,
+	   the bootloader warns the user to avoid loading a vulnerable kernel
+	   accidentally.
+
 config SECCOMP
 	def_bool y
 	prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +13 -1
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
 	# Part 2 of the header, from the old setup.S
 
 		.ascii	"HdrS"		# header signature
-		.word	0x020d		# header version number (>= 0x0105)
+		.word	0x020e		# header version number (>= 0x0105)
 					# or else old loadlin-1.5 will fail)
 		.globl realmode_swtch
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
@@ -552,6 +552,7 @@ pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
 
 init_size:		.long INIT_SIZE		# kernel initialization size
 handover_offset:	.long 0			# Filled in by build.c
+secdata_offset:		.word secdata_start
 
 # End of setup header #####################################################
 
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
 	.byte	7
 	.string	"No setup signature found...\n"
+
+	.section ".secdata", "a"
+secdata_start:
+header_length:
+	.word	signer - secdata_start
+distro_version:
+	.long	CONFIG_DISTRO_VERSION
+security_version:
+	.word	CONFIG_SECURITY_VERSION
+signer:
+	.string	CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
 	.entrytext	: { *(.entrytext) }
 	.inittext	: { *(.inittext) }
 	.initdata	: { *(.initdata) }
+	.secdata	: { *(.secdata) }
 	__end_init = .;
 
 	.text		: { *(.text) }
arch/x86/boot/tools/build.c +0 -1
index 0702d2531bc7..a629d6b615cf 100644
@@ -287,7 +287,6 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
-
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
  * but that would mean tools/build would have to be rebuilt every time. It's
arch/x86/include/uapi/asm/bootparam.h +1 -0
index 07244ea16765..32ffacfaaaff 100644
@@ -85,6 +85,7 @@ struct setup_header {
 	__u64	pref_address;
 	__u32	init_size;
 	__u32	handover_offset;
+	__u16	secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
Signature · 1 line
2.12.2
author
#1 lore raw
Quoted 26 lines · Gary Lin

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
	__u16 header_length;
	__u32 distro_version;
	__u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Quoted 3 lines

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

Any comment?

Gary Lin

Quoted 137 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup header is limited to around 32KB.
- Restructure the secdata section. The signer is now a null-terminated string. The type of distro_version changes to u32 in case the distro uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28 ++++++++++++++++++++++++++++
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +28 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
 	   If unsure, say N.
 
+config SIGNER_NAME
+	string "Signer name"
+	default ""
+	---help---
+	   This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+	int "Distribution version"
+	default 0
+	range 0 4294967295
+	---help---
+	  This option specifies the distribution version which this
+	  kernel belongs to.
+
+config SECURITY_VERSION
+	int "Security version"
+	default 0
+	range 0 65535
+	---help---
+	   The security version is the version defined by the distribution
+	   to indicate the severe security fixes. The bootloader can maintain
+	   a list of the security versions of the current kernels. After
+	   fixing a severe vulnerability in the kernel, the distribution can
+	   increase the security version to notify the bootloader to update
+	   the list. When booting a kernel with a lower security version,
+	   the bootloader warns the user to avoid loading a vulnerable kernel
+	   accidentally.
+
 config SECCOMP
 	def_bool y
 	prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +13 -1
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
 	# Part 2 of the header, from the old setup.S
 
 		.ascii	"HdrS"		# header signature
-		.word	0x020d		# header version number (>= 0x0105)
+		.word	0x020e		# header version number (>= 0x0105)
 					# or else old loadlin-1.5 will fail)
 		.globl realmode_swtch
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
@@ -552,6 +552,7 @@ pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
 
 init_size:		.long INIT_SIZE		# kernel initialization size
 handover_offset:	.long 0			# Filled in by build.c
+secdata_offset:		.word secdata_start
 
 # End of setup header #####################################################
 
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
 	.byte	7
 	.string	"No setup signature found...\n"
+
+	.section ".secdata", "a"
+secdata_start:
+header_length:
+	.word	signer - secdata_start
+distro_version:
+	.long	CONFIG_DISTRO_VERSION
+security_version:
+	.word	CONFIG_SECURITY_VERSION
+signer:
+	.string	CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
 	.entrytext	: { *(.entrytext) }
 	.inittext	: { *(.inittext) }
 	.initdata	: { *(.initdata) }
+	.secdata	: { *(.secdata) }
 	__end_init = .;
 
 	.text		: { *(.text) }
arch/x86/boot/tools/build.c +0 -1
index 0702d2531bc7..a629d6b615cf 100644
@@ -287,7 +287,6 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
-
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
  * but that would mean tools/build would have to be rebuilt every time. It's
arch/x86/include/uapi/asm/bootparam.h +1 -0
index 07244ea16765..32ffacfaaaff 100644
@@ -85,6 +85,7 @@ struct setup_header {
 	__u64	pref_address;
 	__u32	init_size;
 	__u32	handover_offset;
+	__u16	secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
Signature · 1 line
2.12.2
#2 lore raw
Quoted 27 lines · Gary Lin
Quoted 26 lines · Gary Lin

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Quoted 5 lines
Quoted 3 lines

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

Signature · 1 line
Ard.
Quoted 137 lines
Quoted 137 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup header is limited to around 32KB.
- Restructure the secdata section. The signer is now a null-terminated string. The type of distro_version changes to u32 in case the distro uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28 ++++++++++++++++++++++++++++
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +28 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
         If unsure, say N.
 
+config SIGNER_NAME
+     string "Signer name"
+     default ""
+     ---help---
+        This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+     int "Distribution version"
+     default 0
+     range 0 4294967295
+     ---help---
+       This option specifies the distribution version which this
+       kernel belongs to.
+
+config SECURITY_VERSION
+     int "Security version"
+     default 0
+     range 0 65535
+     ---help---
+        The security version is the version defined by the distribution
+        to indicate the severe security fixes. The bootloader can maintain
+        a list of the security versions of the current kernels. After
+        fixing a severe vulnerability in the kernel, the distribution can
+        increase the security version to notify the bootloader to update
+        the list. When booting a kernel with a lower security version,
+        the bootloader warns the user to avoid loading a vulnerable kernel
+        accidentally.
+
 config SECCOMP
      def_bool y
      prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +13 -1
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
      # Part 2 of the header, from the old setup.S
 
              .ascii  "HdrS"          # header signature
-             .word   0x020d          # header version number (>= 0x0105)
+             .word   0x020e          # header version number (>= 0x0105)
                                      # or else old loadlin-1.5 will fail)
              .globl realmode_swtch
 realmode_swtch:      .word   0, 0            # default_switch, SETUPSEG
@@ -552,6 +552,7 @@ pref_address:             .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 
 init_size:           .long INIT_SIZE         # kernel initialization size
 handover_offset:     .long 0                 # Filled in by build.c
+secdata_offset:              .word secdata_start
 
 # End of setup header #####################################################
 
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
      .byte   7
      .string "No setup signature found...\n"
+
+     .section ".secdata", "a"
+secdata_start:
+header_length:
+     .word   signer - secdata_start
+distro_version:
+     .long   CONFIG_DISTRO_VERSION
+security_version:
+     .word   CONFIG_SECURITY_VERSION
+signer:
+     .string CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
      .entrytext      : { *(.entrytext) }
      .inittext       : { *(.inittext) }
      .initdata       : { *(.initdata) }
+     .secdata        : { *(.secdata) }
      __end_init = .;
 
      .text           : { *(.text) }
arch/x86/boot/tools/build.c +0 -1
index 0702d2531bc7..a629d6b615cf 100644
@@ -287,7 +287,6 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
-
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
  * but that would mean tools/build would have to be rebuilt every time. It's
arch/x86/include/uapi/asm/bootparam.h +1 -1
index 07244ea16765..32ffacfaaaff 100644
@@ -85,6 +85,7 @@ struct setup_header {
      __u64   pref_address;
      __u32   init_size;
      __u32   handover_offset;
+     __u16   secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
--

2.12.2

author
#3 lore raw
Quoted 28 lines · Ard Biesheuvel
Quoted 27 lines · Gary Lin
Quoted 26 lines · Gary Lin

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Quoted 9 lines
Quoted 5 lines
Quoted 3 lines

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

That's why I proposed to use the PE/COFF header in the beginning, but it's hard to clear the concern about the potential change in the PE/COFF header. So far, I'm not aware of other generic solution to put those fields, so I'm planning to work on x86 and arm64 separately.

Gary Lin

Quoted 142 lines
Signature · 1 line
Ard.
Quoted 137 lines
Quoted 137 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup header is limited to around 32KB.
- Restructure the secdata section. The signer is now a null-terminated string. The type of distro_version changes to u32 in case the distro uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28 ++++++++++++++++++++++++++++
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +28 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
         If unsure, say N.
 
+config SIGNER_NAME
+     string "Signer name"
+     default ""
+     ---help---
+        This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+     int "Distribution version"
+     default 0
+     range 0 4294967295
+     ---help---
+       This option specifies the distribution version which this
+       kernel belongs to.
+
+config SECURITY_VERSION
+     int "Security version"
+     default 0
+     range 0 65535
+     ---help---
+        The security version is the version defined by the distribution
+        to indicate the severe security fixes. The bootloader can maintain
+        a list of the security versions of the current kernels. After
+        fixing a severe vulnerability in the kernel, the distribution can
+        increase the security version to notify the bootloader to update
+        the list. When booting a kernel with a lower security version,
+        the bootloader warns the user to avoid loading a vulnerable kernel
+        accidentally.
+
 config SECCOMP
      def_bool y
      prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +13 -1
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
      # Part 2 of the header, from the old setup.S
 
              .ascii  "HdrS"          # header signature
-             .word   0x020d          # header version number (>= 0x0105)
+             .word   0x020e          # header version number (>= 0x0105)
                                      # or else old loadlin-1.5 will fail)
              .globl realmode_swtch
 realmode_swtch:      .word   0, 0            # default_switch, SETUPSEG
@@ -552,6 +552,7 @@ pref_address:             .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 
 init_size:           .long INIT_SIZE         # kernel initialization size
 handover_offset:     .long 0                 # Filled in by build.c
+secdata_offset:              .word secdata_start
 
 # End of setup header #####################################################
 
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
      .byte   7
      .string "No setup signature found...\n"
+
+     .section ".secdata", "a"
+secdata_start:
+header_length:
+     .word   signer - secdata_start
+distro_version:
+     .long   CONFIG_DISTRO_VERSION
+security_version:
+     .word   CONFIG_SECURITY_VERSION
+signer:
+     .string CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
      .entrytext      : { *(.entrytext) }
      .inittext       : { *(.inittext) }
      .initdata       : { *(.initdata) }
+     .secdata        : { *(.secdata) }
      __end_init = .;
 
      .text           : { *(.text) }
arch/x86/boot/tools/build.c +0 -1
index 0702d2531bc7..a629d6b615cf 100644
@@ -287,7 +287,6 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
-
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
  * but that would mean tools/build would have to be rebuilt every time. It's
arch/x86/include/uapi/asm/bootparam.h +1 -1
index 07244ea16765..32ffacfaaaff 100644
@@ -85,6 +85,7 @@ struct setup_header {
      __u64   pref_address;
      __u32   init_size;
      __u32   handover_offset;
+     __u16   secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
--

2.12.2

#4 lore raw
In reply to Ard Biesheuvel

Hi Ard,

Quoted 28 lines · Ard Biesheuvel
Quoted 27 lines · Gary Lin
Quoted 26 lines · Gary Lin

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Quoted 11 lines
Quoted 5 lines
Quoted 3 lines

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

Signature · 1 line
Ard.

On x86 platform with secure boot, UEFI boot loader (e.g. shim) keeps the kernel security version in boot variable for comparing to prevent replay attack.

Will ARM platform also apply this approach? Does ARM platform have secure boot knob in firmware?

Thanks a lot!
Joey Lee

Quoted 138 lines
Quoted 138 lines
Quoted 138 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup header is limited to around 32KB.
- Restructure the secdata section. The signer is now a null-terminated string. The type of distro_version changes to u32 in case the distro uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28 ++++++++++++++++++++++++++++
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +28 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
         If unsure, say N.
 
+config SIGNER_NAME
+     string "Signer name"
+     default ""
+     ---help---
+        This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+     int "Distribution version"
+     default 0
+     range 0 4294967295
+     ---help---
+       This option specifies the distribution version which this
+       kernel belongs to.
+
+config SECURITY_VERSION
+     int "Security version"
+     default 0
+     range 0 65535
+     ---help---
+        The security version is the version defined by the distribution
+        to indicate the severe security fixes. The bootloader can maintain
+        a list of the security versions of the current kernels. After
+        fixing a severe vulnerability in the kernel, the distribution can
+        increase the security version to notify the bootloader to update
+        the list. When booting a kernel with a lower security version,
+        the bootloader warns the user to avoid loading a vulnerable kernel
+        accidentally.
+
 config SECCOMP
      def_bool y
      prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +13 -1
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
      # Part 2 of the header, from the old setup.S
 
              .ascii  "HdrS"          # header signature
-             .word   0x020d          # header version number (>= 0x0105)
+             .word   0x020e          # header version number (>= 0x0105)
                                      # or else old loadlin-1.5 will fail)
              .globl realmode_swtch
 realmode_swtch:      .word   0, 0            # default_switch, SETUPSEG
@@ -552,6 +552,7 @@ pref_address:             .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 
 init_size:           .long INIT_SIZE         # kernel initialization size
 handover_offset:     .long 0                 # Filled in by build.c
+secdata_offset:              .word secdata_start
 
 # End of setup header #####################################################
 
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
      .byte   7
      .string "No setup signature found...\n"
+
+     .section ".secdata", "a"
+secdata_start:
+header_length:
+     .word   signer - secdata_start
+distro_version:
+     .long   CONFIG_DISTRO_VERSION
+security_version:
+     .word   CONFIG_SECURITY_VERSION
+signer:
+     .string CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
      .entrytext      : { *(.entrytext) }
      .inittext       : { *(.inittext) }
      .initdata       : { *(.initdata) }
+     .secdata        : { *(.secdata) }
      __end_init = .;
 
      .text           : { *(.text) }
arch/x86/boot/tools/build.c +0 -1
index 0702d2531bc7..a629d6b615cf 100644
@@ -287,7 +287,6 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
-
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
  * but that would mean tools/build would have to be rebuilt every time. It's
arch/x86/include/uapi/asm/bootparam.h +1 -1
index 07244ea16765..32ffacfaaaff 100644
@@ -85,6 +85,7 @@ struct setup_header {
      __u64   pref_address;
      __u32   init_size;
      __u32   handover_offset;
+     __u16   secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
--

2.12.2

#5 lore raw
Quoted 43 lines · joeyli

Hi Ard,

Quoted 31 lines · Ard Biesheuvel
Quoted 30 lines · Gary Lin
Quoted 29 lines · Gary Lin

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

Quoted 8 lines
Quoted 2 lines

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

--
Ard.

Quoted 7 lines

On x86 platform with secure boot, UEFI boot loader (e.g. shim) keeps the kernel security version in boot variable for comparing to prevent replay attack.

Will ARM platform also apply this approach? Does ARM platform have secure boot knob in firmware?

Yes, there is no reason to assume ARM differs from x86 in this respect. Shim can be built for ARM as well as for x86.

author
#6 lore raw
In reply to Ard Biesheuvel
Quoted 28 lines · Ard Biesheuvel
Quoted 27 lines · Gary Lin
Quoted 26 lines · Gary Lin

A new section, secdata, in the setup header is introduced to store the distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or vulnerable kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated string. "header_length" is the size of "struct sec_hdr" and can be used as the offset to "signer". It also can be a kind of the "header version" to detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version" in the kernel build afterward. The bootloader can maintain a list of the security versions of the current kernels and only allows the kernel with a higher or equal security version to boot. If the user is going to boot a kernel with a lower security version, a warning should show to prevent the user from loading a vulnerable kernel accidentally.

Quoted 9 lines
Quoted 5 lines
Quoted 3 lines

Enabling UEFI Secure Boot is recommended when using the security version or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

After check the headers again, another idea came to my mind: the MS-DOS stub. It's designed to show a warning while the image is loaded in DOS(*), but I wonder if it still matters. In the x86 linux efi header, the stub is just a 3-lines message, while arm64 completely ignores the stub.

Since there is a offset to the PE header at 0x3c, we can theoretically put any thing between 0x40 and the PE header without affecting the current settings.

HPA,

Does the MS-DOS stub raise any concern to you?

Thanks,

Gary Lin

(*) https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#ms-dos_stub__image_only_

Quoted 142 lines
Signature · 1 line
Ard.
Quoted 137 lines
Quoted 137 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup header is limited to around 32KB.
- Restructure the secdata section. The signer is now a null-terminated string. The type of distro_version changes to u32 in case the distro uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28 ++++++++++++++++++++++++++++
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +28 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
         If unsure, say N.
 
+config SIGNER_NAME
+     string "Signer name"
+     default ""
+     ---help---
+        This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+     int "Distribution version"
+     default 0
+     range 0 4294967295
+     ---help---
+       This option specifies the distribution version which this
+       kernel belongs to.
+
+config SECURITY_VERSION
+     int "Security version"
+     default 0
+     range 0 65535
+     ---help---
+        The security version is the version defined by the distribution
+        to indicate the severe security fixes. The bootloader can maintain
+        a list of the security versions of the current kernels. After
+        fixing a severe vulnerability in the kernel, the distribution can
+        increase the security version to notify the bootloader to update
+        the list. When booting a kernel with a lower security version,
+        the bootloader warns the user to avoid loading a vulnerable kernel
+        accidentally.
+
 config SECCOMP
      def_bool y
      prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +13 -1
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
      # Part 2 of the header, from the old setup.S
 
              .ascii  "HdrS"          # header signature
-             .word   0x020d          # header version number (>= 0x0105)
+             .word   0x020e          # header version number (>= 0x0105)
                                      # or else old loadlin-1.5 will fail)
              .globl realmode_swtch
 realmode_swtch:      .word   0, 0            # default_switch, SETUPSEG
@@ -552,6 +552,7 @@ pref_address:             .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 
 init_size:           .long INIT_SIZE         # kernel initialization size
 handover_offset:     .long 0                 # Filled in by build.c
+secdata_offset:              .word secdata_start
 
 # End of setup header #####################################################
 
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
      .byte   7
      .string "No setup signature found...\n"
+
+     .section ".secdata", "a"
+secdata_start:
+header_length:
+     .word   signer - secdata_start
+distro_version:
+     .long   CONFIG_DISTRO_VERSION
+security_version:
+     .word   CONFIG_SECURITY_VERSION
+signer:
+     .string CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
      .entrytext      : { *(.entrytext) }
      .inittext       : { *(.inittext) }
      .initdata       : { *(.initdata) }
+     .secdata        : { *(.secdata) }
      __end_init = .;
 
      .text           : { *(.text) }
arch/x86/boot/tools/build.c +0 -1
index 0702d2531bc7..a629d6b615cf 100644
@@ -287,7 +287,6 @@ static inline int reserve_pecoff_reloc_section(int c)
 }
 #endif /* CONFIG_EFI_STUB */
 
-
 /*
  * Parse zoffset.h and find the entry points. We could just #include zoffset.h
  * but that would mean tools/build would have to be rebuilt every time. It's
arch/x86/include/uapi/asm/bootparam.h +1 -1
index 07244ea16765..32ffacfaaaff 100644
@@ -85,6 +85,7 @@ struct setup_header {
      __u64   pref_address;
      __u32   init_size;
      __u32   handover_offset;
+     __u16   secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
--

2.12.2

#7 lore raw
Quoted 213 lines · Gary Lin
Quoted 3 lines · Ard Biesheuvel
Quoted 2 lines · Gary Lin
Quoted 1 line · Gary Lin

A new section, secdata, in the setup header is introduced to store

the

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or

vulnerable

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated

string.

Quoted 1 line
Quoted 1 line
Quoted 1 line

"header_length" is the size of "struct sec_hdr" and can be used as

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

offset to "signer". It also can be a kind of the "header version"

to

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version"

in

Quoted 1 line
Quoted 1 line
Quoted 1 line

the kernel build afterward. The bootloader can maintain a list of

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

security versions of the current kernels and only allows the

kernel with

Quoted 1 line
Quoted 1 line
Quoted 1 line

a higher or equal security version to boot. If the user is going

to boot

Quoted 1 line
Quoted 1 line
Quoted 1 line

a kernel with a lower security version, a warning should show to

prevent

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the security

version

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

After check the headers again, another idea came to my mind: the MS-DOS stub. It's designed to show a warning while the image is loaded in DOS(*),
but I wonder if it still matters. In the x86 linux efi header, the stub is just a 3-lines message, while arm64 completely ignores the stub.

Since there is a offset to the PE header at 0x3c, we can theoretically put any thing between 0x40 and the PE header without affecting the current settings.

HPA,

Does the MS-DOS stub raise any concern to you?

Thanks,

Gary Lin

(*)
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#ms-dos_stub__image_only_

Quoted 6 lines
Signature · 1 line
Ard.
Quoted 2 lines
Quoted 2 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup

header

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

is limited to around 32KB.
- Restructure the secdata section. The signer is now a

null-terminated

Quoted 1 line
Quoted 1 line
Quoted 1 line

string. The type of distro_version changes to u32 in case the

distro

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>
---
 arch/x86/Kconfig                      | 28

++++++++++++++++++++++++++++

Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
 arch/x86/boot/header.S                | 14 +++++++++++++-
 arch/x86/boot/setup.ld                |  1 +
 arch/x86/boot/tools/build.c           |  1 -
 arch/x86/include/uapi/asm/bootparam.h |  1 +
 5 files changed, 43 insertions(+), 2 deletions(-)
arch/x86/Kconfig +12 -0
index 5bbdef151805..2c5539518ce0 100644
@@ -1817,6 +1817,34 @@ config EFI_MIXED
 
         If unsure, say N.
 
+config SIGNER_NAME
+     string "Signer name"
+     default ""
+     ---help---
+        This option specifies who signs or releases this kernel.
+
+config DISTRO_VERSION
+     int "Distribution version"
+     default 0
+     range 0 4294967295
+     ---help---
+       This option specifies the distribution version which this
Quoted 8 lines
Quoted 8 lines

arch/x86/Kconfig config EFI_MIXED

Quoted 8 lines
arch/x86/Kconfig +8 -0
+       kernel belongs to.
+
+config SECURITY_VERSION
+     int "Security version"
+     default 0
+     range 0 65535
+     ---help---
+        The security version is the version defined by the

distribution

Quoted 1 line
Quoted 1 line

arch/x86/Kconfig config EFI_MIXED · line 1840

Quoted 1 line
arch/x86/Kconfig +1 -0
+        to indicate the severe security fixes. The bootloader can

maintain

Quoted 1 line
Quoted 1 line

arch/x86/Kconfig config EFI_MIXED · line 1841

Quoted 1 line
arch/x86/Kconfig +1 -0
+        a list of the security versions of the current kernels.

After

Quoted 1 line
Quoted 1 line

arch/x86/Kconfig config EFI_MIXED · line 1842

Quoted 1 line
arch/x86/Kconfig +1 -0
+        fixing a severe vulnerability in the kernel, the

distribution can

Quoted 1 line
Quoted 1 line

arch/x86/Kconfig config EFI_MIXED · line 1843

Quoted 1 line
arch/x86/Kconfig +1 -0
+        increase the security version to notify the bootloader to

update

Quoted 1 line
Quoted 1 line

arch/x86/Kconfig config EFI_MIXED · line 1844

Quoted 1 line
arch/x86/Kconfig +1 -0
+        the list. When booting a kernel with a lower security

version,

Quoted 1 line
Quoted 1 line

arch/x86/Kconfig config EFI_MIXED · line 1845

Quoted 1 line
arch/x86/Kconfig +1 -0
+        the bootloader warns the user to avoid loading a

vulnerable kernel

Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
arch/x86/Kconfig +2 -0
+        accidentally.
+
 config SECCOMP
      def_bool y
      prompt "Enable seccomp to safely compute untrusted bytecode"
arch/x86/boot/header.S +0 -0
index 3dd5be33aaa7..37683caf1668 100644
@@ -301,7 +301,7 @@ _start:
      # Part 2 of the header, from the old setup.S
 
Quoted 2 lines
Quoted 2 lines

arch/x86/boot/header.S _start: · line 304

Quoted 2 lines
arch/x86/boot/header.S +0 -1
              .ascii  "HdrS"          # header signature
-             .word   0x020d          # header version number (>=

0x0105)

Quoted 1 line
Quoted 1 line

arch/x86/boot/header.S _start: · line 304

Quoted 1 line
arch/x86/boot/header.S +1 -0
+             .word   0x020e          # header version number (>=

0x0105)

Quoted 1 line
Quoted 1 line

arch/x86/boot/header.S _start: · line 305

Quoted 1 line
arch/x86/boot/header.S +0 -0
                                      # or else old loadlin-1.5

will fail)

Quoted 2 lines
Quoted 2 lines

arch/x86/boot/header.S _start: · line 307

Quoted 2 lines
arch/x86/boot/header.S +0 -0
              .globl realmode_swtch
 realmode_swtch:      .word   0, 0            # default_switch,

SETUPSEG

Quoted 1 line
Quoted 1 line

arch/x86/boot/header.S pref_address: .quad

Quoted 1 line
arch/x86/boot/header.S +0 -0
@@ -552,6 +552,7 @@ pref_address:             .quad

LOAD_PHYSICAL_ADDR # preferred load addr

Quoted 2 lines
Quoted 2 lines

arch/x86/boot/header.S pref_address: .quad · line 552

Quoted 2 lines
arch/x86/boot/header.S +0 -0
 init_size:           .long INIT_SIZE         # kernel

initialization size

Quoted 1 line
Quoted 1 line

arch/x86/boot/header.S pref_address: .quad · line 553

Quoted 1 line
arch/x86/boot/header.S +0 -0
 handover_offset:     .long 0                 # Filled in by

build.c

Quoted 3 lines
Quoted 3 lines

arch/x86/boot/header.S pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr

Quoted 3 lines
arch/x86/boot/header.S +1 -0
+secdata_offset:              .word secdata_start
 
 # End of setup header

#####################################################

Quoted 27 lines
Quoted 27 lines
Quoted 27 lines
arch/x86/boot/header.S +11 -0
@@ -629,3 +630,14 @@ die:
 setup_corrupt:
      .byte   7
      .string "No setup signature found...\n"
+
+     .section ".secdata", "a"
+secdata_start:
+header_length:
+     .word   signer - secdata_start
+distro_version:
+     .long   CONFIG_DISTRO_VERSION
+security_version:
+     .word   CONFIG_SECURITY_VERSION
+signer:
+     .string CONFIG_SIGNER_NAME
arch/x86/boot/setup.ld +1 -0
index 96a6c7563538..43ddbaabaf7a 100644
@@ -18,6 +18,7 @@ SECTIONS
      .entrytext      : { *(.entrytext) }
      .inittext       : { *(.inittext) }
      .initdata       : { *(.initdata) }
+     .secdata        : { *(.secdata) }
      __end_init = .;
 
Quoted 2 lines
Quoted 2 lines

Review

Quoted 2 lines
arch/x86/boot/setup.ld +0 -0
      .text           : { *(.text) }
(quoted diff) +0 -0

b/arch/x86/boot/tools/build.c

Quoted 4 lines
Quoted 4 lines

arch/x86/boot/tools/build.c static inline int

Quoted 4 lines

index 0702d2531bc7..a629d6b615cf 100644

arch/x86/boot/tools/build.c +0 -0
@@ -287,7 +287,6 @@ static inline int

reserve_pecoff_reloc_section(int c)

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
arch/x86/boot/tools/build.c +0 -0
 }
 #endif /* CONFIG_EFI_STUB */
 
Quoted 23 lines
Quoted 3 lines
Quoted 3 lines

arch/x86/boot/tools/build.c static inline int reserve_pecoff_reloc_section(int c)

Quoted 3 lines
arch/x86/boot/tools/build.c +0 -1
-
 /*
  * Parse zoffset.h and find the entry points. We could just

#include zoffset.h

Quoted 1 line
Quoted 1 line

arch/x86/boot/tools/build.c static inline int · line 292

Quoted 1 line
arch/x86/boot/tools/build.c +0 -0
  * but that would mean tools/build would have to be rebuilt every

time. It's

Quoted 1 line
Quoted 1 line

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/x86/include/uapi/asm/bootparam.h

Quoted 15 lines
Quoted 14 lines
Quoted 14 lines

index 07244ea16765..32ffacfaaaff 100644

arch/x86/include/uapi/asm/bootparam.h +1 -1
@@ -85,6 +85,7 @@ struct setup_header {
      __u64   pref_address;
      __u32   init_size;
      __u32   handover_offset;
+     __u16   secdata_offset;
 } __attribute__((packed));
 
 struct sys_desc_table {
--

2.12.2

I really don't think that is a good idea. I would much rather keep this in a space we fully own.

Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
author
#8 lore raw
Quoted 94 lines · On Thu, Sep 07, 2017 at 02:16:21PM -0700, [email protected] wrote:
Quoted 93 lines · Gary Lin
Quoted 3 lines · Ard Biesheuvel
Quoted 2 lines · Gary Lin
Quoted 1 line · Gary Lin

A new section, secdata, in the setup header is introduced to store

the

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or

vulnerable

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

It consists of a fixed size structure and a null-terminated

string.

Quoted 1 line
Quoted 1 line
Quoted 1 line

"header_length" is the size of "struct sec_hdr" and can be used as

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

offset to "signer". It also can be a kind of the "header version"

to

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

detect if any new member is introduced.

The kernel packager of the distribution can put the distro name in "signer" and the distro version in "distro_version". When a severe vulnerability is fixed, the packager increases "security_version"

in

Quoted 1 line
Quoted 1 line
Quoted 1 line

the kernel build afterward. The bootloader can maintain a list of

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

security versions of the current kernels and only allows the

kernel with

Quoted 1 line
Quoted 1 line
Quoted 1 line

a higher or equal security version to boot. If the user is going

to boot

Quoted 1 line
Quoted 1 line
Quoted 1 line

a kernel with a lower security version, a warning should show to

prevent

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the security

version

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have a generic solution instead.

After check the headers again, another idea came to my mind: the MS-DOS stub. It's designed to show a warning while the image is loaded in DOS(*),
but I wonder if it still matters. In the x86 linux efi header, the stub is just a 3-lines message, while arm64 completely ignores the stub.

Since there is a offset to the PE header at 0x3c, we can theoretically put any thing between 0x40 and the PE header without affecting the current settings.

HPA,

Does the MS-DOS stub raise any concern to you?

Thanks,

Gary Lin

(*)
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#ms-dos_stub__image_only_

Quoted 6 lines
Signature · 1 line
Ard.
Quoted 2 lines
Quoted 2 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the setup

header

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

is limited to around 32KB.
- Restructure the secdata section. The signer is now a

null-terminated

Quoted 1 line
Quoted 1 line
Quoted 1 line

string. The type of distro_version changes to u32 in case the

distro

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>

---

[snip]

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Quoted 3 lines

--
2.12.2

I really don't think that is a good idea. I would much rather keep this in a space we fully own.

Fine. I'll find another place for ARM64 (probably append the structure right after the PE-header and denote the 2-byte offset in the reserved fields in the first 64 bytes header).

Thanks,

Gary Lin

#9 lore raw
Quoted 118 lines · Gary Lin
Quoted 5 lines · On Thu, Sep 07, 2017 at 02:16:21PM -0700, [email protected] wrote:
Quoted 4 lines · Gary Lin
Quoted 3 lines · Ard Biesheuvel
Quoted 2 lines · Gary Lin
Quoted 1 line · Gary Lin

A new section, secdata, in the setup header is introduced to

store

Quoted 13 lines
Quoted 13 lines

the

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or

vulnerable

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

Quoted 3 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line

It consists of a fixed size structure and a null-terminated

string.

Quoted 1 line
Quoted 1 line
Quoted 1 line

"header_length" is the size of "struct sec_hdr" and can be used

as

Quoted 2 lines
Quoted 2 lines

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

offset to "signer". It also can be a kind of the "header

version"

Quoted 4 lines
Quoted 4 lines

to

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

detect if any new member is introduced.

The kernel packager of the distribution can put the distro name

in

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"signer" and the distro version in "distro_version". When a

severe

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

vulnerability is fixed, the packager increases

"security_version"

Quoted 2 lines
Quoted 2 lines

in

Quoted 1 line
Quoted 1 line
Quoted 1 line

the kernel build afterward. The bootloader can maintain a list

of

Quoted 4 lines
Quoted 4 lines

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

security versions of the current kernels and only allows the

kernel with

Quoted 1 line
Quoted 1 line
Quoted 1 line

a higher or equal security version to boot. If the user is

going

Quoted 2 lines
Quoted 2 lines

to boot

Quoted 1 line
Quoted 1 line
Quoted 1 line

a kernel with a lower security version, a warning should show

to

Quoted 4 lines
Quoted 4 lines

prevent

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the

security

Quoted 7 lines
Quoted 7 lines

version

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have

a

Quoted 3 lines
Quoted 3 lines
Quoted 2 lines

generic solution instead.

After check the headers again, another idea came to my mind: the

MS-DOS

Quoted 3 lines
Quoted 3 lines

stub. It's designed to show a warning while the image is loaded in DOS(*),
but I wonder if it still matters. In the x86 linux efi header, the

stub

Quoted 3 lines
Quoted 3 lines

is just a 3-lines message, while arm64 completely ignores the stub.

Since there is a offset to the PE header at 0x3c, we can

theoretically

Quoted 7 lines
Quoted 7 lines

put any thing between 0x40 and the PE header without affecting the current settings.

HPA,

Does the MS-DOS stub raise any concern to you?

Quoted 14 lines
Quoted 5 lines

Thanks,

Gary Lin

(*)

https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#ms-dos_stub__image_only_

Quoted 7 lines
Quoted 7 lines
Signature · 2 lines
-- 
Ard.
Quoted 2 lines
Quoted 2 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the

setup

Quoted 17 lines
Quoted 17 lines

header

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

is limited to around 32KB.
- Restructure the secdata section. The signer is now a

null-terminated

Quoted 1 line
Quoted 1 line
Quoted 1 line

string. The type of distro_version changes to u32 in case the

distro

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>

---

[snip]

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Quoted 3 lines

--
2.12.2

I really don't think that is a good idea. I would much rather keep

Quoted 8 lines

this in a space we fully own.
Fine. I'll find another place for ARM64 (probably append the structure right after the PE-header and denote the 2-byte offset in the reserved fields in the first 64 bytes header).

Thanks,

Gary Lin

Another "safe" option would be to put it in a COFF segment; then it would be system-independent.

Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse my brevity.
author
#10 lore raw
Quoted 124 lines · On Fri, Sep 08, 2017 at 01:59:00PM -0700, [email protected] wrote:
Quoted 123 lines · Gary Lin
Quoted 5 lines · On Thu, Sep 07, 2017 at 02:16:21PM -0700, [email protected] wrote:
Quoted 4 lines · Gary Lin
Quoted 3 lines · Ard Biesheuvel
Quoted 2 lines · Gary Lin
Quoted 1 line · Gary Lin

A new section, secdata, in the setup header is introduced to

store

Quoted 13 lines
Quoted 13 lines

the

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or

vulnerable

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

Quoted 3 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line

It consists of a fixed size structure and a null-terminated

string.

Quoted 1 line
Quoted 1 line
Quoted 1 line

"header_length" is the size of "struct sec_hdr" and can be used

as

Quoted 2 lines
Quoted 2 lines

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

offset to "signer". It also can be a kind of the "header

version"

Quoted 4 lines
Quoted 4 lines

to

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

detect if any new member is introduced.

The kernel packager of the distribution can put the distro name

in

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"signer" and the distro version in "distro_version". When a

severe

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

vulnerability is fixed, the packager increases

"security_version"

Quoted 2 lines
Quoted 2 lines

in

Quoted 1 line
Quoted 1 line
Quoted 1 line

the kernel build afterward. The bootloader can maintain a list

of

Quoted 4 lines
Quoted 4 lines

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

security versions of the current kernels and only allows the

kernel with

Quoted 1 line
Quoted 1 line
Quoted 1 line

a higher or equal security version to boot. If the user is

going

Quoted 2 lines
Quoted 2 lines

to boot

Quoted 1 line
Quoted 1 line
Quoted 1 line

a kernel with a lower security version, a warning should show

to

Quoted 4 lines
Quoted 4 lines

prevent

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the

security

Quoted 7 lines
Quoted 7 lines

version

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have

a

Quoted 3 lines
Quoted 3 lines
Quoted 2 lines

generic solution instead.

After check the headers again, another idea came to my mind: the

MS-DOS

Quoted 3 lines
Quoted 3 lines

stub. It's designed to show a warning while the image is loaded in DOS(*),
but I wonder if it still matters. In the x86 linux efi header, the

stub

Quoted 3 lines
Quoted 3 lines

is just a 3-lines message, while arm64 completely ignores the stub.

Since there is a offset to the PE header at 0x3c, we can

theoretically

Quoted 7 lines
Quoted 7 lines

put any thing between 0x40 and the PE header without affecting the current settings.

HPA,

Does the MS-DOS stub raise any concern to you?

Quoted 14 lines
Quoted 5 lines

Thanks,

Gary Lin

(*)

https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#ms-dos_stub__image_only_

Quoted 7 lines
Quoted 7 lines
Signature · 2 lines
-- 
Ard.
Quoted 2 lines
Quoted 2 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the

setup

Quoted 17 lines
Quoted 17 lines

header

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

is limited to around 32KB.
- Restructure the secdata section. The signer is now a

null-terminated

Quoted 1 line
Quoted 1 line
Quoted 1 line

string. The type of distro_version changes to u32 in case the

distro

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>

---

[snip]

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Quoted 3 lines

--
2.12.2

I really don't think that is a good idea. I would much rather keep

this in a space we fully own.
Fine. I'll find another place for ARM64 (probably append the structure right after the PE-header and denote the 2-byte offset in the reserved fields in the first 64 bytes header).

Quoted 5 lines
Quoted 3 lines

Thanks,

Gary Lin

Another "safe" option would be to put it in a COFF segment; then it would be system-independent.

Creating a new COFF section looks promising. Thanks for pointing the direction.

Gary Lin

author
#11 lore raw
In reply to [email protected]
Quoted 124 lines · On Fri, Sep 08, 2017 at 01:59:00PM -0700, [email protected] wrote:
Quoted 123 lines · Gary Lin
Quoted 5 lines · On Thu, Sep 07, 2017 at 02:16:21PM -0700, [email protected] wrote:
Quoted 4 lines · Gary Lin
Quoted 3 lines · Ard Biesheuvel
Quoted 2 lines · Gary Lin
Quoted 1 line · Gary Lin

A new section, secdata, in the setup header is introduced to

store

Quoted 13 lines
Quoted 13 lines

the

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

distro-specific security version which is designed to help the bootloader to warn the user when loading a less secure or

vulnerable

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

kernel. The secdata section can be presented as the following:

struct sec_hdr {
      __u16 header_length;
      __u32 distro_version;
      __u16 security_version;
} __attribute__((packed));

char *signer;

Quoted 3 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line

It consists of a fixed size structure and a null-terminated

string.

Quoted 1 line
Quoted 1 line
Quoted 1 line

"header_length" is the size of "struct sec_hdr" and can be used

as

Quoted 2 lines
Quoted 2 lines

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

offset to "signer". It also can be a kind of the "header

version"

Quoted 4 lines
Quoted 4 lines

to

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

detect if any new member is introduced.

The kernel packager of the distribution can put the distro name

in

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"signer" and the distro version in "distro_version". When a

severe

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

vulnerability is fixed, the packager increases

"security_version"

Quoted 2 lines
Quoted 2 lines

in

Quoted 1 line
Quoted 1 line
Quoted 1 line

the kernel build afterward. The bootloader can maintain a list

of

Quoted 4 lines
Quoted 4 lines

the

Quoted 1 line
Quoted 1 line
Quoted 1 line

security versions of the current kernels and only allows the

kernel with

Quoted 1 line
Quoted 1 line
Quoted 1 line

a higher or equal security version to boot. If the user is

going

Quoted 2 lines
Quoted 2 lines

to boot

Quoted 1 line
Quoted 1 line
Quoted 1 line

a kernel with a lower security version, a warning should show

to

Quoted 4 lines
Quoted 4 lines

prevent

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

the user from loading a vulnerable kernel accidentally.

Enabling UEFI Secure Boot is recommended when using the

security

Quoted 7 lines
Quoted 7 lines

version

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

or the attacker may alter the security version stealthily.

Any comment?

This is now entirely x86-specific. My preference would be to have

a

Quoted 3 lines
Quoted 3 lines
Quoted 2 lines

generic solution instead.

After check the headers again, another idea came to my mind: the

MS-DOS

Quoted 3 lines
Quoted 3 lines

stub. It's designed to show a warning while the image is loaded in DOS(*),
but I wonder if it still matters. In the x86 linux efi header, the

stub

Quoted 3 lines
Quoted 3 lines

is just a 3-lines message, while arm64 completely ignores the stub.

Since there is a offset to the PE header at 0x3c, we can

theoretically

Quoted 7 lines
Quoted 7 lines

put any thing between 0x40 and the PE header without affecting the current settings.

HPA,

Does the MS-DOS stub raise any concern to you?

Quoted 14 lines
Quoted 5 lines

Thanks,

Gary Lin

(*)

https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms680547(v=vs.85).aspx#ms-dos_stub__image_only_

Quoted 7 lines
Quoted 7 lines
Signature · 2 lines
-- 
Ard.
Quoted 2 lines
Quoted 2 lines

v2:
- Decrease the size of secdata_offset to 2 bytes since the

setup

Quoted 17 lines
Quoted 17 lines

header

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

is limited to around 32KB.
- Restructure the secdata section. The signer is now a

null-terminated

Quoted 1 line
Quoted 1 line
Quoted 1 line

string. The type of distro_version changes to u32 in case the

distro

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

uses a long version.
- Modify the Kconfig names and add help.
- Remove the signer name hack in build.c.

Cc Ard Biesheuvel <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Joey Lee <[email protected]>

---

[snip]

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Quoted 3 lines

--
2.12.2

I really don't think that is a good idea. I would much rather keep

this in a space we fully own.
Fine. I'll find another place for ARM64 (probably append the structure right after the PE-header and denote the 2-byte offset in the reserved fields in the first 64 bytes header).

Quoted 5 lines
Quoted 3 lines

Thanks,

Gary Lin

Another "safe" option would be to put it in a COFF segment; then it would be system-independent.

Hi HPA,

Sorry for the late reply, I was travelling last two weeks.

In the beginning, I thought a new coff section was feasible. However, it seems not possible for x86-64.

Although the section itself can be anywhere, we have to register an entry in the section table in the coff optional header. For the x86-64 kernel image, the section table starts at 0x13b while every entry takes 40 bytes. Currently, there are 4 sections: .setup, .reloc, .text, and .bss, so the new entry should be added at (0x13b + 0x24 * 4) = 0x1db and ended at 0x1ff. Unfortunately, the x86 boot protocol requires the setup header starts at 0x1f1, so there is no room for a new entry in the coff section table :-(

Gary Lin