Re: [Xen-devel] [RFC 21/22] x86/module: Add support for mcmodel large and PLTs

2017-07-24 Thread Thomas Garnier
On Wed, Jul 19, 2017 at 10:34 AM, Brian Gerst  wrote:
> On Wed, Jul 19, 2017 at 11:58 AM, Thomas Garnier  wrote:
>> On Tue, Jul 18, 2017 at 8:59 PM, Brian Gerst  wrote:
>>> On Tue, Jul 18, 2017 at 9:35 PM, H. Peter Anvin  wrote:
 On 07/18/17 15:33, Thomas Garnier wrote:
> With PIE support and KASLR extended range, the modules may be further
> away from the kernel than before breaking mcmodel=kernel expectations.
>
> Add an option to build modules with mcmodel=large. The modules generated
> code will make no assumptions on placement in memory.
>
> Despite this option, modules still expect kernel functions to be within
> 2G and generate relative calls. To solve this issue, the PLT arm64 code
> was adapted for x86_64. When a relative relocation go outside its range,
> a dynamic PLT entry is used to correctly jump to the destination.

 Why large as opposed to medium or medium-PIC?
>>>
>>> Or for that matter, why not small-PIC?  We aren't changing the size of
>>> the kernel to be larger than 2G text or data.  Small-PIC would still
>>> allow it to be placed anywhere in the address space, and would
>>> generate far better code.
>>
>> My understanding was that small=PIC and medium=PIC assume that the
>> module code is in the lower 2G of memory. I will do additional testing
>> on the modules to confirm that.
>
> That is only for small/medium absolute (non-PIC) code.  Think about
> userspace shared libraries.  They are not limited to being mapped in
> the lower 2G of the address space.

I built lkdtm with mcmodel=(kernel, small, medium & large).

Comparing the same instruction and its relocation in lkdtm
(lkdtm_register_cpoint).

On mcmodel=kernel:

 1b8:   48 c7 c7 00 00 00 00mov$0x0,%rdi
1bb: R_X86_64_32S   .rodata.str1.8+0x50

On mcmodel=small and mcmodel=medium:

 1b8:   bf 00 00 00 00  mov$0x0,%edi
 1b9: R_X86_64_32.rodata.str1.8+0x50

On mcmodel=large:

 235:   48 bf 00 00 00 00 00movabs $0x0,%rdi
 23c:   00 00 00
237: R_X86_64_64.rodata.str1.8+0x50

The kernel mcmodel extends the sign of the address. It assumes you are
in the top 2G of the address space. So the relocated pointer
0x8XXX becomes 0x8XXX.

The small and medium mcmodels assume the pointer is within the lower
part of the address space. The generate pointer has the 32-bit high
part to zero. You can only map the module between 0 and 0x.

The large mcmodel can handle a full 64-bit pointer.

That's why I use the large mcmodel on modules. I cannot use PIE due to
how the modules are linked.

>
> --
> Brian Gerst



-- 
Thomas

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC 21/22] x86/module: Add support for mcmodel large and PLTs

2017-07-19 Thread Brian Gerst
On Wed, Jul 19, 2017 at 11:58 AM, Thomas Garnier  wrote:
> On Tue, Jul 18, 2017 at 8:59 PM, Brian Gerst  wrote:
>> On Tue, Jul 18, 2017 at 9:35 PM, H. Peter Anvin  wrote:
>>> On 07/18/17 15:33, Thomas Garnier wrote:
 With PIE support and KASLR extended range, the modules may be further
 away from the kernel than before breaking mcmodel=kernel expectations.

 Add an option to build modules with mcmodel=large. The modules generated
 code will make no assumptions on placement in memory.

 Despite this option, modules still expect kernel functions to be within
 2G and generate relative calls. To solve this issue, the PLT arm64 code
 was adapted for x86_64. When a relative relocation go outside its range,
 a dynamic PLT entry is used to correctly jump to the destination.
>>>
>>> Why large as opposed to medium or medium-PIC?
>>
>> Or for that matter, why not small-PIC?  We aren't changing the size of
>> the kernel to be larger than 2G text or data.  Small-PIC would still
>> allow it to be placed anywhere in the address space, and would
>> generate far better code.
>
> My understanding was that small=PIC and medium=PIC assume that the
> module code is in the lower 2G of memory. I will do additional testing
> on the modules to confirm that.

That is only for small/medium absolute (non-PIC) code.  Think about
userspace shared libraries.  They are not limited to being mapped in
the lower 2G of the address space.

--
Brian Gerst

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC 21/22] x86/module: Add support for mcmodel large and PLTs

2017-07-19 Thread Thomas Garnier
On Tue, Jul 18, 2017 at 8:59 PM, Brian Gerst  wrote:
> On Tue, Jul 18, 2017 at 9:35 PM, H. Peter Anvin  wrote:
>> On 07/18/17 15:33, Thomas Garnier wrote:
>>> With PIE support and KASLR extended range, the modules may be further
>>> away from the kernel than before breaking mcmodel=kernel expectations.
>>>
>>> Add an option to build modules with mcmodel=large. The modules generated
>>> code will make no assumptions on placement in memory.
>>>
>>> Despite this option, modules still expect kernel functions to be within
>>> 2G and generate relative calls. To solve this issue, the PLT arm64 code
>>> was adapted for x86_64. When a relative relocation go outside its range,
>>> a dynamic PLT entry is used to correctly jump to the destination.
>>
>> Why large as opposed to medium or medium-PIC?
>
> Or for that matter, why not small-PIC?  We aren't changing the size of
> the kernel to be larger than 2G text or data.  Small-PIC would still
> allow it to be placed anywhere in the address space, and would
> generate far better code.

My understanding was that small=PIC and medium=PIC assume that the
module code is in the lower 2G of memory. I will do additional testing
on the modules to confirm that.

>
> --
> Brian Gerst



-- 
Thomas

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC 21/22] x86/module: Add support for mcmodel large and PLTs

2017-07-18 Thread Brian Gerst
On Tue, Jul 18, 2017 at 9:35 PM, H. Peter Anvin  wrote:
> On 07/18/17 15:33, Thomas Garnier wrote:
>> With PIE support and KASLR extended range, the modules may be further
>> away from the kernel than before breaking mcmodel=kernel expectations.
>>
>> Add an option to build modules with mcmodel=large. The modules generated
>> code will make no assumptions on placement in memory.
>>
>> Despite this option, modules still expect kernel functions to be within
>> 2G and generate relative calls. To solve this issue, the PLT arm64 code
>> was adapted for x86_64. When a relative relocation go outside its range,
>> a dynamic PLT entry is used to correctly jump to the destination.
>
> Why large as opposed to medium or medium-PIC?

Or for that matter, why not small-PIC?  We aren't changing the size of
the kernel to be larger than 2G text or data.  Small-PIC would still
allow it to be placed anywhere in the address space, and would
generate far better code.

--
Brian Gerst

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC 21/22] x86/module: Add support for mcmodel large and PLTs

2017-07-18 Thread H. Peter Anvin
On 07/18/17 15:33, Thomas Garnier wrote:
> With PIE support and KASLR extended range, the modules may be further
> away from the kernel than before breaking mcmodel=kernel expectations.
> 
> Add an option to build modules with mcmodel=large. The modules generated
> code will make no assumptions on placement in memory.
> 
> Despite this option, modules still expect kernel functions to be within
> 2G and generate relative calls. To solve this issue, the PLT arm64 code
> was adapted for x86_64. When a relative relocation go outside its range,
> a dynamic PLT entry is used to correctly jump to the destination.

Why large as opposed to medium or medium-PIC?

-hpa



___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [RFC 21/22] x86/module: Add support for mcmodel large and PLTs

2017-07-18 Thread Thomas Garnier
With PIE support and KASLR extended range, the modules may be further
away from the kernel than before breaking mcmodel=kernel expectations.

Add an option to build modules with mcmodel=large. The modules generated
code will make no assumptions on placement in memory.

Despite this option, modules still expect kernel functions to be within
2G and generate relative calls. To solve this issue, the PLT arm64 code
was adapted for x86_64. When a relative relocation go outside its range,
a dynamic PLT entry is used to correctly jump to the destination.

Signed-off-by: Thomas Garnier 
---
 arch/x86/Kconfig  |  10 +++
 arch/x86/Makefile |  10 ++-
 arch/x86/include/asm/module.h |  16 
 arch/x86/kernel/Makefile  |   2 +
 arch/x86/kernel/module-plts.c | 198 ++
 arch/x86/kernel/module.c  |  18 ++--
 arch/x86/kernel/module.lds|   4 +
 7 files changed, 251 insertions(+), 7 deletions(-)
 create mode 100644 arch/x86/kernel/module-plts.c
 create mode 100644 arch/x86/kernel/module.lds

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b26ee6751021..60d161391d5a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2086,6 +2086,16 @@ config X86_PIE
select DEFAULT_HIDDEN
select MODULE_REL_CRCS if MODVERSIONS
 
+config X86_MODULE_MODEL_LARGE
+   bool
+   depends on X86_64 && X86_PIE
+
+config X86_MODULE_PLTS
+   bool
+   depends on X86_64
+   select X86_MODULE_MODEL_LARGE
+   select HAVE_MOD_ARCH_SPECIFIC
+
 config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs"
depends on SMP
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 452a9621af8f..72a90da0149a 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -138,10 +138,18 @@ else
 KBUILD_CFLAGS += -mno-red-zone
 ifdef CONFIG_X86_PIE
 KBUILD_CFLAGS += -fPIC
-KBUILD_CFLAGS_MODULE += -fno-PIC -mcmodel=kernel
+KBUILD_CFLAGS_MODULE += -fno-PIC
 else
 KBUILD_CFLAGS += -mcmodel=kernel
 endif
+ifdef CONFIG_X86_MODULE_MODEL_LARGE
+KBUILD_CFLAGS_MODULE += -mcmodel=large
+else
+KBUILD_CFLAGS_MODULE += -mcmodel=kernel
+endif
+ifdef CONFIG_X86_MODULE_PLTS
+KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/x86/kernel/module.lds
+endif
 
 # -funit-at-a-time shrinks the kernel .text considerably
 # unfortunately it makes reading oopses harder.
diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
index e3b7819caeef..d054c37656ea 100644
--- a/arch/x86/include/asm/module.h
+++ b/arch/x86/include/asm/module.h
@@ -61,4 +61,20 @@
 # define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
 #endif
 
+#ifdef CONFIG_X86_MODULE_PLTS
+struct mod_plt_sec {
+   struct elf64_shdr   *plt;
+   int plt_num_entries;
+   int plt_max_entries;
+};
+
+struct mod_arch_specific {
+   struct mod_plt_sec  core;
+   struct mod_plt_sec  init;
+};
+#endif
+
+u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela 
*rela,
+ Elf64_Sym *sym);
+
 #endif /* _ASM_X86_MODULE_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index a01892bdd61a..e294aefb747c 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -142,4 +142,6 @@ ifeq ($(CONFIG_X86_64),y)
 
obj-$(CONFIG_PCI_MMCONFIG)  += mmconf-fam10h_64.o
obj-y   += vsmp_64.o
+
+   obj-$(CONFIG_X86_MODULE_PLTS)   += module-plts.o
 endif
diff --git a/arch/x86/kernel/module-plts.c b/arch/x86/kernel/module-plts.c
new file mode 100644
index ..bbf11771f424
--- /dev/null
+++ b/arch/x86/kernel/module-plts.c
@@ -0,0 +1,198 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Generate PLT entries for out-of-bound PC-relative relocations. It is 
required
+ * when a module can be mapped more than 2G away from the kernel.
+ *
+ * Based on arm64 module-plts implementation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+/* jmpQWORD PTR [rip+0xfff2] */
+const u8 jmp_target[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF };
+
+struct plt_entry {
+   u64 target; /* Hold the target address */
+   u8 jmp[sizeof(jmp_target)]; /* jmp opcode to target */
+};
+
+static bool in_init(const struct module *mod, void *loc)
+{
+   return (u64)loc - (u64)mod->init_layout.base < mod->init_layout.size;
+}
+
+u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela 
*rela,
+ Elf64_Sym *sym)
+{
+   struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core :
+ &mod->arch.init;
+   struct plt_entry *plt = (struct plt_entry *)pltsec->plt->sh_addr;
+   int i