Ver Fonte

riscv64, linker: make sure vdso lies inside .data

With current ldscript, linkers will put vdso data after `__kernel_end`,
which is buggy since we use the symbol to indicate the end of our kernel
image and newly allocated pages may overwrite those positions.

Change by place the vdso inside REGION_DATA. Remove old VDSO memory
region. Align .data section end to page size border.

Add a helper macro to retrieve .vdso section symbol addresses.

Signed-off-by: greatbridf <greatbridf@icloud.com>
greatbridf há 1 semana atrás
pai
commit
4d272fe8b2

+ 3 - 1
crates/eonix_hal/src/arch/riscv64/link.x

@@ -81,10 +81,12 @@ INSERT AFTER .rodata;
 SECTIONS {
     .vdso ALIGN(0x1000) : ALIGN(0x1000)
     {
+        VDSO_START = ABSOLUTE(.);
+
         KEEP(*(.vdso .vdso.*));
 
         . = ALIGN(0x1000);
-    } > VDSO AT> RAM
+    } > REGION_DATA AT> RAM
 
     VDSO_PADDR = LOADADDR(.vdso);
 }

+ 0 - 1
crates/eonix_hal/src/arch/riscv64/memory.x

@@ -3,7 +3,6 @@ ENTRY(_start)
 
 MEMORY {
     RAM    : org = 0x0000000080200000, len = 8M
-    VDSO   : org = 0x00007f0000000000, len = 4K
     KBSS   : org = 0xffffffff40000000, len = 2M
     KIMAGE : org = 0xffffffff80200000, len = 8M
 }

+ 2 - 2
crates/eonix_hal/src/link.x.in

@@ -18,7 +18,7 @@ SECTIONS {
         __srodata = .;
 
         *(.rodata .rodata.*);
-        
+
         . = ALIGN(8);
 
         PROVIDE(__eh_frame = .);
@@ -41,7 +41,7 @@ SECTIONS {
 
     } > REGION_DATA AT> LINK_REGION_DATA
 
-    .data.after :
+    .data.after : ALIGN(0x1000)
     {
         __data_after = .;
     } > REGION_DATA AT> LINK_REGION_DATA

+ 12 - 19
src/kernel/task/signal/signal_action.rs

@@ -20,6 +20,16 @@ use crate::kernel::constants::{EFAULT, EINVAL};
 use crate::kernel::syscall::UserMut;
 use crate::kernel::user::UserBuffer;
 
+macro_rules! vdso_sym_addr {
+    ($sym:expr) => {{
+        const VDSO_START_VADDR: VAddr = VAddr::from(0x7f00_0000_0000);
+        let vdso_link_start = eonix_hal::extern_symbol_addr!(VDSO_START);
+
+        eonix_hal::symbol_addr!($sym) - vdso_link_start
+            + VDSO_START_VADDR.addr()
+    }};
+}
+
 #[cfg(target_arch = "x86_64")]
 #[unsafe(naked)]
 #[unsafe(link_section = ".vdso.sigreturn")]
@@ -178,29 +188,12 @@ impl SignalAction {
             #[cfg(target_arch = "x86_64")]
             {
                 // TODO: Check and use `vdso_rt_sigreturn` for x86 as well.
-                static VDSO_SIGRETURN_ADDR: &'static unsafe extern "C" fn() =
-                    &(vdso_rt_sigreturn as unsafe extern "C" fn());
-
-                unsafe {
-                    // SAFETY: To prevent the compiler from optimizing this into `la` instructions
-                    //         and causing a linking error.
-                    (VDSO_SIGRETURN_ADDR as *const _ as *const usize)
-                        .read_volatile()
-                }
+                vdso_sym_addr!(vdso_rt_sigreturn)
             }
 
             #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))]
             {
-                static VDSO_RT_SIGRETURN_ADDR:
-                    &'static unsafe extern "C" fn() =
-                    &(vdso_rt_sigreturn as unsafe extern "C" fn());
-
-                unsafe {
-                    // SAFETY: To prevent the compiler from optimizing this into `la` instructions
-                    //         and causing a linking error.
-                    (VDSO_RT_SIGRETURN_ADDR as *const _ as *const usize)
-                        .read_volatile()
-                }
+                vdso_sym_addr!(vdso_rt_sigreturn)
             }
         };