Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1350430 > unrolled thread

[PATCH v3 00/19] x86, boot: kaslr cleanup and 64bit kaslr support

Started byBaoquan He <bhe@redhat.com>
First post2016-03-04 17:30 +0100
Last post2016-03-05 12:40 +0100
Articles 3 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH v3 00/19] x86, boot: kaslr cleanup and 64bit kaslr support Baoquan He <bhe@redhat.com> - 2016-03-04 17:30 +0100
    [PATCH v3 03/19] x86, boot: Move z_extract_offset calculation to header.S Baoquan He <bhe@redhat.com> - 2016-03-04 17:30 +0100
    Re: [PATCH v3 00/19] x86, boot: kaslr cleanup and 64bit kaslr support Baoquan He <bhe@redhat.com> - 2016-03-05 12:40 +0100

#1350430 — [PATCH v3 00/19] x86, boot: kaslr cleanup and 64bit kaslr support

FromBaoquan He <bhe@redhat.com>
Date2016-03-04 17:30 +0100
Subject[PATCH v3 00/19] x86, boot: kaslr cleanup and 64bit kaslr support
Message-ID<r90M1-Y1-7@gated-at.bofh.it>
***Background:
Previously a bug is reported that kdump didn't work when kaslr is enabled. During
discussing that bug fix, we found current kaslr has a limilation that it can
only randomize in 1GB region.

This is because in curent kaslr implementaion only physical address of kernel
loading is randomized. Then calculate the delta of physical address where
vmlinux was linked to load and where it is finally loaded. If delta is not
equal to 0, namely there's a new physical address where kernel is actually
decompressed, relocation handling need be done. Then delta is added to offset
of kernel symbol relocation, this makes the address of kernel text mapping move
delta long. Though in principle kernel can be randomized to any physical address,
kernel text mapping address space is limited and only 1G, namely as follows on
x86_64:
	[0xffffffff80000000, 0xffffffffc0000000)

In one word, kernel text physical address and virtual address randomization is
coupled. This causes the limitation.

Then hpa and Vivek suggested we should change this. To decouple the physical
address and virtual address randomization of kernel text and let them work
separately. Then kernel text physical address can be randomized in region
[16M, 64T), and kernel text virtual address can be randomized in region
[0xffffffff80000000, 0xffffffffc0000000).

***Problems we need solved:
  - For kernel boot from startup_32 case, only 0~4G identity mapping is built.
    If kernel will be randomly put anywhere from 16M to 64T at most, the price
    to build all region of identity mapping is too high. We need build the
    identity mapping on demand, not covering all physical address space.

  - Decouple the physical address and virtual address randomization of kernel
    text and let them work separately.

***Parts:
   - The 1st part is Yinghai's identity mapping building on demand patches.
     This is used to solve the first problem mentioned above.
     (Patch 09-10/19)
   - The 2nd part is decoupling the physical address and virtual address
     randomization of kernel text and letting them work separately patches
     based on Yinghai's ident mapping patches.
     (Patch 12-19/19)
   - The 3rd part is some clean up patches which Yinghai found when he reviewed
     my patches and the related code around.
     (Patch 01-08/19)

***Patch status:
This patchset went through several rounds of review.

   - The first round can be found here:
	https://lwn.net/Articles/637115/

   - In 2nd round Yinghai made a big patchset including this kaslr fix and another
     setup_data related fix. The link is here:
      http://lists-archives.com/linux-kernel/28346903-x86-updated-patches-for-kaslr-and-setup_data-etc-for-v4-3.html
     You can get the code from Yinghai's git branch:
     git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-x86-v4.3-next

   - This post is the 3rd round. It only takes care of the kaslr related patches.
     For reviewers it's better to discuss only one issue in one thread.
       * I take off one patch as follows from Yinghai's because I think it's unnecessay. 
          - Patch 05/19 x86, kaslr: rename output_size to output_run_size
         output_size is enough to represen the value:
		output_len > run_size ? output_len : run_size
      
       * I add Patch 04/19, it's a comment update patch. For other patches, I just
         adjust patch log and do several places of change comparing with 2nd round.
         Please check the change log under patch log of each patch for details.

       * I adjust sequence of several patches to make review easier. It doesn't
         affect codes.

   - You can also get this patchset from my github:
     https://github.com/baoquan-he/linux.git kaslr-above-4G

Any comments and suggestions are welcome. Code changes, code comments, patch logs,
anything you think it's unclear, please add your comment.

Baoquan He (8):
  x86, kaskr: Update the description for decompressor worst case
  x86, kaslr: Fix a bug that relocation can not be handled when kernel
    is loaded above 2G
  x86, kaslr: Introduce struct slot_area to manage randomization slot
    info
  x86, kaslr: Add two functions which will be used later
  x86, kaslr: Introduce fetch_random_virt_offset to randomize the kernel
    text mapping address
  x86, kaslr: Randomize physical and virtual address of kernel
    separately
  x86, kaslr: Add support of kernel physical address randomization above
    4G
  x86, kaslr: Remove useless codes

Yinghai Lu (11):
  x86, kaslr: Remove not needed parameter for choose_kernel_location
  x86, boot: Move compressed kernel to end of buffer before
    decompressing
  x86, boot: Move z_extract_offset calculation to header.S
  x86, boot: Fix run_size calculation
  x86, kaslr: Clean up useless code related to run_size.
  x86, kaslr: Get correct max_addr for relocs pointer
  x86, kaslr: Consolidate mem_avoid array filling
  x86, boot: Split kernel_ident_mapping_init to another file
  x86, 64bit: Set ident_mapping for kaslr
  x86, boot: Add checking for memcpy
  x86, kaslr: Allow random address to be below loaded address

 arch/x86/boot/Makefile                 |  13 +-
 arch/x86/boot/compressed/Makefile      |  19 ++-
 arch/x86/boot/compressed/aslr.c        | 258 +++++++++++++++++++++++----------
 arch/x86/boot/compressed/head_32.S     |  14 +-
 arch/x86/boot/compressed/head_64.S     |  15 +-
 arch/x86/boot/compressed/misc.c        |  94 +++++++-----
 arch/x86/boot/compressed/misc.h        |  34 +++--
 arch/x86/boot/compressed/misc_pgt.c    |  91 ++++++++++++
 arch/x86/boot/compressed/mkpiggy.c     |  28 +---
 arch/x86/boot/compressed/string.c      |  29 +++-
 arch/x86/boot/compressed/vmlinux.lds.S |   1 +
 arch/x86/boot/header.S                 |  22 ++-
 arch/x86/include/asm/boot.h            |  19 +++
 arch/x86/include/asm/page.h            |   5 +
 arch/x86/kernel/asm-offsets.c          |   1 +
 arch/x86/kernel/vmlinux.lds.S          |   1 +
 arch/x86/mm/ident_map.c                |  74 ++++++++++
 arch/x86/mm/init_64.c                  |  74 +---------
 arch/x86/tools/calc_run_size.sh        |  42 ------
 19 files changed, 543 insertions(+), 291 deletions(-)
 create mode 100644 arch/x86/boot/compressed/misc_pgt.c
 create mode 100644 arch/x86/mm/ident_map.c
 delete mode 100644 arch/x86/tools/calc_run_size.sh

-- 
2.5.0

[toc] | [next] | [standalone]


#1350431 — [PATCH v3 03/19] x86, boot: Move z_extract_offset calculation to header.S

FromBaoquan He <bhe@redhat.com>
Date2016-03-04 17:30 +0100
Subject[PATCH v3 03/19] x86, boot: Move z_extract_offset calculation to header.S
Message-ID<r90M4-Y1-67@gated-at.bofh.it>
In reply to#1350430
From: Yinghai Lu <yinghai@kernel.org>

Current z_extract_offset is calculated in boot/compressed/mkpiggy.c. The
problem is in mkpiggy.c we don't know the detail of decompressor. Then
we just get a rough z_extract_offset according to extra_bytes. As we know
extra_bytes can only promise a safety margin when decompressing. In fact
this brings some risks:

 - output+output_len could be much bigger than input+input_len. In this
   cass decompressed kernel plus relocs could overwrite decompressing
   method code even when they are running.

 - ehead of ZO could be bigger than z_extract_offset. In this case overwrite
   could happen when head code is running to move ZO to end of buffer.
   Though currently the size of head code is very small it's still a
   potential risk. Because no rule to limit the size of head code of ZO,
   it has possibility to be very big.

Now move z_extract_offset calculation to header.S, and adjust z_extract_offset
to make sure that above two cases never happen.

Besides we have made ZO always be in the end of decompressing buffer,
z_extract_offset is only used here to calculate an appropriate INIT_SIZE,
no other place need it now. So no need to put it in voffset.h.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Baoquan He <bhe@redhat.com>
---
v2->v3:
    Tune the patch log.
    Remove code comment above init_size.
    I still think extra_bytes shoule be taken as below formula to cover
    the worst case of xz.
#define ZO_z_extra_bytes ((ZO_z_output_len >> 12) + 65536 + 128)

 arch/x86/boot/Makefile             |  2 +-
 arch/x86/boot/compressed/misc.c    |  5 +----
 arch/x86/boot/compressed/mkpiggy.c | 15 +--------------
 arch/x86/boot/header.S             | 22 +++++++++++++++++++++-
 4 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index bbe1a62..bd021e5 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -87,7 +87,7 @@ targets += voffset.h
 $(obj)/voffset.h: vmlinux FORCE
 	$(call if_changed,voffset)
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index f35ad9e..a56bb5d 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -83,13 +83,10 @@
  * To avoid problems with the compressed data's meta information an extra 18
  * bytes are needed.  Leading to the formula:
  *
- * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
+ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18.
  *
  * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
  * Adding 32768 instead of 32767 just makes for round numbers.
- * Adding the decompressor_size is necessary as it musht live after all
- * of the data as well.  Last I measured the decompressor is about 14K.
- * 10K of actual data and 4K of bss.
  *
  */
 
diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c
index b980046..a613c84 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -21,8 +21,7 @@
  * ----------------------------------------------------------------------- */
 
 /*
- * Compute the desired load offset from a compressed program; outputs
- * a small assembly wrapper with the appropriate symbols defined.
+ * outputs a small assembly wrapper with the appropriate symbols defined.
  */
 
 #include <stdlib.h>
@@ -35,7 +34,6 @@ int main(int argc, char *argv[])
 {
 	uint32_t olen;
 	long ilen;
-	unsigned long offs;
 	unsigned long run_size;
 	FILE *f = NULL;
 	int retval = 1;
@@ -67,15 +65,6 @@ int main(int argc, char *argv[])
 	ilen = ftell(f);
 	olen = get_unaligned_le32(&olen);
 
-	/*
-	 * Now we have the input (compressed) and output (uncompressed)
-	 * sizes, compute the necessary decompression offset...
-	 */
-
-	offs = (olen > ilen) ? olen - ilen : 0;
-	offs += olen >> 12;	/* Add 8 bytes for each 32K block */
-	offs += 64*1024 + 128;	/* Add 64K + 128 bytes slack */
-	offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
 	run_size = atoi(argv[2]);
 
 	printf(".section \".rodata..compressed\",\"a\",@progbits\n");
@@ -83,8 +72,6 @@ int main(int argc, char *argv[])
 	printf("z_input_len = %lu\n", ilen);
 	printf(".globl z_output_len\n");
 	printf("z_output_len = %lu\n", (unsigned long)olen);
-	printf(".globl z_extract_offset\n");
-	printf("z_extract_offset = 0x%lx\n", offs);
 	printf(".globl z_run_size\n");
 	printf("z_run_size = %lu\n", run_size);
 
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 6236b9e..1c057e3 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -440,7 +440,27 @@ setup_data:		.quad 0			# 64-bit physical pointer to
 
 pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
 
-#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_extract_offset)
+/* Check arch/x86/boot/compressed/misc.c for the formula of extra_bytes*/
+#define ZO_z_extra_bytes ((ZO_z_output_len >> 12) + 65536 + 128)
+#if ZO_z_output_len > ZO_z_input_len
+#define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - ZO_z_input_len)
+#else
+#define ZO_z_extract_offset ZO_z_extra_bytes
+#endif
+
+/*
+ * extract_offset has to be bigger than ZO head section. Otherwise
+ * during head code running to move ZO to end of buffer, it will
+ * overwrite head code itself.
+ */
+#if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset
+#define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095)
+#else
+#define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095)
+#endif
+
+#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_min_extract_offset)
+
 #define VO_INIT_SIZE	(VO__end - VO__text)
 #if ZO_INIT_SIZE > VO_INIT_SIZE
 #define INIT_SIZE ZO_INIT_SIZE
-- 
2.5.0

[toc] | [prev] | [next] | [standalone]


#1350869

FromBaoquan He <bhe@redhat.com>
Date2016-03-05 12:40 +0100
Message-ID<r9iIW-5vt-1@gated-at.bofh.it>
In reply to#1350430
Forget mentioning this patchset is based on v4.5-rc6 of Linus's tree.

On 03/05/16 at 12:24am, Baoquan He wrote:
> ***Background:
> Previously a bug is reported that kdump didn't work when kaslr is enabled. During
> discussing that bug fix, we found current kaslr has a limilation that it can
> only randomize in 1GB region.
> 
> This is because in curent kaslr implementaion only physical address of kernel
> loading is randomized. Then calculate the delta of physical address where
> vmlinux was linked to load and where it is finally loaded. If delta is not
> equal to 0, namely there's a new physical address where kernel is actually
> decompressed, relocation handling need be done. Then delta is added to offset
> of kernel symbol relocation, this makes the address of kernel text mapping move
> delta long. Though in principle kernel can be randomized to any physical address,
> kernel text mapping address space is limited and only 1G, namely as follows on
> x86_64:
> 	[0xffffffff80000000, 0xffffffffc0000000)
> 
> In one word, kernel text physical address and virtual address randomization is
> coupled. This causes the limitation.
> 
> Then hpa and Vivek suggested we should change this. To decouple the physical
> address and virtual address randomization of kernel text and let them work
> separately. Then kernel text physical address can be randomized in region
> [16M, 64T), and kernel text virtual address can be randomized in region
> [0xffffffff80000000, 0xffffffffc0000000).
> 
> ***Problems we need solved:
>   - For kernel boot from startup_32 case, only 0~4G identity mapping is built.
>     If kernel will be randomly put anywhere from 16M to 64T at most, the price
>     to build all region of identity mapping is too high. We need build the
>     identity mapping on demand, not covering all physical address space.
> 
>   - Decouple the physical address and virtual address randomization of kernel
>     text and let them work separately.
> 
> ***Parts:
>    - The 1st part is Yinghai's identity mapping building on demand patches.
>      This is used to solve the first problem mentioned above.
>      (Patch 09-10/19)
>    - The 2nd part is decoupling the physical address and virtual address
>      randomization of kernel text and letting them work separately patches
>      based on Yinghai's ident mapping patches.
>      (Patch 12-19/19)
>    - The 3rd part is some clean up patches which Yinghai found when he reviewed
>      my patches and the related code around.
>      (Patch 01-08/19)
> 
> ***Patch status:
> This patchset went through several rounds of review.
> 
>    - The first round can be found here:
> 	https://lwn.net/Articles/637115/
> 
>    - In 2nd round Yinghai made a big patchset including this kaslr fix and another
>      setup_data related fix. The link is here:
>       http://lists-archives.com/linux-kernel/28346903-x86-updated-patches-for-kaslr-and-setup_data-etc-for-v4-3.html
>      You can get the code from Yinghai's git branch:
>      git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-x86-v4.3-next
> 
>    - This post is the 3rd round. It only takes care of the kaslr related patches.
>      For reviewers it's better to discuss only one issue in one thread.
>        * I take off one patch as follows from Yinghai's because I think it's unnecessay. 
>           - Patch 05/19 x86, kaslr: rename output_size to output_run_size
>          output_size is enough to represen the value:
> 		output_len > run_size ? output_len : run_size
>       
>        * I add Patch 04/19, it's a comment update patch. For other patches, I just
>          adjust patch log and do several places of change comparing with 2nd round.
>          Please check the change log under patch log of each patch for details.
> 
>        * I adjust sequence of several patches to make review easier. It doesn't
>          affect codes.
> 
>    - You can also get this patchset from my github:
>      https://github.com/baoquan-he/linux.git kaslr-above-4G
> 
> Any comments and suggestions are welcome. Code changes, code comments, patch logs,
> anything you think it's unclear, please add your comment.
> 
> Baoquan He (8):
>   x86, kaskr: Update the description for decompressor worst case
>   x86, kaslr: Fix a bug that relocation can not be handled when kernel
>     is loaded above 2G
>   x86, kaslr: Introduce struct slot_area to manage randomization slot
>     info
>   x86, kaslr: Add two functions which will be used later
>   x86, kaslr: Introduce fetch_random_virt_offset to randomize the kernel
>     text mapping address
>   x86, kaslr: Randomize physical and virtual address of kernel
>     separately
>   x86, kaslr: Add support of kernel physical address randomization above
>     4G
>   x86, kaslr: Remove useless codes
> 
> Yinghai Lu (11):
>   x86, kaslr: Remove not needed parameter for choose_kernel_location
>   x86, boot: Move compressed kernel to end of buffer before
>     decompressing
>   x86, boot: Move z_extract_offset calculation to header.S
>   x86, boot: Fix run_size calculation
>   x86, kaslr: Clean up useless code related to run_size.
>   x86, kaslr: Get correct max_addr for relocs pointer
>   x86, kaslr: Consolidate mem_avoid array filling
>   x86, boot: Split kernel_ident_mapping_init to another file
>   x86, 64bit: Set ident_mapping for kaslr
>   x86, boot: Add checking for memcpy
>   x86, kaslr: Allow random address to be below loaded address
> 
>  arch/x86/boot/Makefile                 |  13 +-
>  arch/x86/boot/compressed/Makefile      |  19 ++-
>  arch/x86/boot/compressed/aslr.c        | 258 +++++++++++++++++++++++----------
>  arch/x86/boot/compressed/head_32.S     |  14 +-
>  arch/x86/boot/compressed/head_64.S     |  15 +-
>  arch/x86/boot/compressed/misc.c        |  94 +++++++-----
>  arch/x86/boot/compressed/misc.h        |  34 +++--
>  arch/x86/boot/compressed/misc_pgt.c    |  91 ++++++++++++
>  arch/x86/boot/compressed/mkpiggy.c     |  28 +---
>  arch/x86/boot/compressed/string.c      |  29 +++-
>  arch/x86/boot/compressed/vmlinux.lds.S |   1 +
>  arch/x86/boot/header.S                 |  22 ++-
>  arch/x86/include/asm/boot.h            |  19 +++
>  arch/x86/include/asm/page.h            |   5 +
>  arch/x86/kernel/asm-offsets.c          |   1 +
>  arch/x86/kernel/vmlinux.lds.S          |   1 +
>  arch/x86/mm/ident_map.c                |  74 ++++++++++
>  arch/x86/mm/init_64.c                  |  74 +---------
>  arch/x86/tools/calc_run_size.sh        |  42 ------
>  19 files changed, 543 insertions(+), 291 deletions(-)
>  create mode 100644 arch/x86/boot/compressed/misc_pgt.c
>  create mode 100644 arch/x86/mm/ident_map.c
>  delete mode 100644 arch/x86/tools/calc_run_size.sh
> 
> -- 
> 2.5.0
> 

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web