[PATCH v4 04/10] loader: Explicitly munmap() the preloader's ELF EHDR.
Jinoh Kang
jinoh.kang.kr at gmail.com
Fri Jan 28 12:52:01 CST 2022
On 1/29/22 03:40, Jinoh Kang wrote:
> Today, the preloader reserves some predefined address ranges without
> checking if there are any overlapping virtual memory mappings.
>
> One side effect of this behaviour is that the preloader's ELF EHDR gets
> unmapped. Note the following overlapping address ranges:
>
> - 0x00110000 - 0x68000000: low memory area (preload_info)
> - 0x08040000 - 0x08041000: preloader ELF EHDR (x86)
> - 0x00400000 - 0x00401000: preloader ELF EHDR (AMD64)
>
> In practice, unmapping the preloader ELF EHDR is harmless; this is
> because the dynamic linker does not recognise the preloader binary.
>
> Make the unmapping behaviour explicit by calling munmap() on the
> preloader's ELF EHDR.
Side note: without this patch, the next patch in the series will
leave the EHDR hanging around.
>
> Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
> ---
>
> Notes:
> v1 -> v2: fix comparing text segment start against EHDR start
>
> loader/preloader.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/loader/preloader.c b/loader/preloader.c
> index 94f5a264420..14ab42c2ffc 100644
> --- a/loader/preloader.c
> +++ b/loader/preloader.c
> @@ -227,6 +227,7 @@ struct
> * then jumps to the address wld_start returns.
> */
> void _start(void);
> +extern char __executable_start[];
> extern char _end[];
> __ASM_GLOBAL_FUNC(_start,
> __ASM_CFI("\t.cfi_undefined %eip\n")
> @@ -346,6 +347,15 @@ __ASM_GLOBAL_FUNC(wld_mmap,
> __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
> "\tret\n" )
>
> +static inline int wld_munmap( void *addr, size_t len )
> +{
> + int ret;
> + __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
> + : "=a" (ret) : "0" (91 /* SYS_munmap */), "r" (addr), "c" (len)
> + : "memory" );
> + return SYSCALL_RET(ret);
> +}
> +
> static inline int wld_prctl( int code, long arg )
> {
> int ret;
> @@ -365,6 +375,7 @@ void *thread_data[256];
> * then jumps to the address wld_start returns.
> */
> void _start(void);
> +extern char __executable_start[];
> extern char _end[];
> __ASM_GLOBAL_FUNC(_start,
> __ASM_CFI(".cfi_undefined %rip\n\t")
> @@ -428,6 +439,9 @@ SYSCALL_FUNC( wld_mmap, 9 /* SYS_mmap */ );
> int wld_mprotect( const void *addr, size_t len, int prot );
> SYSCALL_FUNC( wld_mprotect, 10 /* SYS_mprotect */ );
>
> +int wld_munmap( void *addr, size_t len );
> +SYSCALL_FUNC( wld_munmap, 11 /* SYS_munmap */ );
> +
> int wld_prctl( int code, long arg );
> SYSCALL_FUNC( wld_prctl, 157 /* SYS_prctl */ );
>
> @@ -454,6 +468,7 @@ void *thread_data[256];
> * then jumps to the address wld_start returns.
> */
> void _start(void);
> +extern char __executable_start[];
> extern char _end[];
> __ASM_GLOBAL_FUNC(_start,
> "mov x0, SP\n\t"
> @@ -534,6 +549,9 @@ SYSCALL_FUNC( wld_mmap, 222 /* SYS_mmap */ );
> int wld_mprotect( const void *addr, size_t len, int prot );
> SYSCALL_FUNC( wld_mprotect, 226 /* SYS_mprotect */ );
>
> +int wld_munmap( void *addr, size_t len );
> +SYSCALL_FUNC( wld_munmap, 215 /* SYS_munmap */ );
> +
> int wld_prctl( int code, long arg );
> SYSCALL_FUNC( wld_prctl, 167 /* SYS_prctl */ );
>
> @@ -560,6 +578,7 @@ void *thread_data[256];
> * then jumps to the address wld_start returns.
> */
> void _start(void);
> +extern char __executable_start[];
> extern char _end[];
> __ASM_GLOBAL_FUNC(_start,
> "mov r0, sp\n\t"
> @@ -632,6 +651,9 @@ void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offs
> int wld_mprotect( const void *addr, size_t len, int prot );
> SYSCALL_FUNC( wld_mprotect, 125 /* SYS_mprotect */ );
>
> +int wld_munmap( void *addr, size_t len );
> +SYSCALL_FUNC( wld_munmap, 91 /* SYS_munmap */ );
> +
> int wld_prctl( int code, long arg );
> SYSCALL_FUNC( wld_prctl, 172 /* SYS_prctl */ );
>
> @@ -1567,6 +1589,14 @@ void* wld_start( void **stack )
> preloader_start = (char *)_start - ((unsigned long)_start & page_mask);
> preloader_end = (char *)((unsigned long)(_end + page_mask) & ~page_mask);
>
> + if ((unsigned long)preloader_start >= (unsigned long)__executable_start + page_size)
> + {
> + /* Unmap preloader's ELF EHDR */
> + wld_munmap( __executable_start,
> + ((unsigned long)preloader_start -
> + (unsigned long)__executable_start) & ~page_mask );
> + }
> +
> #ifdef DUMP_AUX_INFO
> wld_printf( "stack = %p\n", state.s.stack );
> for( i = 0; i < state.s.argc; i++ ) wld_printf("argv[%lx] = %s\n", i, state.s.argv[i]);
>
--
Sincerely,
Jinoh Kang
More information about the wine-devel
mailing list