loader: Don't return from __stack_chk_fail() stub in preloader.

GCC expects __stack_chk_fail() to be noreturn[1].  Returning from
__stack_chk_fail() can thus lead to subtle failures.

When crashing, use a volatile NULL pointer dereference.  Ideally we
would like to "abort()" here, but doing so would require two more
syscall definitions just for a cold function.  After all, the function
isn't even used at all if -fno-stack-protector is specified.

Also, don't say "stack smashing" (unlike glibc).  The preloader
currently initializes the stack canary value to a fixed value (0), which
serves little value in protecting against actual buffer overrun attacks.

[1]: https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gccint/Stack-Smashing-Protection.html
This commit is contained in:
Jinoh Kang 2023-09-02 18:24:49 +09:00 committed by Alexandre Julliard
parent 81f7329f4c
commit da74da2939
Notes: Alexandre Julliard 2023-09-04 22:20:12 +02:00
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/wine/-/merge_requests/3708

View file

@ -175,11 +175,6 @@ struct wld_auxv
*/
void __bb_init_func(void) { return; }
/* similar to the above but for -fstack-protector */
void *__stack_chk_guard = 0;
void __stack_chk_fail_local(void) { return; }
void __stack_chk_fail(void) { return; }
#ifdef __i386__
/* data for setting up the glibc-style thread-local storage in %gs */
@ -759,6 +754,33 @@ static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char
wld_exit(1);
}
/*
* The __stack_chk_* symbols are only used when file is compiled with gcc flags
* "-fstack-protector". This function is normally provided by libc's startup
* files, but since we build the preloader with "-nostartfiles -nodefaultlibs",
* we have to provide our own version to keep the linker happy.
*/
unsigned long __stack_chk_guard = 0;
void __attribute__((noreturn)) __stack_chk_fail(void)
{
static const char message[] = "preloader: stack overrun detected, crashing\n";
/* Avoid using non-syscall functions that can re-enter this function */
wld_write(2, message, sizeof(message) - 1);
/* Deliberate induce crash and possibly dump core */
*(volatile char *)0;
/* Last resort if the zero page turns out to be actually readable */
wld_exit(1);
}
void __attribute__((noreturn)) __stack_chk_fail_local(void)
{
__stack_chk_fail();
}
#ifdef DUMP_AUX_INFO
/*
* Dump interesting bits of the ELF auxv_t structure that is passed