arm64: assembler: make adr_l work in modules under KASLR
PATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
When CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make the adr_l macro emit a movz/movk sequence instead when executing in module context.
While at it, remove the pointless special case for the stack pointer.
--- arch/arm64/include/asm/assembler.h | 36 +++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-)
arch/arm64/include/asm/assembler.h +27 -9
@@ -164,22 +164,25 @@ lr .req x30 // link register/* * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where -* <symbol> is within the range +/- 4 GB of the PC. +* <symbol> is within the range +/- 4 GB of the PC when running +* in core kernel context. In module context, a movz/movk sequence +* is used, since modules may be loaded far away from the kernel +* when KASLR is in effect. */ /* * @dst: destination register (64 bit wide) * @sym: name of the symbol -* @tmp: optional scratch register to be used if <dst> == sp, which -* is not allowed in an adrp instruction */ - .macro adr_l, dst, sym, tmp= - .ifb \tmp + .macro adr_l, dst, sym +#ifndef MODULE adrp \dst, \sym add \dst, \dst, :lo12:\sym - .else - adrp \tmp, \sym - add \dst, \tmp, :lo12:\sym - .endif +#else + movz \dst, #:abs_g3:\sym + movk \dst, #:abs_g2_nc:\sym + movk \dst, #:abs_g1_nc:\sym + movk \dst, #:abs_g0_nc:\sym +#endif .endm/*
@@ -190,6 +193,7 @@ lr .req x30 // link register* the address */ .macro ldr_l, dst, sym, tmp= +#ifndef MODULE .ifb \tmp adrp \dst, \sym ldr \dst, [\dst, :lo12:\sym]
@@ -197,6 +201,15 @@ lr .req x30 // link register adrp \tmp, \sym ldr \dst, [\tmp, :lo12:\sym] .endif +#else + .ifb \tmp + adr_l \dst, \sym + ldr \dst, [\dst] + .else + adr_l \tmp, \sym + ldr \dst, [\tmp] + .endif +#endif .endm/*
@@ -206,8 +219,13 @@ lr .req x30 // link register* while <src> needs to be preserved. */ .macro str_l, src, sym, tmp +#ifndef MODULE adrp \tmp, \sym str \src, [\tmp, :lo12:\sym] +#else + adr_l \tmp, \sym + str \src, [\tmp] +#endif .endm/*
Signature · 1 line
2.7.4
Mark Rutland
reviewerPATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
Hi Ard,
Quoted 5 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.
AFAICT, we only use adr_l in a few assembly files that shouldn't matter to modules:
* arch/arm64/kernel/head.S
* arch/arm64/kernel/sleep.S
* arch/arm64/kvm/hyp-init.S
* arch/arm64/kvm/hyp/hyp-entry.S
... so I don't follow why we need this.
Have I missed something? Or do you intend to use this in module code in future?
It seems somewhat surprising to me to have adr_l expand to something that doesn't use adr/adrp, but that's not necessarily a problem.
Thanks,
Mark.
PATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
Quoted 17 lines · Mark Rutland
Hi Ard,
Quoted 5 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.AFAICT, we only use
adr_lin a few assembly files that shouldn't matter to modules:*
arch/arm64/kernel/head.S
*arch/arm64/kernel/sleep.S
*arch/arm64/kvm/hyp-init.S
*arch/arm64/kvm/hyp/hyp-entry.S
Quoted 5 lines
... so I don't follow why we need this.
Have I missed something? Or do you intend to use this in module code in future?
Yes. E.g., the scalar AES cipher that I am proposing for v4.11 reuses the lookup tables from crypto/aes_generic.c, which may be built into the core kernel, while the code itself may be built as a module.
But in general, if the macro is available to modules, I would like to make sure that it does not result in code that builds fine but may fail in some cases only at runtime, especially given the fact that there is also a Cortex-A53 erratum regarding adrp instructions, for which reason we build modules with -mcmodel=large (which amounts to the same thing as the patch above)
Quoted 3 lines
It seems somewhat surprising to me to have
adr_lexpand to something that doesn't use adr/adrp, but that's not necessarily a problem.
I did realise that, but I don't think it is a problem tbh.
PATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
Quoted 28 lines · Ard Biesheuvel
Quoted 17 lines · Mark Rutland
Hi Ard,
Quoted 5 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.AFAICT, we only use
adr_lin a few assembly files that shouldn't matter to modules:*
arch/arm64/kernel/head.S
*arch/arm64/kernel/sleep.S
*arch/arm64/kvm/hyp-init.S
*arch/arm64/kvm/hyp/hyp-entry.SQuoted 5 lines
... so I don't follow why we need this.
Have I missed something? Or do you intend to use this in module code in future?
Yes. E.g., the scalar AES cipher that I am proposing for v4.11 reuses the lookup tables from
crypto/aes_generic.c, which may be built into the core kernel, while the code itself may be built as a module.
Quoted 7 lines
But in general, if the macro is available to modules, I would like to make sure that it does not result in code that builds fine but may fail in some cases only at runtime, especially given the fact that there is also a Cortex-A53 erratum regarding adrp instructions, for which reason we build modules with -mcmodel=large (which amounts to the same thing as the patch above)
Actually, we could test for
defined(MODULE) && defined(CONFIG_ARM64_MODULE_CMODEL_LARGE)
instead, so we revert to adrp/add pairs for modules if the erratum and KASLR are both disabled
Quoted 5 lines
Quoted 3 lines
It seems somewhat surprising to me to have
adr_lexpand to something that doesn't use adr/adrp, but that's not necessarily a problem.I did realise that, but I don't think it is a problem tbh.
Mark Rutland
reviewerPATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
In reply to Ard BiesheuvelQuoted 18 lines · Ard Biesheuvel
Quoted 17 lines · Mark Rutland
Hi Ard,
Quoted 5 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.AFAICT, we only use
adr_lin a few assembly files that shouldn't matter to modules:*
arch/arm64/kernel/head.S
*arch/arm64/kernel/sleep.S
*arch/arm64/kvm/hyp-init.S
*arch/arm64/kvm/hyp/hyp-entry.S
Quoted 8 lines
Quoted 4 lines
... so I don't follow why we need this.
Have I missed something? Or do you intend to use this in module code in future?
Yes. E.g., the scalar AES cipher that I am proposing for v4.11 reuses the lookup tables from
crypto/aes_generic.c, which may be built into the core kernel, while the code itself may be built as a module.
Ah, ok.
Quoted 11 lines
But in general, if the macro is available to modules, I would like to make sure that it does not result in code that builds fine but may fail in some cases only at runtime, especially given the fact that there is also a Cortex-A53 erratum regarding adrp instructions, for which reason we build modules with -mcmodel=large (which amounts to the same thing as the patch above)
Quoted 2 lines
It seems somewhat surprising to me to have
adr_lexpand to something that doesn't use adr/adrp, but that's not necessarily a problem.I did realise that, but I don't think it is a problem tbh.
In this case it should be fine, certainly.
There are cases like the early boot code and hyp code where it's critical that we use adr. It's also possible that we might build (modular) drivers which want some idmapped code, where we want adr, so it seems unfortunate that this depends on howthe code is built.
So, maybe it's better to have a mov_sym helper for this case, to be explicit about what we want? That can use either adr* or mov*, or the latter consistently.
Thanks,
Mark.
PATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
Quoted 40 lines · Mark Rutland
Quoted 18 lines · Ard Biesheuvel
Quoted 17 lines · Mark Rutland
Hi Ard,
Quoted 5 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.AFAICT, we only use
adr_lin a few assembly files that shouldn't matter to modules:*
arch/arm64/kernel/head.S
*arch/arm64/kernel/sleep.S
*arch/arm64/kvm/hyp-init.S
*arch/arm64/kvm/hyp/hyp-entry.SQuoted 8 lines
Quoted 4 lines
... so I don't follow why we need this.
Have I missed something? Or do you intend to use this in module code in future?
Yes. E.g., the scalar AES cipher that I am proposing for v4.11 reuses the lookup tables from
crypto/aes_generic.c, which may be built into the core kernel, while the code itself may be built as a module.Ah, ok.
Quoted 10 lines
But in general, if the macro is available to modules, I would like to make sure that it does not result in code that builds fine but may fail in some cases only at runtime, especially given the fact that there is also a Cortex-A53 erratum regarding adrp instructions, for which reason we build modules with -mcmodel=large (which amounts to the same thing as the patch above)
Quoted 2 lines
It seems somewhat surprising to me to have
adr_lexpand to something that doesn't use adr/adrp, but that's not necessarily a problem.
Quoted 9 lines
Quoted 1 line
I did realise that, but I don't think it is a problem tbh.
In this case it should be fine, certainly.
There are cases like the early boot code and hyp code where it's critical that we use adr. It's also possible that we might build (modular) drivers which want some idmapped code, where we want adr, so it seems unfortunate that this depends on howthe code is built.
How would /that/ work? Modules are vmalloc'ed, and not covered by the ID map to begin with, so it is impossible to execute those adr instructions in a way that would make them return anything other than the virtual address of the symbol they refer to.
Quoted 4 lines
So, maybe it's better to have a
mov_symhelper for this case, to be explicit about what we want? That can use either adr* or mov*, or the latter consistently.
Well, the point is that adr_l should not be used for modules so adding something that may be used is fine, but that still leaves the risk that someone may end up using it in a module.
Mark Rutland
reviewerPATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
Quoted 24 lines · Ard Biesheuvel
Quoted 14 lines · Mark Rutland
Quoted 13 lines · Ard Biesheuvel
Quoted 1 line · Mark Rutland
On Wed, Jan 11, 2017 at 02:54:53PM +0000, Ard Biesheuvel wrote:
But in general, if the macro is available to modules, I would like to make sure that it does not result in code that builds fine but may fail in some cases only at runtime, especially given the fact that there is also a Cortex-A53 erratum regarding adrp instructions, for which reason we build modules with -mcmodel=large (which amounts to the same thing as the patch above)
Quoted 2 lines
It seems somewhat surprising to me to have
adr_lexpand to something that doesn't use adr/adrp, but that's not necessarily a problem.Quoted 8 lines
Quoted 1 line
I did realise that, but I don't think it is a problem tbh.
In this case it should be fine, certainly.
There are cases like the early boot code and hyp code where it's critical that we use adr. It's also possible that we might build (modular) drivers which want some idmapped code, where we want adr, so it seems unfortunate that this depends on howthe code is built.
Quoted 4 lines
How would /that/ work? Modules are vmalloc'ed, and not covered by the ID map to begin with, so it is impossible to execute those adr instructions in a way that would make them return anything other than the virtual address of the symbol they refer to.
That's a fair point.
Quoted 7 lines
Quoted 3 lines
So, maybe it's better to have a
mov_symhelper for this case, to be explicit about what we want? That can use either adr* or mov*, or the latter consistently.Well, the point is that
adr_lshould not be used for modules so adding something that may be used is fine, but that still leaves the risk that someone may end up using it in a module.
Sure.
Given you have a concrete use case, and all I have are some vague concerns for code that doesn't exist at present, I have no real objection to the patch as it stands. FWIW:
Thanks,
Mark.
PATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
In reply to Ard BiesheuvelQuoted 6 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.
Quoted 6 lines
While at it, remove the pointless special case for the stack pointer.
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/include/asm/assembler.h | 36 +++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-)
Given that you need this for 4.11, I suggest Catalin takes it as a fix for 4.10 to avoid the crypto dependency.
Will
Catalin Marinas
maintainerPATCH 1/1 arm64: assembler: make adr_l work in modules under KASLR
Quoted 14 lines · Will Deacon
Quoted 6 lines · Ard Biesheuvel
When
CONFIG_RANDOMIZE_MODULE_REGION_FULL=y, the offset between loaded modules and the core kernel may exceed 4 GB, putting symbols exported by the core kernel out of the reach of the ordinary adrp/add instruction pairs used to generate relative symbol references. So make theadr_lmacro emit a movz/movk sequence instead when executing in module context.Quoted 6 lines
While at it, remove the pointless special case for the stack pointer.
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/include/asm/assembler.h | 36 +++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-)
Quoted 4 lines
Given that you need this for 4.11, I suggest Catalin takes it as a fix for 4.10 to avoid the crypto dependency.
Acked-by Will Deacon <[email protected]>
That's fine by me. Thanks for the ack.
Signature · 1 line
Catalin