Unlike the x86_64 linker script, the aarch64 version of it
does not align the size of the TLS segment to 64 bytes. In release
build it happens to be 64-bytes aligned, but the debug one does not
and causes the assertion fail in setup_tcb() as described by the issue
#1120.

The TLS segment does not need to be 64-bytes aligned in the loader ELF
file. However when we setup TCB block for each thread and initialize TLS
memory block for kernel and initial exec application ELF objects,
we need to make sure the start of the first application block starting
right after the kernel block is 64-bytes aligned.

In theory we could deal with a non 64-bytes aligned TLS segment by
modifying number of places in dynamic linker to align the kernel block
to 64 bytes. But it is easier to simply align up the size of the kernel TLS
segment right when we parse it out from kernel ELF in get_init() during
early boot phase. This actually works for both 64-bytes size aligned
segment in x64 build and unaligned one in aarch64 build, as logic
in all other relevant places will zero-out and initialize the correct
parts of kernel TLS block.

This patch also modifies arch_setup_tls() to zero-out the TLS block
for the 1st thread in similar way it is done in setup_tcb().

Fixes #1120

Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 arch/aarch64/arch-setup.cc | 2 +-
 core/elf.cc                | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc
index 30fb0db6..e22b4ea4 100644
--- a/arch/aarch64/arch-setup.cc
+++ b/arch/aarch64/arch-setup.cc
@@ -128,7 +128,7 @@ void arch_setup_free_memory()
 void arch_setup_tls(void *tls, const elf::tls_data& info)
 {
     struct thread_control_block *tcb;
-    memset(tls, 0, info.size + 1024);
+    memset(tls, 0, sizeof(*tcb) + info.size);
 
     tcb = (thread_control_block *)tls;
     tcb[0].tls_base = &tcb[1];
diff --git a/core/elf.cc b/core/elf.cc
index 06537be9..94e14b07 100644
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -1758,7 +1758,7 @@ init_table get_init(Elf64_Ehdr* header)
         } else if (phdr->p_type == PT_TLS) {
             ret.tls.start = reinterpret_cast<void*>(phdr->p_vaddr);
             ret.tls.filesize = phdr->p_filesz;
-            ret.tls.size = phdr->p_memsz;
+            ret.tls.size = align_up(phdr->p_memsz, (u64)64);
         }
     }
     return ret;
-- 
2.29.2

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20210225053616.228340-1-jwkozaczuk%40gmail.com.

Reply via email to