aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
diff options
context:
space:
mode:
authorBaoquan He <bhe@redhat.com>2016-04-20 16:55:42 -0400
committerIngo Molnar <mingo@kernel.org>2016-04-22 04:00:50 -0400
commit4252db10559fc3d1efc1e43613254fdd220b014b (patch)
tree68696b65de2c52581467b7c5bc6d0a74345fb4b4 /arch/x86/boot
parent9016875df408fc5db6a94a3c5f5f5503c916cf81 (diff)
x86/KASLR: Update description for decompressor worst case size
The comment that describes the analysis for the size of the decompressor code only took gzip into account (there are currently 6 other decompressors that could be used). The actual z_extract_offset calculation in code was already handling the correct maximum size, but this documentation hadn't been updated. This updates the documentation, fixes several typos, moves the comment to header.S, updates references, and adds a note at the end of the decompressor include list to remind us about updating the comment in the future. (Instead of moving the comment to mkpiggy.c, where the calculation is currently happening, it is being moved to header.S because the calculations in mkpiggy.c will be removed in favor of header.S calculations in a following patch, and it seemed like overkill to move the giant comment twice, especially when there's already reference to z_extract_offset in header.S.) Signed-off-by: Baoquan He <bhe@redhat.com> [ Rewrote changelog, cleaned up comment style, moved comments around. ] Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bp@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: H.J. Lu <hjl.tools@gmail.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Yinghai Lu <yinghai@kernel.org> Link: http://lkml.kernel.org/r/1461185746-8017-2-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/boot')
-rw-r--r--arch/x86/boot/compressed/kaslr.c2
-rw-r--r--arch/x86/boot/compressed/misc.c89
-rw-r--r--arch/x86/boot/header.S88
3 files changed, 97 insertions, 82 deletions
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 9c29e7885ef0..7d86c5dd8e99 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -155,7 +155,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
155 155
156 /* 156 /*
157 * Avoid the region that is unsafe to overlap during 157 * Avoid the region that is unsafe to overlap during
158 * decompression (see calculations at top of misc.c). 158 * decompression (see calculations in ../header.S).
159 */ 159 */
160 unsafe_len = (output_size >> 12) + 32768 + 18; 160 unsafe_len = (output_size >> 12) + 32768 + 18;
161 unsafe = (unsigned long)input + input_size - unsafe_len; 161 unsafe = (unsigned long)input + input_size - unsafe_len;
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index ad8c01ac2885..e96829bdb6d2 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -14,90 +14,13 @@
14#include "misc.h" 14#include "misc.h"
15#include "../string.h" 15#include "../string.h"
16 16
17/* WARNING!!
18 * This code is compiled with -fPIC and it is relocated dynamically
19 * at run time, but no relocation processing is performed.
20 * This means that it is not safe to place pointers in static structures.
21 */
22
23/* 17/*
24 * Getting to provable safe in place decompression is hard. 18 * WARNING!!
25 * Worst case behaviours need to be analyzed. 19 * This code is compiled with -fPIC and it is relocated dynamically at
26 * Background information: 20 * run time, but no relocation processing is performed. This means that
27 * 21 * it is not safe to place pointers in static structures.
28 * The file layout is:
29 * magic[2]
30 * method[1]
31 * flags[1]
32 * timestamp[4]
33 * extraflags[1]
34 * os[1]
35 * compressed data blocks[N]
36 * crc[4] orig_len[4]
37 *
38 * resulting in 18 bytes of non compressed data overhead.
39 *
40 * Files divided into blocks
41 * 1 bit (last block flag)
42 * 2 bits (block type)
43 *
44 * 1 block occurs every 32K -1 bytes or when there 50% compression
45 * has been achieved. The smallest block type encoding is always used.
46 *
47 * stored:
48 * 32 bits length in bytes.
49 *
50 * fixed:
51 * magic fixed tree.
52 * symbols.
53 *
54 * dynamic:
55 * dynamic tree encoding.
56 * symbols.
57 *
58 *
59 * The buffer for decompression in place is the length of the
60 * uncompressed data, plus a small amount extra to keep the algorithm safe.
61 * The compressed data is placed at the end of the buffer. The output
62 * pointer is placed at the start of the buffer and the input pointer
63 * is placed where the compressed data starts. Problems will occur
64 * when the output pointer overruns the input pointer.
65 *
66 * The output pointer can only overrun the input pointer if the input
67 * pointer is moving faster than the output pointer. A condition only
68 * triggered by data whose compressed form is larger than the uncompressed
69 * form.
70 *
71 * The worst case at the block level is a growth of the compressed data
72 * of 5 bytes per 32767 bytes.
73 *
74 * The worst case internal to a compressed block is very hard to figure.
75 * The worst case can at least be boundined by having one bit that represents
76 * 32764 bytes and then all of the rest of the bytes representing the very
77 * very last byte.
78 *
79 * All of which is enough to compute an amount of extra data that is required
80 * to be safe. To avoid problems at the block level allocating 5 extra bytes
81 * per 32767 bytes of data is sufficient. To avoind problems internal to a
82 * block adding an extra 32767 bytes (the worst case uncompressed block size)
83 * is sufficient, to ensure that in the worst case the decompressed data for
84 * block will stop the byte before the compressed data for a block begins.
85 * To avoid problems with the compressed data's meta information an extra 18
86 * bytes are needed. Leading to the formula:
87 *
88 * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
89 *
90 * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
91 * Adding 32768 instead of 32767 just makes for round numbers.
92 * Adding the decompressor_size is necessary as it musht live after all
93 * of the data as well. Last I measured the decompressor is about 14K.
94 * 10K of actual data and 4K of bss.
95 *
96 */ 22 */
97 23
98/*
99 * gzip declarations
100 */
101#define STATIC static 24#define STATIC static
102 25
103#undef memcpy 26#undef memcpy
@@ -148,6 +71,10 @@ static int lines, cols;
148#ifdef CONFIG_KERNEL_LZ4 71#ifdef CONFIG_KERNEL_LZ4
149#include "../../../../lib/decompress_unlz4.c" 72#include "../../../../lib/decompress_unlz4.c"
150#endif 73#endif
74/*
75 * NOTE: When adding a new decompressor, please update the analysis in
76 * ../header.S.
77 */
151 78
152static void scroll(void) 79static void scroll(void)
153{ 80{
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 6236b9ec4b76..fd85b9e4e953 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -440,6 +440,94 @@ setup_data: .quad 0 # 64-bit physical pointer to
440 440
441pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr 441pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
442 442
443#
444# Getting to provably safe in-place decompression is hard. Worst case
445# behaviours need to be analyzed. Here let's take the decompression of
446# a gzip-compressed kernel as example, to illustrate it:
447#
448# The file layout of gzip compressed kernel is:
449#
450# magic[2]
451# method[1]
452# flags[1]
453# timestamp[4]
454# extraflags[1]
455# os[1]
456# compressed data blocks[N]
457# crc[4] orig_len[4]
458#
459# ... resulting in +18 bytes overhead of uncompressed data.
460#
461# (For more information, please refer to RFC 1951 and RFC 1952.)
462#
463# Files divided into blocks
464# 1 bit (last block flag)
465# 2 bits (block type)
466#
467# 1 block occurs every 32K -1 bytes or when there 50% compression
468# has been achieved. The smallest block type encoding is always used.
469#
470# stored:
471# 32 bits length in bytes.
472#
473# fixed:
474# magic fixed tree.
475# symbols.
476#
477# dynamic:
478# dynamic tree encoding.
479# symbols.
480#
481#
482# The buffer for decompression in place is the length of the uncompressed
483# data, plus a small amount extra to keep the algorithm safe. The
484# compressed data is placed at the end of the buffer. The output pointer
485# is placed at the start of the buffer and the input pointer is placed
486# where the compressed data starts. Problems will occur when the output
487# pointer overruns the input pointer.
488#
489# The output pointer can only overrun the input pointer if the input
490# pointer is moving faster than the output pointer. A condition only
491# triggered by data whose compressed form is larger than the uncompressed
492# form.
493#
494# The worst case at the block level is a growth of the compressed data
495# of 5 bytes per 32767 bytes.
496#
497# The worst case internal to a compressed block is very hard to figure.
498# The worst case can at least be bounded by having one bit that represents
499# 32764 bytes and then all of the rest of the bytes representing the very
500# very last byte.
501#
502# All of which is enough to compute an amount of extra data that is required
503# to be safe. To avoid problems at the block level allocating 5 extra bytes
504# per 32767 bytes of data is sufficient. To avoid problems internal to a
505# block adding an extra 32767 bytes (the worst case uncompressed block size)
506# is sufficient, to ensure that in the worst case the decompressed data for
507# block will stop the byte before the compressed data for a block begins.
508# To avoid problems with the compressed data's meta information an extra 18
509# bytes are needed. Leading to the formula:
510#
511# extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size
512#
513# Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
514# Adding 32768 instead of 32767 just makes for round numbers.
515# Adding the decompressor_size is necessary as it musht live after all
516# of the data as well. Last I measured the decompressor is about 14K.
517# 10K of actual data and 4K of bss.
518#
519# Above analysis is for decompressing gzip compressed kernel only. Up to
520# now 6 different decompressor are supported all together. And among them
521# xz stores data in chunks and has maximum chunk of 64K. Hence safety
522# margin should be updated to cover all decompressors so that we don't
523# need to deal with each of them separately. Please check
524# the description in lib/decompressor_xxx.c for specific information.
525#
526# extra_bytes = (uncompressed_size >> 12) + 65536 + 128
527#
528# Note that this calculation, which results in z_extract_offset (below),
529# is currently generated in compressed/mkpiggy.c
530
443#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset) 531#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
444#define VO_INIT_SIZE (VO__end - VO__text) 532#define VO_INIT_SIZE (VO__end - VO__text)
445#if ZO_INIT_SIZE > VO_INIT_SIZE 533#if ZO_INIT_SIZE > VO_INIT_SIZE