Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1313012 > unrolled thread
| Started by | Ard Biesheuvel <ard.biesheuvel@linaro.org> |
|---|---|
| First post | 2016-01-20 10:10 +0100 |
| Last post | 2016-01-27 05:40 +0100 |
| Articles | 9 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH 0/4] support for text-relative kallsyms table Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2016-01-20 10:10 +0100
[PATCH 1/4] kallsyms: add support for relative offsets in kallsyms address table Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2016-01-20 10:10 +0100
Re: [PATCH 1/4] kallsyms: add support for relative offsets in kallsyms address table Kees Cook <keescook@chromium.org> - 2016-01-20 20:20 +0100
Re: [PATCH 0/4] support for text-relative kallsyms table Ingo Molnar <mingo@kernel.org> - 2016-01-20 11:40 +0100
Re: [PATCH 0/4] support for text-relative kallsyms table Arnd Bergmann <arnd@arndb.de> - 2016-01-20 13:00 +0100
Re: [PATCH 0/4] support for text-relative kallsyms table Rusty Russell <rusty@rustcorp.com.au> - 2016-01-21 06:20 +0100
Re: [PATCH 0/4] support for text-relative kallsyms table Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2016-01-21 07:50 +0100
Re: [PATCH 0/4] support for text-relative kallsyms table Ard Biesheuvel <ard.biesheuvel@linaro.org> - 2016-01-21 09:40 +0100
Re: [PATCH 0/4] support for text-relative kallsyms table Rusty Russell <rusty@rustcorp.com.au> - 2016-01-27 05:40 +0100
| From | Ard Biesheuvel <ard.biesheuvel@linaro.org> |
|---|---|
| Date | 2016-01-20 10:10 +0100 |
| Subject | [PATCH 0/4] support for text-relative kallsyms table |
| Message-ID | <qSWW6-4hT-3@gated-at.bofh.it> |
This implements text-relative kallsyms address tables. This was developed as part of my series to implement KASLR/CONFIG_RELOCATABLE for arm64, but I think it may be beneficial to other architectures as well, so I am presenting it as a separate series. The idea is that on 64-bit builds, it is rather wasteful to use absolute addressing for kernel symbols since they are all within a couple of MBs of each other. On top of that, the absolute addressing implies that, when the kernel is relocated at runtime, each address in the table needs to be fixed up individually. Since all section-relative addresses are already emitted relative to _text, it is quite straight-forward to record only the offset, and add the absolute address of _text at runtime when referring to the address table. The reduction ranges from around 250 KB uncompressed vmlinux size and 10 KB compressed size (s390) to 3 MB/500 KB for ppc64 (although, in the latter case, the reduction in uncompressed size is primarily __init data) Kees Cook was so kind to test these against x86_64, and confirmed that KASLR still operates as expected. Ard Biesheuvel (4): kallsyms: add support for relative offsets in kallsyms address table powerpc: enable text relative kallsyms for ppc64 s390: enable text relative kallsyms for 64-bit targets x86_64: enable text relative kallsyms for 64-bit targets arch/powerpc/Kconfig | 1 + arch/s390/Kconfig | 1 + arch/x86/Kconfig | 1 + init/Kconfig | 14 ++++++++ kernel/kallsyms.c | 35 +++++++++++++----- scripts/kallsyms.c | 38 +++++++++++++++++--- scripts/link-vmlinux.sh | 4 +++ scripts/namespace.pl | 1 + 8 files changed, 82 insertions(+), 13 deletions(-) -- 2.5.0
[toc] | [next] | [standalone]
| From | Ard Biesheuvel <ard.biesheuvel@linaro.org> |
|---|---|
| Date | 2016-01-20 10:10 +0100 |
| Subject | [PATCH 1/4] kallsyms: add support for relative offsets in kallsyms address table |
| Message-ID | <qSWW7-4hT-37@gated-at.bofh.it> |
| In reply to | #1313012 |
Similar to how relative extables are implemented, it is possible to emit
the kallsyms table in such a way that it contains offsets relative to some
anchor point in the kernel image rather than absolute addresses. The benefit
is that such table entries are no longer subject to dynamic relocation when
the build time and runtime offsets of the kernel image are different. Also,
on 64-bit architectures, it essentially cuts the size of the address table
in half since offsets can typically be expressed in 32 bits.
Since it is useful for some architectures (like x86) to retain the ability
to emit absolute values as well, this patch adds support for both, by
emitting absolute addresses as positive 32-bit values, and addresses
relative to _text as negative values, which are subtracted from the runtime
address of _text to produce the actual address. Positive values are used as
they are found in the table.
Support for the above is enabled by setting CONFIG_KALLSYMS_TEXT_RELATIVE.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
init/Kconfig | 14 ++++++++
kernel/kallsyms.c | 35 +++++++++++++-----
scripts/kallsyms.c | 38 +++++++++++++++++---
scripts/link-vmlinux.sh | 4 +++
scripts/namespace.pl | 1 +
5 files changed, 79 insertions(+), 13 deletions(-)
diff --git a/init/Kconfig b/init/Kconfig
index 5b86082fa238..73e00b040572 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1427,6 +1427,20 @@ config KALLSYMS_ALL
Say N unless you really need all symbols.
+config KALLSYMS_TEXT_RELATIVE
+ bool
+ help
+ Instead of emitting them as absolute values in the native word size,
+ emit the symbol references in the kallsyms table as 32-bit entries,
+ each containing either an absolute value in the range [0, S32_MAX] or
+ a text relative value in the range [_text, _text + S32_MAX], encoded
+ as negative values.
+
+ On 64-bit builds, this reduces the size of the address table by 50%,
+ but more importantly, it results in entries whose values are build
+ time constants, and no relocation pass is required at runtime to fix
+ up the entries based on the runtime load address of the kernel.
+
config PRINTK
default y
bool "Enable support for printk" if EXPERT
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 5c5987f10819..e612f7f9e71b 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -38,6 +38,7 @@
* during the second link stage.
*/
extern const unsigned long kallsyms_addresses[] __weak;
+extern const int kallsyms_offsets[] __weak;
extern const u8 kallsyms_names[] __weak;
/*
@@ -176,6 +177,19 @@ static unsigned int get_symbol_offset(unsigned long pos)
return name - kallsyms_names;
}
+static unsigned long kallsyms_sym_address(int idx)
+{
+ if (!IS_ENABLED(CONFIG_KALLSYMS_TEXT_RELATIVE))
+ return kallsyms_addresses[idx];
+
+ /* positive offsets are absolute values */
+ if (kallsyms_offsets[idx] >= 0)
+ return kallsyms_offsets[idx];
+
+ /* negative offsets are relative to _text - 1 */
+ return (unsigned long)_text - 1 - kallsyms_offsets[idx];
+}
+
/* Lookup the address for this symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name)
{
@@ -187,7 +201,7 @@ unsigned long kallsyms_lookup_name(const char *name)
off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
if (strcmp(namebuf, name) == 0)
- return kallsyms_addresses[i];
+ return kallsyms_sym_address(i);
}
return module_kallsyms_lookup_name(name);
}
@@ -204,7 +218,7 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
- ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
+ ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
if (ret != 0)
return ret;
}
@@ -220,7 +234,10 @@ static unsigned long get_symbol_pos(unsigned long addr,
unsigned long i, low, high, mid;
/* This kernel should never had been booted. */
- BUG_ON(!kallsyms_addresses);
+ if (!IS_ENABLED(CONFIG_KALLSYMS_TEXT_RELATIVE))
+ BUG_ON(!kallsyms_addresses);
+ else
+ BUG_ON(!kallsyms_offsets);
/* Do a binary search on the sorted kallsyms_addresses array. */
low = 0;
@@ -228,7 +245,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
while (high - low > 1) {
mid = low + (high - low) / 2;
- if (kallsyms_addresses[mid] <= addr)
+ if (kallsyms_sym_address(mid) <= addr)
low = mid;
else
high = mid;
@@ -238,15 +255,15 @@ static unsigned long get_symbol_pos(unsigned long addr,
* Search for the first aliased symbol. Aliased
* symbols are symbols with the same address.
*/
- while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
+ while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
--low;
- symbol_start = kallsyms_addresses[low];
+ symbol_start = kallsyms_sym_address(low);
/* Search for next non-aliased symbol. */
for (i = low + 1; i < kallsyms_num_syms; i++) {
- if (kallsyms_addresses[i] > symbol_start) {
- symbol_end = kallsyms_addresses[i];
+ if (kallsyms_sym_address(i) > symbol_start) {
+ symbol_end = kallsyms_sym_address(i);
break;
}
}
@@ -470,7 +487,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
unsigned off = iter->nameoff;
iter->module_name[0] = '\0';
- iter->value = kallsyms_addresses[iter->pos];
+ iter->value = kallsyms_sym_address(iter->pos);
iter->type = kallsyms_get_symbol_type(off);
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 8fa81e84e295..07656c102e60 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <limits.h>
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -61,6 +62,7 @@ static int all_symbols = 0;
static int absolute_percpu = 0;
static char symbol_prefix_char = '\0';
static unsigned long long kernel_start_addr = 0;
+static int text_relative = 0;
int token_profit[0x10000];
@@ -74,7 +76,7 @@ static void usage(void)
fprintf(stderr, "Usage: kallsyms [--all-symbols] "
"[--symbol-prefix=<prefix char>] "
"[--page-offset=<CONFIG_PAGE_OFFSET>] "
- "< in.map > out.S\n");
+ "[--text-relative] < in.map > out.S\n");
exit(1);
}
@@ -202,6 +204,7 @@ static int symbol_valid(struct sym_entry *s)
*/
static char *special_symbols[] = {
"kallsyms_addresses",
+ "kallsyms_offsets",
"kallsyms_num_syms",
"kallsyms_names",
"kallsyms_markers",
@@ -353,9 +356,34 @@ static void write_src(void)
* .o files. This prevents .tmp_kallsyms.o or any other
* object from referencing them.
*/
- output_label("kallsyms_addresses");
+ if (!text_relative)
+ output_label("kallsyms_addresses");
+ else
+ output_label("kallsyms_offsets");
+
for (i = 0; i < table_cnt; i++) {
- if (!symbol_absolute(&table[i])) {
+ if (text_relative) {
+ long long offset;
+
+ if (symbol_absolute(&table[i])) {
+ offset = table[i].addr;
+ if (offset < 0 || offset > INT_MAX) {
+ fprintf(stderr, "kallsyms failure: "
+ "absolute symbol value %#llx out of range in relative mode\n",
+ table[i].addr);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ offset = _text - table[i].addr - 1;
+ if (offset < INT_MIN || offset >= 0) {
+ fprintf(stderr, "kallsyms failure: "
+ "relative symbol value %#llx out of range in relative mode\n",
+ table[i].addr);
+ exit(EXIT_FAILURE);
+ }
+ }
+ printf("\t.long\t%#x\n", (int)offset);
+ } else if (!symbol_absolute(&table[i])) {
if (_text <= table[i].addr)
printf("\tPTR\t_text + %#llx\n",
table[i].addr - _text);
@@ -703,7 +731,9 @@ int main(int argc, char **argv)
} else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
const char *p = &argv[i][14];
kernel_start_addr = strtoull(p, NULL, 16);
- } else
+ } else if (strcmp(argv[i], "--text-relative") == 0)
+ text_relative = 1;
+ else
usage();
}
} else if (argc != 1)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index ba6c34ea5429..e0f957f6a54c 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -90,6 +90,10 @@ kallsyms()
kallsymopt="${kallsymopt} --absolute-percpu"
fi
+ if [ -n "${CONFIG_KALLSYMS_TEXT_RELATIVE}" ]; then
+ kallsymopt="${kallsymopt} --text-relative"
+ fi
+
local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index a71be6b7cdec..e059ab240364 100755
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
@@ -117,6 +117,7 @@ my %nameexception = (
'kallsyms_names' => 1,
'kallsyms_num_syms' => 1,
'kallsyms_addresses'=> 1,
+ 'kallsyms_offsets' => 1,
'__this_module' => 1,
'_etext' => 1,
'_edata' => 1,
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2016-01-20 20:20 +0100 |
| Subject | Re: [PATCH 1/4] kallsyms: add support for relative offsets in kallsyms address table |
| Message-ID | <qT6sq-2vJ-9@gated-at.bofh.it> |
| In reply to | #1313016 |
On Wed, Jan 20, 2016 at 1:05 AM, Ard Biesheuvel
<ard.biesheuvel@linaro.org> wrote:
> Similar to how relative extables are implemented, it is possible to emit
> the kallsyms table in such a way that it contains offsets relative to some
> anchor point in the kernel image rather than absolute addresses. The benefit
> is that such table entries are no longer subject to dynamic relocation when
> the build time and runtime offsets of the kernel image are different. Also,
> on 64-bit architectures, it essentially cuts the size of the address table
> in half since offsets can typically be expressed in 32 bits.
>
> Since it is useful for some architectures (like x86) to retain the ability
> to emit absolute values as well, this patch adds support for both, by
> emitting absolute addresses as positive 32-bit values, and addresses
> relative to _text as negative values, which are subtracted from the runtime
> address of _text to produce the actual address. Positive values are used as
> they are found in the table.
>
> Support for the above is enabled by setting CONFIG_KALLSYMS_TEXT_RELATIVE.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
A nice space-saver! :)
-Kees
> ---
> init/Kconfig | 14 ++++++++
> kernel/kallsyms.c | 35 +++++++++++++-----
> scripts/kallsyms.c | 38 +++++++++++++++++---
> scripts/link-vmlinux.sh | 4 +++
> scripts/namespace.pl | 1 +
> 5 files changed, 79 insertions(+), 13 deletions(-)
>
> diff --git a/init/Kconfig b/init/Kconfig
> index 5b86082fa238..73e00b040572 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1427,6 +1427,20 @@ config KALLSYMS_ALL
>
> Say N unless you really need all symbols.
>
> +config KALLSYMS_TEXT_RELATIVE
> + bool
> + help
> + Instead of emitting them as absolute values in the native word size,
> + emit the symbol references in the kallsyms table as 32-bit entries,
> + each containing either an absolute value in the range [0, S32_MAX] or
> + a text relative value in the range [_text, _text + S32_MAX], encoded
> + as negative values.
> +
> + On 64-bit builds, this reduces the size of the address table by 50%,
> + but more importantly, it results in entries whose values are build
> + time constants, and no relocation pass is required at runtime to fix
> + up the entries based on the runtime load address of the kernel.
> +
> config PRINTK
> default y
> bool "Enable support for printk" if EXPERT
> diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
> index 5c5987f10819..e612f7f9e71b 100644
> --- a/kernel/kallsyms.c
> +++ b/kernel/kallsyms.c
> @@ -38,6 +38,7 @@
> * during the second link stage.
> */
> extern const unsigned long kallsyms_addresses[] __weak;
> +extern const int kallsyms_offsets[] __weak;
> extern const u8 kallsyms_names[] __weak;
>
> /*
> @@ -176,6 +177,19 @@ static unsigned int get_symbol_offset(unsigned long pos)
> return name - kallsyms_names;
> }
>
> +static unsigned long kallsyms_sym_address(int idx)
> +{
> + if (!IS_ENABLED(CONFIG_KALLSYMS_TEXT_RELATIVE))
> + return kallsyms_addresses[idx];
> +
> + /* positive offsets are absolute values */
> + if (kallsyms_offsets[idx] >= 0)
> + return kallsyms_offsets[idx];
> +
> + /* negative offsets are relative to _text - 1 */
> + return (unsigned long)_text - 1 - kallsyms_offsets[idx];
> +}
> +
> /* Lookup the address for this symbol. Returns 0 if not found. */
> unsigned long kallsyms_lookup_name(const char *name)
> {
> @@ -187,7 +201,7 @@ unsigned long kallsyms_lookup_name(const char *name)
> off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
>
> if (strcmp(namebuf, name) == 0)
> - return kallsyms_addresses[i];
> + return kallsyms_sym_address(i);
> }
> return module_kallsyms_lookup_name(name);
> }
> @@ -204,7 +218,7 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
>
> for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
> off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
> - ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
> + ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
> if (ret != 0)
> return ret;
> }
> @@ -220,7 +234,10 @@ static unsigned long get_symbol_pos(unsigned long addr,
> unsigned long i, low, high, mid;
>
> /* This kernel should never had been booted. */
> - BUG_ON(!kallsyms_addresses);
> + if (!IS_ENABLED(CONFIG_KALLSYMS_TEXT_RELATIVE))
> + BUG_ON(!kallsyms_addresses);
> + else
> + BUG_ON(!kallsyms_offsets);
>
> /* Do a binary search on the sorted kallsyms_addresses array. */
> low = 0;
> @@ -228,7 +245,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
>
> while (high - low > 1) {
> mid = low + (high - low) / 2;
> - if (kallsyms_addresses[mid] <= addr)
> + if (kallsyms_sym_address(mid) <= addr)
> low = mid;
> else
> high = mid;
> @@ -238,15 +255,15 @@ static unsigned long get_symbol_pos(unsigned long addr,
> * Search for the first aliased symbol. Aliased
> * symbols are symbols with the same address.
> */
> - while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
> + while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
> --low;
>
> - symbol_start = kallsyms_addresses[low];
> + symbol_start = kallsyms_sym_address(low);
>
> /* Search for next non-aliased symbol. */
> for (i = low + 1; i < kallsyms_num_syms; i++) {
> - if (kallsyms_addresses[i] > symbol_start) {
> - symbol_end = kallsyms_addresses[i];
> + if (kallsyms_sym_address(i) > symbol_start) {
> + symbol_end = kallsyms_sym_address(i);
> break;
> }
> }
> @@ -470,7 +487,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
> unsigned off = iter->nameoff;
>
> iter->module_name[0] = '\0';
> - iter->value = kallsyms_addresses[iter->pos];
> + iter->value = kallsyms_sym_address(iter->pos);
>
> iter->type = kallsyms_get_symbol_type(off);
>
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 8fa81e84e295..07656c102e60 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -22,6 +22,7 @@
> #include <stdlib.h>
> #include <string.h>
> #include <ctype.h>
> +#include <limits.h>
>
> #ifndef ARRAY_SIZE
> #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
> @@ -61,6 +62,7 @@ static int all_symbols = 0;
> static int absolute_percpu = 0;
> static char symbol_prefix_char = '\0';
> static unsigned long long kernel_start_addr = 0;
> +static int text_relative = 0;
>
> int token_profit[0x10000];
>
> @@ -74,7 +76,7 @@ static void usage(void)
> fprintf(stderr, "Usage: kallsyms [--all-symbols] "
> "[--symbol-prefix=<prefix char>] "
> "[--page-offset=<CONFIG_PAGE_OFFSET>] "
> - "< in.map > out.S\n");
> + "[--text-relative] < in.map > out.S\n");
> exit(1);
> }
>
> @@ -202,6 +204,7 @@ static int symbol_valid(struct sym_entry *s)
> */
> static char *special_symbols[] = {
> "kallsyms_addresses",
> + "kallsyms_offsets",
> "kallsyms_num_syms",
> "kallsyms_names",
> "kallsyms_markers",
> @@ -353,9 +356,34 @@ static void write_src(void)
> * .o files. This prevents .tmp_kallsyms.o or any other
> * object from referencing them.
> */
> - output_label("kallsyms_addresses");
> + if (!text_relative)
> + output_label("kallsyms_addresses");
> + else
> + output_label("kallsyms_offsets");
> +
> for (i = 0; i < table_cnt; i++) {
> - if (!symbol_absolute(&table[i])) {
> + if (text_relative) {
> + long long offset;
> +
> + if (symbol_absolute(&table[i])) {
> + offset = table[i].addr;
> + if (offset < 0 || offset > INT_MAX) {
> + fprintf(stderr, "kallsyms failure: "
> + "absolute symbol value %#llx out of range in relative mode\n",
> + table[i].addr);
> + exit(EXIT_FAILURE);
> + }
> + } else {
> + offset = _text - table[i].addr - 1;
> + if (offset < INT_MIN || offset >= 0) {
> + fprintf(stderr, "kallsyms failure: "
> + "relative symbol value %#llx out of range in relative mode\n",
> + table[i].addr);
> + exit(EXIT_FAILURE);
> + }
> + }
> + printf("\t.long\t%#x\n", (int)offset);
> + } else if (!symbol_absolute(&table[i])) {
> if (_text <= table[i].addr)
> printf("\tPTR\t_text + %#llx\n",
> table[i].addr - _text);
> @@ -703,7 +731,9 @@ int main(int argc, char **argv)
> } else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
> const char *p = &argv[i][14];
> kernel_start_addr = strtoull(p, NULL, 16);
> - } else
> + } else if (strcmp(argv[i], "--text-relative") == 0)
> + text_relative = 1;
> + else
> usage();
> }
> } else if (argc != 1)
> diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
> index ba6c34ea5429..e0f957f6a54c 100755
> --- a/scripts/link-vmlinux.sh
> +++ b/scripts/link-vmlinux.sh
> @@ -90,6 +90,10 @@ kallsyms()
> kallsymopt="${kallsymopt} --absolute-percpu"
> fi
>
> + if [ -n "${CONFIG_KALLSYMS_TEXT_RELATIVE}" ]; then
> + kallsymopt="${kallsymopt} --text-relative"
> + fi
> +
> local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
> ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
>
> diff --git a/scripts/namespace.pl b/scripts/namespace.pl
> index a71be6b7cdec..e059ab240364 100755
> --- a/scripts/namespace.pl
> +++ b/scripts/namespace.pl
> @@ -117,6 +117,7 @@ my %nameexception = (
> 'kallsyms_names' => 1,
> 'kallsyms_num_syms' => 1,
> 'kallsyms_addresses'=> 1,
> + 'kallsyms_offsets' => 1,
> '__this_module' => 1,
> '_etext' => 1,
> '_edata' => 1,
> --
> 2.5.0
>
--
Kees Cook
Chrome OS & Brillo Security
[toc] | [prev] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2016-01-20 11:40 +0100 |
| Message-ID | <qSYlc-56e-9@gated-at.bofh.it> |
| In reply to | #1313012 |
* Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > This implements text-relative kallsyms address tables. This was developed as > part of my series to implement KASLR/CONFIG_RELOCATABLE for arm64, but I think > it may be beneficial to other architectures as well, so I am presenting it as a > separate series. > > The idea is that on 64-bit builds, it is rather wasteful to use absolute > addressing for kernel symbols since they are all within a couple of MBs of each > other. On top of that, the absolute addressing implies that, when the kernel is > relocated at runtime, each address in the table needs to be fixed up > individually. > > Since all section-relative addresses are already emitted relative to _text, it > is quite straight-forward to record only the offset, and add the absolute > address of _text at runtime when referring to the address table. > > The reduction ranges from around 250 KB uncompressed vmlinux size and 10 KB > compressed size (s390) to 3 MB/500 KB for ppc64 (although, in the latter case, > the reduction in uncompressed size is primarily __init data) So since kallsyms is in unswappable kernel RAM, the uncompressed size reduction is what we care about mostly. How much bootloader load times are impacted is a third order concern. IOW a nice change! Thanks, Ingo
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-01-20 13:00 +0100 |
| Message-ID | <qSZAD-5Pv-23@gated-at.bofh.it> |
| In reply to | #1313090 |
On Wednesday 20 January 2016 11:33:25 Ingo Molnar wrote: > > The reduction ranges from around 250 KB uncompressed vmlinux size and 10 KB > > compressed size (s390) to 3 MB/500 KB for ppc64 (although, in the latter case, > > the reduction in uncompressed size is primarily __init data) > > So since kallsyms is in unswappable kernel RAM, the uncompressed size reduction is > what we care about mostly. How much bootloader load times are impacted is a third > order concern. > > IOW a nice change! I think some people care a lot about the compressed size as well: http://git.openwrt.org/?p=openwrt.git;a=blob;f=target/linux/generic/patches-4.4/203-kallsyms_uncompressed.patch;h=cf8a447bbcd5b1621d4edc36a69fe0ad384fe53f;hb=HEAD This has been in openwrt.git for ages, because a lot of the target devices are much more limited on flash memory size (4MB typically) than they are on RAM size (at least 32MB). Arnd
[toc] | [prev] | [next] | [standalone]
| From | Rusty Russell <rusty@rustcorp.com.au> |
|---|---|
| Date | 2016-01-21 06:20 +0100 |
| Message-ID | <qTfP5-x3-31@gated-at.bofh.it> |
| In reply to | #1313012 |
Ard Biesheuvel <ard.biesheuvel@linaro.org> writes: > This implements text-relative kallsyms address tables. This was developed > as part of my series to implement KASLR/CONFIG_RELOCATABLE for arm64, but > I think it may be beneficial to other architectures as well, so I am > presenting it as a separate series. Nice work! AFAICT this should work for every arch, as long as they start with _text (esp: data and init must be > _text). In addition, it's not harmful on 32 bit archs. IOW, I'd like to turn it on for everyone and discard some code. But it's easier to roll in like you've done first. Should we enable it by default for every arch for now, and see what happens? Thanks! Rusty. > The idea is that on 64-bit builds, it is rather wasteful to use absolute > addressing for kernel symbols since they are all within a couple of MBs > of each other. On top of that, the absolute addressing implies that, when > the kernel is relocated at runtime, each address in the table needs to be > fixed up individually. > > Since all section-relative addresses are already emitted relative to _text, > it is quite straight-forward to record only the offset, and add the absolute > address of _text at runtime when referring to the address table. > > The reduction ranges from around 250 KB uncompressed vmlinux size and 10 KB > compressed size (s390) to 3 MB/500 KB for ppc64 (although, in the latter case, > the reduction in uncompressed size is primarily __init data) > > Kees Cook was so kind to test these against x86_64, and confirmed that KASLR > still operates as expected. > > Ard Biesheuvel (4): > kallsyms: add support for relative offsets in kallsyms address table > powerpc: enable text relative kallsyms for ppc64 > s390: enable text relative kallsyms for 64-bit targets > x86_64: enable text relative kallsyms for 64-bit targets > > arch/powerpc/Kconfig | 1 + > arch/s390/Kconfig | 1 + > arch/x86/Kconfig | 1 + > init/Kconfig | 14 ++++++++ > kernel/kallsyms.c | 35 +++++++++++++----- > scripts/kallsyms.c | 38 +++++++++++++++++--- > scripts/link-vmlinux.sh | 4 +++ > scripts/namespace.pl | 1 + > 8 files changed, 82 insertions(+), 13 deletions(-) > > -- > 2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Ard Biesheuvel <ard.biesheuvel@linaro.org> |
|---|---|
| Date | 2016-01-21 07:50 +0100 |
| Message-ID | <qThea-1qJ-13@gated-at.bofh.it> |
| In reply to | #1313893 |
On 21 January 2016 at 06:10, Rusty Russell <rusty@rustcorp.com.au> wrote: > Ard Biesheuvel <ard.biesheuvel@linaro.org> writes: >> This implements text-relative kallsyms address tables. This was developed >> as part of my series to implement KASLR/CONFIG_RELOCATABLE for arm64, but >> I think it may be beneficial to other architectures as well, so I am >> presenting it as a separate series. > > Nice work! > Thanks > AFAICT this should work for every arch, as long as they start with _text > (esp: data and init must be > _text). In addition, it's not harmful on > 32 bit archs. > > IOW, I'd like to turn it on for everyone and discard some code. But > it's easier to roll in like you've done first. > > Should we enable it by default for every arch for now, and see what > happens? > As you say, this only works if every symbol >= _text, which is obviously not the case per the conditional in scripts/kallsyms.c, which emits _text + n or _text - n depending on whether the symbol precedes or follows _text. The git log tells me for which arch this was originally implemented, but it does not tell me which other archs have come to rely on it in the meantime. On top of that, ia64 fails to build with this option, since it has some whitelisted absolute symbols that look suspiciously like they could be emitted as _text relative (and it does not even matter in the absence of CONFIG_RELOCATABLE on ia64, afaict) but I don't know whether we can just override their types as T, since it would also change the type in the contents of /proc/kallsyms. So some guidance would be appreciated here. So I agree that it would be preferred to have a single code path, but I would need some help validating it on architectures I don't have access to. Thanks, Ard. >> The idea is that on 64-bit builds, it is rather wasteful to use absolute >> addressing for kernel symbols since they are all within a couple of MBs >> of each other. On top of that, the absolute addressing implies that, when >> the kernel is relocated at runtime, each address in the table needs to be >> fixed up individually. >> >> Since all section-relative addresses are already emitted relative to _text, >> it is quite straight-forward to record only the offset, and add the absolute >> address of _text at runtime when referring to the address table. >> >> The reduction ranges from around 250 KB uncompressed vmlinux size and 10 KB >> compressed size (s390) to 3 MB/500 KB for ppc64 (although, in the latter case, >> the reduction in uncompressed size is primarily __init data) >> >> Kees Cook was so kind to test these against x86_64, and confirmed that KASLR >> still operates as expected. >> >> Ard Biesheuvel (4): >> kallsyms: add support for relative offsets in kallsyms address table >> powerpc: enable text relative kallsyms for ppc64 >> s390: enable text relative kallsyms for 64-bit targets >> x86_64: enable text relative kallsyms for 64-bit targets >> >> arch/powerpc/Kconfig | 1 + >> arch/s390/Kconfig | 1 + >> arch/x86/Kconfig | 1 + >> init/Kconfig | 14 ++++++++ >> kernel/kallsyms.c | 35 +++++++++++++----- >> scripts/kallsyms.c | 38 +++++++++++++++++--- >> scripts/link-vmlinux.sh | 4 +++ >> scripts/namespace.pl | 1 + >> 8 files changed, 82 insertions(+), 13 deletions(-) >> >> -- >> 2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Ard Biesheuvel <ard.biesheuvel@linaro.org> |
|---|---|
| Date | 2016-01-21 09:40 +0100 |
| Message-ID | <qTiWB-2IG-1@gated-at.bofh.it> |
| In reply to | #1313960 |
On 21 January 2016 at 07:45, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > On 21 January 2016 at 06:10, Rusty Russell <rusty@rustcorp.com.au> wrote: >> Ard Biesheuvel <ard.biesheuvel@linaro.org> writes: >>> This implements text-relative kallsyms address tables. This was developed >>> as part of my series to implement KASLR/CONFIG_RELOCATABLE for arm64, but >>> I think it may be beneficial to other architectures as well, so I am >>> presenting it as a separate series. >> >> Nice work! >> > > Thanks > >> AFAICT this should work for every arch, as long as they start with _text >> (esp: data and init must be > _text). In addition, it's not harmful on >> 32 bit archs. >> >> IOW, I'd like to turn it on for everyone and discard some code. But >> it's easier to roll in like you've done first. >> >> Should we enable it by default for every arch for now, and see what >> happens? >> > > As you say, this only works if every symbol >= _text, which is > obviously not the case per the conditional in scripts/kallsyms.c, > which emits _text + n or _text - n depending on whether the symbol > precedes or follows _text. The git log tells me for which arch this > was originally implemented, but it does not tell me which other archs > have come to rely on it in the meantime. > > On top of that, ia64 fails to build with this option, since it has > some whitelisted absolute symbols that look suspiciously like they > could be emitted as _text relative (and it does not even matter in the > absence of CONFIG_RELOCATABLE on ia64, afaict) but I don't know > whether we can just override their types as T, since it would also > change the type in the contents of /proc/kallsyms. So some guidance > would be appreciated here. > Digging a little deeper, it appears that it would be non-trivial to port this to ia64: ... a000000000040720 A __kernel_syscall_via_break a000000000040740 A __kernel_sigtramp a000000000040a00 A __kernel_syscall_via_epc a000000100000000 T ia64_ivt a000000100000000 T __start_ivt_text a000000100000000 T _stext a000000100000000 T _text ... The top three symbols are the absolute symbols that are explicitly whitelisted by scripts/kallsyms.c, and they are too far from 0 and too far from _text to be representable in 32 bits > So I agree that it would be preferred to have a single code path, but > I would need some help validating it on architectures I don't have > access to. > > Thanks, > Ard. > > >>> The idea is that on 64-bit builds, it is rather wasteful to use absolute >>> addressing for kernel symbols since they are all within a couple of MBs >>> of each other. On top of that, the absolute addressing implies that, when >>> the kernel is relocated at runtime, each address in the table needs to be >>> fixed up individually. >>> >>> Since all section-relative addresses are already emitted relative to _text, >>> it is quite straight-forward to record only the offset, and add the absolute >>> address of _text at runtime when referring to the address table. >>> >>> The reduction ranges from around 250 KB uncompressed vmlinux size and 10 KB >>> compressed size (s390) to 3 MB/500 KB for ppc64 (although, in the latter case, >>> the reduction in uncompressed size is primarily __init data) >>> >>> Kees Cook was so kind to test these against x86_64, and confirmed that KASLR >>> still operates as expected. >>> >>> Ard Biesheuvel (4): >>> kallsyms: add support for relative offsets in kallsyms address table >>> powerpc: enable text relative kallsyms for ppc64 >>> s390: enable text relative kallsyms for 64-bit targets >>> x86_64: enable text relative kallsyms for 64-bit targets >>> >>> arch/powerpc/Kconfig | 1 + >>> arch/s390/Kconfig | 1 + >>> arch/x86/Kconfig | 1 + >>> init/Kconfig | 14 ++++++++ >>> kernel/kallsyms.c | 35 +++++++++++++----- >>> scripts/kallsyms.c | 38 +++++++++++++++++--- >>> scripts/link-vmlinux.sh | 4 +++ >>> scripts/namespace.pl | 1 + >>> 8 files changed, 82 insertions(+), 13 deletions(-) >>> >>> -- >>> 2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Rusty Russell <rusty@rustcorp.com.au> |
|---|---|
| Date | 2016-01-27 05:40 +0100 |
| Message-ID | <qVq3E-6sp-15@gated-at.bofh.it> |
| In reply to | #1313997 |
Ard Biesheuvel <ard.biesheuvel@linaro.org> writes: > On 21 January 2016 at 07:45, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: >> On 21 January 2016 at 06:10, Rusty Russell <rusty@rustcorp.com.au> wrote: >>> Ard Biesheuvel <ard.biesheuvel@linaro.org> writes: >>>> This implements text-relative kallsyms address tables. This was developed >>>> as part of my series to implement KASLR/CONFIG_RELOCATABLE for arm64, but >>>> I think it may be beneficial to other architectures as well, so I am >>>> presenting it as a separate series. >>> >>> Nice work! >>> >> >> Thanks >> >>> AFAICT this should work for every arch, as long as they start with _text >>> (esp: data and init must be > _text). In addition, it's not harmful on >>> 32 bit archs. >>> >>> IOW, I'd like to turn it on for everyone and discard some code. But >>> it's easier to roll in like you've done first. >>> >>> Should we enable it by default for every arch for now, and see what >>> happens? >>> >> >> As you say, this only works if every symbol >= _text, which is >> obviously not the case per the conditional in scripts/kallsyms.c, >> which emits _text + n or _text - n depending on whether the symbol >> precedes or follows _text. The git log tells me for which arch this >> was originally implemented, but it does not tell me which other archs >> have come to rely on it in the meantime. >> >> On top of that, ia64 fails to build with this option, since it has >> some whitelisted absolute symbols that look suspiciously like they >> could be emitted as _text relative (and it does not even matter in the >> absence of CONFIG_RELOCATABLE on ia64, afaict) but I don't know >> whether we can just override their types as T, since it would also >> change the type in the contents of /proc/kallsyms. So some guidance >> would be appreciated here. >> > > Digging a little deeper, it appears that it would be non-trivial to > port this to ia64: > > ... > a000000000040720 A __kernel_syscall_via_break > a000000000040740 A __kernel_sigtramp > a000000000040a00 A __kernel_syscall_via_epc > a000000100000000 T ia64_ivt > a000000100000000 T __start_ivt_text > a000000100000000 T _stext > a000000100000000 T _text > ... > > The top three symbols are the absolute symbols that are explicitly > whitelisted by scripts/kallsyms.c, and they are too far from 0 and too > far from _text to be representable in 32 bits How annoying. OK, until ia64 is removed, we'll leave the option. Thanks, Rusty.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web