The handling of various sections in the VDSO linker script
looks pretty haphazard. This patch series cleans it up in
these regards:
- improve the coding style
- remove superfluous sections
- issue a linker error if a section is encountered which
is known not to work
- check that the .got section is empty, except for the
three entries defined by the ABI
- discard sections which are not useful to user-space
Petr Tesarik (9):
x86: Adjust the coding style of vdso-layout.lds.S
x86: Remove .sdata from the vDSO linker script
x86: add .broken section to the vDSO linker script
x86: mark altinstr-related sections in vDSO as broken
x86: mark some standard sections as broken in a vDSO
x86: move 32-bit vDSO padding from .data to .rodata
x86: mark writable vDSO sections as broken
x86: check the size of GOT in vDSO
x86: remove .gnu.warning* sections from the vDSO
arch/x86/vdso/Makefile | 5 +-
arch/x86/vdso/vdso-layout.lds.S | 158 ++++++++++++++++++++++++++++++++-------
arch/x86/vdso/vdso32/int80.S | 2 +-
arch/x86/vdso/vdso32/syscall.S | 2 +-
4 files changed, 136 insertions(+), 31 deletions(-)
There is no .sdata section on either i386 or x86_64.
The existence of this line probably dates back to the (long abandoned)
idea that x86_64 would have .sdata for "small" data and .data for large
data. However, the final ABI has .data for "normal" data and .ldata
for large data, so this line is no longer pertinent.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 917df03..af3fa61 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -50,7 +50,6 @@ SECTIONS
} :text
.data : {
*(.data*)
- *(.sdata*)
*(.got.plt) *(.got)
*(.gnu.linkonce.d.*)
*(.bss*)
--
1.6.0.2
The .gnu.warning* sections are only processed by ld, but ld will never
explicitly link against the vDSO, so it can be discarded.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 0bef418..d199f25 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -112,6 +112,12 @@ SECTIONS
*(.altinstructions)
*(.altinstr_replacement)
}
+
+ /* These sections are not useful to user-space */
+ /DISCARD/ : {
+ *(.gnu.warning*)
+ *(.discard)
+ }
}
/*
--
1.6.0.2
There are several reasons why this does not work for the vDSO.
1. The alt_instr records are not processed by anybody.
The .altinstruction sections end up in the vDSO binary, which
is then incorporated verbatim inside a completely different
section, so it is not seen by the main kernel.
There is no code to interpret them during vDSO setup either.
2. The pointers in the alt_instr records are wrong.
They point to the instructions and replacements at the prelinked
addresses, but that's neither where the vDSO blob is located at
startup, nor where it is copied to by the vDSO setup.
The .altinstr_replacement section is not broken per se, but it is
useless dead code without the accompanying .alt_instr section.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index cc66120..3d34d66 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -57,13 +57,6 @@ SECTIONS
*(.gnu.linkonce.b.*)
}
- .altinstructions : {
- *(.altinstructions)
- }
- .altinstr_replacement : {
- *(.altinstr_replacement)
- }
-
/*
* Align the actual code well away from the non-instruction data.
* This is the best thing for the I-cache.
@@ -82,6 +75,12 @@ SECTIONS
* if they get used by accident.
*/
.broken : {
+ /*
+ * The vDSO setup code does not handle alternative
+ * instructions.
+ */
+ *(.altinstructions)
+ *(.altinstr_replacement)
}
}
--
1.6.0.2
This section should not contain anything unless the vDSO is
broken. It is intended to hold sections which are known not
to work correctly inside a vDSO.
If such a "broken" section is found at link-time, the linker
issues an error with a hint how to find out more.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index af3fa61..cc66120 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -73,9 +73,33 @@ SECTIONS
.text : {
*(.text*)
} :text =0x90909090
+
+ /*
+ * Some sections require some additional work from the dynamic
+ * linker to work properly. However, there is no dynamic-link
+ * pass for the vDSO, so these sections will not work.
+ * Put them into a special section and raise a link-time error
+ * if they get used by accident.
+ */
+ .broken : {
+ }
}
/*
+ * This assert is triggered if the linker finds a section in one of its
+ * input files which is known not to work inside a vDSO.
+ *
+ * To see which is the offending sections, you may:
+ * a. use objdump -h on the object files which make up the vDSO, or
+ * b. add -Wl,-M to VDSO_LDFLAGS and examine the linker map.
+ *
+ * See individual comments in the definition of the .broken section
+ * above for more information on why any given section is considered
+ * "broken".
+ */
+ASSERT(!SIZEOF(.broken), "The vdso linker script found a section that is bad. See vdso-layout.lds.S for details.");
+
+/*
* Very old versions of ld do not recognize this name token; use the constant.
*/
#define PT_GNU_EH_FRAME 0x6474e550
--
1.6.0.2
Some standard sections can't work in a vDSO. Although most of them
are not very likely to ever appear there, it doesn't hurt to list
them as a precaution.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 3d34d66..74fc5ae 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -76,6 +76,31 @@ SECTIONS
*/
.broken : {
/*
+ * Code in the Procedure Linkage Table will segfault.
+ */
+ *(.plt)
+
+ /*
+ * Nobody does the final relocation to fixup prelinked
+ * addresses for the actual vDSO base address.
+ */
+ *(.rel*)
+
+ /*
+ * Initialization/termination won't work this way.
+ */
+ *(.init) *(.fini)
+ *(.preinit_array) *(.init_array*)
+ *(.fini_array*)
+
+ /*
+ * Thread-local storage cannot be defined like this.
+ */
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ *(.tbss .tbss.* .gnu.linkonce.tb.*)
+ *(.tcommon)
+
+ /*
* The vDSO setup code does not handle alternative
* instructions.
*/
--
1.6.0.2
The style we try to introduce for .lds files in
arch/$ARCH/kernel/vmlinux.lds.S is much more C-like.
Use the same style in the vDSO linker script to get a consistent
style in linker scripts.
Credits to Sam Ravnborg for suggesting this change.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 76 +++++++++++++++++++++++++++------------
1 files changed, 53 insertions(+), 23 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 634a2cf..917df03 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -8,34 +8,62 @@ SECTIONS
{
. = VDSO_PRELINK + SIZEOF_HEADERS;
- .hash : { *(.hash) } :text
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
+ .hash : {
+ *(.hash)
+ } :text
+ .gnu.hash : {
+ *(.gnu.hash)
+ }
+ .dynsym : {
+ *(.dynsym)
+ }
+ .dynstr : {
+ *(.dynstr)
+ }
+ .gnu.version : {
+ *(.gnu.version)
+ }
+ .gnu.version_d : {
+ *(.gnu.version_d)
+ }
+ .gnu.version_r : {
+ *(.gnu.version_r)
+ }
- .note : { *(.note.*) } :text :note
+ .note : {
+ *(.note.*)
+ } :text :note
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .eh_frame_hdr : {
+ *(.eh_frame_hdr)
+ } :text :eh_frame_hdr
+ .eh_frame : {
+ KEEP (*(.eh_frame))
+ } :text
- .dynamic : { *(.dynamic) } :text :dynamic
+ .dynamic : {
+ *(.dynamic)
+ } :text :dynamic
- .rodata : { *(.rodata*) } :text
- .data : {
- *(.data*)
- *(.sdata*)
- *(.got.plt) *(.got)
- *(.gnu.linkonce.d.*)
- *(.bss*)
- *(.dynbss*)
- *(.gnu.linkonce.b.*)
+ .rodata : {
+ *(.rodata*)
+ } :text
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
}
- .altinstructions : { *(.altinstructions) }
- .altinstr_replacement : { *(.altinstr_replacement) }
+ .altinstructions : {
+ *(.altinstructions)
+ }
+ .altinstr_replacement : {
+ *(.altinstr_replacement)
+ }
/*
* Align the actual code well away from the non-instruction data.
@@ -43,7 +71,9 @@ SECTIONS
*/
. = ALIGN(0x100);
- .text : { *(.text*) } :text =0x90909090
+ .text : {
+ *(.text*)
+ } :text =0x90909090
}
/*
--
1.6.0.2
The padding is read-only after all, so there is no reason to put it
into a writable section.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso32/int80.S | 2 +-
arch/x86/vdso/vdso32/syscall.S | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/vdso/vdso32/int80.S b/arch/x86/vdso/vdso32/int80.S
index b15b7c0..3f8c174 100644
--- a/arch/x86/vdso/vdso32/int80.S
+++ b/arch/x86/vdso/vdso32/int80.S
@@ -51,6 +51,6 @@ __kernel_vsyscall:
* Pad out the segment to match the size of the sysenter.S version.
*/
VDSO32_vsyscall_eh_frame_size = 0x40
- .section .data,"aw",@progbits
+ .section .rodata,"a",@progbits
.space VDSO32_vsyscall_eh_frame_size-(.LENDFDEDLSI-.LSTARTFRAMEDLSI), 0
.previous
diff --git a/arch/x86/vdso/vdso32/syscall.S b/arch/x86/vdso/vdso32/syscall.S
index 5415b56..7def1fe 100644
--- a/arch/x86/vdso/vdso32/syscall.S
+++ b/arch/x86/vdso/vdso32/syscall.S
@@ -72,6 +72,6 @@ __kernel_vsyscall:
* Pad out the segment to match the size of the sysenter.S version.
*/
VDSO32_vsyscall_eh_frame_size = 0x40
- .section .data,"aw",@progbits
+ .section .rodata,"a",@progbits
.space VDSO32_vsyscall_eh_frame_size-(.LENDFDE1-.LSTARTFRAME), 0
.previous
--
1.6.0.2
The vDSO is mapped read-only into the process' address space, so
any write accesses to it are broken and would segfault.
Additionally, if there is any uninitialized data, the vDSO setup
code does not allocate any space for it, so this is doubly broken.
The .dynbss section is a place to put symbols which are defined by
dynamic objects, are referenced by regular objects, and are not
functions. Space for these objects is allocated in the process image,
and the dynamic linker copies the object data (using a copy relocation).
So, there should never ever be a .dynbss section in a shared object
(and GNU binutils can't produce one, for sure), but then we can place
it into .broken, too.
As a side effect, the .data section now only contains the Global Offset
Table. Give it a more appropriate name for that.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/vdso-layout.lds.S | 17 +++++++++++------
1 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 74fc5ae..53317a6 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -48,13 +48,8 @@ SECTIONS
.rodata : {
*(.rodata*)
} :text
- .data : {
- *(.data*)
+ .got : {
*(.got.plt) *(.got)
- *(.gnu.linkonce.d.*)
- *(.bss*)
- *(.dynbss*)
- *(.gnu.linkonce.b.*)
}
/*
@@ -76,6 +71,16 @@ SECTIONS
*/
.broken : {
/*
+ * The vDSO is mapped read-only, so any writable
+ * sections are broken (and will segfault at runtime).
+ * Additionally, space for uninitialized data is not
+ * even allocated by the vDSO setup code.
+ */
+ *(.data* .gnu.linkonce.d.*)
+ *(.bss* .gnu.linkonce.b.*)
+ *(.dynbss*)
+
+ /*
* Code in the Procedure Linkage Table will segfault.
*/
*(.plt)
--
1.6.0.2
There should be no real entries in the GOT, because they are basically
pointers to dynamic symbols, and that will not work correctly without
a real dynamic linker for the vDSO.
However, the ABI pre-defines three entries in the GOT which are always
present, so the GOT section is never completely empty. We can check
that there are no extra entries beyond these three.
To make it work, pass -m32 or -m64 to the pre-processor to get the
correct definition of __SIZEOF_POINTER__.
Signed-off-by: Petr Tesarik <[email protected]>
---
arch/x86/vdso/Makefile | 5 +++--
arch/x86/vdso/vdso-layout.lds.S | 16 ++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index 16a9020..8c7f06a 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -23,7 +23,8 @@ $(obj)/vdso.o: $(obj)/vdso.so
targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
-export CPPFLAGS_vdso.lds += -P -C
+vdso-cppflags = -P -C
+export CPPFLAGS_vdso.lds += -m64 $(vdso-cppflags)
VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
@@ -68,7 +69,7 @@ vdso32.so-$(VDSO32-y) += sysenter
vdso32-images = $(vdso32.so-y:%=vdso32-%.so)
-CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
+CPPFLAGS_vdso32.lds = -m32 $(vdso-cppflags)
VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
# This makes sure the $(obj) subdirectory exists even though vdso32/
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 53317a6..0bef418 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -128,6 +128,22 @@ SECTIONS
*/
ASSERT(!SIZEOF(.broken), "The vdso linker script found a section that is bad. See vdso-layout.lds.S for details.");
+/* This assert is triggered if the resulting GOT is larger than the
+ * minimum defined by the ABI, i.e. there is some actual use of the
+ * GOT.
+ *
+ * To find the offending symbols you may:
+ * 1. temporarily disable this check
+ * 2. examine the dynamic relocations of the resulting vDSO with
+ * objdump -R
+ *
+ * To find the places where the symbols were used, you may:
+ * 1. add -Wl,--emit-relocs to VDSO_LDFLAGS
+ * 2. run objdump -r on the resulting vDSO and look for all
+ * GOT-type relocations.
+ */
+ASSERT(SIZEOF(.got) == 3*__SIZEOF_POINTER__, "The vdso linker script found a wrong reference to an external object. See vdso-layout.lds.S for details.");
+
/*
* Very old versions of ld do not recognize this name token; use the constant.
*/
--
1.6.0.2
Petr Tesarik píše v Út 16. 06. 2009 v 14:55 +0200:
> The handling of various sections in the VDSO linker script
> looks pretty haphazard. This patch series cleans it up in
> these regards:
>
> - improve the coding style
> - remove superfluous sections
> - issue a linker error if a section is encountered which
> is known not to work
> - check that the .got section is empty, except for the
> three entries defined by the ABI
> - discard sections which are not useful to user-space
>
> Petr Tesarik (9):
> x86: Adjust the coding style of vdso-layout.lds.S
> x86: Remove .sdata from the vDSO linker script
> x86: add .broken section to the vDSO linker script
> x86: mark altinstr-related sections in vDSO as broken
> x86: mark some standard sections as broken in a vDSO
> x86: move 32-bit vDSO padding from .data to .rodata
> x86: mark writable vDSO sections as broken
> x86: check the size of GOT in vDSO
> x86: remove .gnu.warning* sections from the vDSO
>
> arch/x86/vdso/Makefile | 5 +-
> arch/x86/vdso/vdso-layout.lds.S | 158 ++++++++++++++++++++++++++++++++-------
> arch/x86/vdso/vdso32/int80.S | 2 +-
> arch/x86/vdso/vdso32/syscall.S | 2 +-
> 4 files changed, 136 insertions(+), 31 deletions(-)
Any plans with this patchset? Is it waiting for somebody's Ack?
Petr Tesarik
Petr Tesarik wrote:
>
> Any plans with this patchset? Is it waiting for somebody's Ack?
>
Now when the merge window is closed I'm going to review it for .32 most
likely within the next week... I don't think it's super-urgent partly
because it looks to be in good shape. The fact that I don't consider it
urgent doesn't mean I don't consider it important -- the lack of urgency
is mostly just a matter of when it first showed up in the kernel cycle.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.