Commit 518e394794160818ffe6826c874ff2f550c95bbb introduced new and important default behavior for PE binaries built using `winegcc`/`wineg++`/`winebuild`. * `/DYNAMICBASE` - Generates an executable image that can be randomly rebased at load time by using the address space layout randomization (ASLR) feature of Windows that was first available in Windows Vista. * `/HIGHENTROPYVA` - Randomized 64-bit virtual addresses make it more difficult for an attacker to guess the location of a particular memory region.
... however as identified in https://bugs.winehq.org/show_bug.cgi?id=58480, this new default behavior can severely impact applications that interact with binaries created for Windows XP and older. This is quite common for legacy audio plugins, such as VST2(TM) plugins.
This MR keeps the new default "dynamicbase" and "highentropyva" flags by default, but mirrors the mingw/msys2 `--disable-dynamicbase` flag as explained here: https://www.msys2.org/news/#2021-01-31-aslr-enabled-by-default. MSVC also provides a similarly named flag [here](https://learn.microsoft.com/en-us/cpp/build/reference/dynamicbase).
Downstream, the LMMS project has successfully deployed the mingw flag and the MSVC flag for our Windows builds. Our Linux builds use a custom wine-bridge and would benefit from the same.
We've currently tested this MR downstream against a snapshot of master branch to passing results.
Downstream PRs: * Linux: https://github.com/LMMS/lmms/pull/7987 * Windows: https://github.com/LMMS/lmms/pull/7976
From: Tres Finocchiaro tres.finocchiaro@gmail.com
--- tools/winebuild/main.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index b38c70dc71e..8683b5874de 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -36,6 +36,7 @@ int UsePIC = 0; int nb_errors = 0; int display_warnings = 0; +int disable_dynamicbase = 0; int native_arch = -1; int kill_at = 0; int verbose = 0; @@ -182,6 +183,7 @@ static const char usage_str[] = " --data-only Generate a data-only dll (i.e. without any executable code)\n" " -d, --delay-lib=LIB Import the specified library in delayed mode\n" " -D SYM Ignored for C flags compatibility\n" +" --disable-dynamicbase Disable 'ASLR' address space layout randomization (default: ASLR on)\n" " -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n" " -E, --export=FILE Export the symbols defined in the .spec or .def file\n" " --external-symbols Allow linking to external symbols\n" @@ -226,6 +228,7 @@ enum long_options_values { LONG_OPT_DLL = 1, LONG_OPT_DEF, + LONG_OPT_DISABLE_DYNAMICBASE, LONG_OPT_EXE, LONG_OPT_IMPLIB, LONG_OPT_BUILTIN, @@ -256,6 +259,7 @@ static const struct long_option long_options[] = /* mode options */ { "dll", 0, LONG_OPT_DLL }, { "def", 0, LONG_OPT_DEF }, + { "disable-dynamicbase", 0, LONG_OPT_DISABLE_DYNAMICBASE }, { "exe", 0, LONG_OPT_EXE }, { "implib", 0, LONG_OPT_IMPLIB }, { "staticlib", 0, LONG_OPT_STATICLIB }, @@ -436,6 +440,9 @@ static void option_callback( int optc, char *optarg ) case LONG_OPT_DEF: set_exec_mode( MODE_DEF ); break; + case LONG_OPT_DISABLE_DYNAMICBASE: + disable_dynamicbase = 1; + break; case LONG_OPT_EXE: set_exec_mode( MODE_EXE ); if (!main_spec->subsystem) main_spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; @@ -598,7 +605,13 @@ int main(int argc, char **argv) else { spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; - spec->dll_characteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; + if (!disable_dynamicbase) { + spec->dll_characteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; + } + } + + if (disable_dynamicbase) { + spec->dll_characteristics &= ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; }
check_target();
Switched PR to draft. Further testing shows that although `/DYNAMICBASE` fixes the underlying bug, the bug may be solely related to the 64-bit-only `/HIGHENTROPYVA` flag.
If this is the case, I would propose that the patch is modified to include **both** flags, similar to how mingw does it.
e.g.
`--disable-dynamicbase` `--disable-high-entropy-va`
Clearing either flag should work, there's no need to set both.