Skip to content

Commit

Permalink
Merge restore_win32-0.21+knots
Browse files Browse the repository at this point in the history
  • Loading branch information
luke-jr committed Dec 13, 2021
3 parents ee70e25 + 12bbfb6 + d37803a commit 849948e
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 20 deletions.
8 changes: 8 additions & 0 deletions .cirrus.yml
Expand Up @@ -63,6 +63,14 @@ task:
env:
FILE_ENV: "./ci/test/00_setup_env_arm.sh"

task:
name: 'Win32 [GOAL: deploy] [unit tests, no gui, no boost::process, no functional tests]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:bionic
env:
FILE_ENV: "./ci/test/00_setup_env_win32.sh"

task:
name: 'Win64 [GOAL: deploy] [unit tests, no gui, no boost::process, no functional tests]'
<< : *GLOBAL_TASK_TEMPLATE
Expand Down
5 changes: 5 additions & 0 deletions .travis.yml
Expand Up @@ -65,6 +65,11 @@ jobs:
script:
- set -o errexit; source ./ci/lint/06_script.sh

- stage: test
name: 'Win32 [GOAL: deploy] [unit tests, no gui, no boost::process, no functional tests]'
env: >-
FILE_ENV="./ci/test/00_setup_env_win32.sh"
- stage: test
name: 'PowerPC64 [GOAL: install] [unit tests, functional tests]'
os: linux
Expand Down
7 changes: 6 additions & 1 deletion Makefile.am
Expand Up @@ -25,7 +25,7 @@ BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT)
BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT)
BITCOIN_TX_BIN=$(top_builddir)/src/$(BITCOIN_TX_NAME)$(EXEEXT)
BITCOIN_WALLET_BIN=$(top_builddir)/src/$(BITCOIN_WALLET_TOOL_NAME)$(EXEEXT)
BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win64-setup$(EXEEXT)
BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT)

empty :=
space := $(empty) $(empty)
Expand Down Expand Up @@ -355,7 +355,12 @@ if TARGET_DARWIN
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_MACHO
endif
if TARGET_WINDOWS
ifeq ($(WINDOWS_BITS),32)
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_32bit_PE
endif
ifeq ($(WINDOWS_BITS),64)
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_PE
endif
endif
if TARGET_LINUX
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_ELF
Expand Down
21 changes: 21 additions & 0 deletions ci/test/00_setup_env_win32.sh
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
#
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

export LC_ALL=C.UTF-8

export CONTAINER_NAME=ci_win32
export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to win64 (bionic is used in the gitian build as well)
export HOST=i686-w64-mingw32
export DPKG_ADD_ARCH="i386"
export PACKAGES="python3 nsis g++-mingw-w64-i686 wine-binfmt wine32 file"
export RUN_FUNCTIONAL_TESTS=false
export RUN_SECURITY_TESTS="true"
export GOAL="deploy"
export BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests --without-boost-process"

# Compiler for MinGW-w64 causes false -Wreturn-type warning.
# See https://sourceforge.net/p/mingw-w64/bugs/306/
export NO_WERROR=1
7 changes: 6 additions & 1 deletion ci/test/wrap-wine.sh
Expand Up @@ -9,11 +9,16 @@ export LC_ALL=C.UTF-8
for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/univalue/{no_nul,test_json,unitester,object}}.exe; do
# shellcheck disable=SC2044
for b in $(find "${BASE_ROOT_DIR}" -executable -type f -name "$(basename $b_name)"); do
if (file "$b" | grep "Windows"); then
filetype="$(file -b "$b")"
if grep -q "Windows" <<<"${filetype}"; then
echo "Wrap $b ..."
mv "$b" "${b}_orig"
echo '#!/usr/bin/env bash' > "$b"
if grep -q "\b64\b" <<<"${filetype}"; then
echo "wine64 \"${b}_orig\" \"\$@\"" >> "$b"
else
echo "wine \"${b}_orig\" \"\$@\"" >> "$b"
fi
chmod +x "$b"
fi
done
Expand Down
22 changes: 15 additions & 7 deletions configure.ac
Expand Up @@ -602,20 +602,20 @@ case $host in
*mingw*)
TARGET_OS=windows
AC_CHECK_LIB([mingwthrd],[main],, AC_MSG_ERROR(libmingwthrd missing))
AC_CHECK_LIB([kernel32], [GetModuleFileNameA],, AC_MSG_ERROR(libkernel32 missing))
AC_CHECK_LIB([kernel32], [main],, AC_MSG_ERROR(libkernel32 missing))
AC_CHECK_LIB([user32], [main],, AC_MSG_ERROR(libuser32 missing))
AC_CHECK_LIB([gdi32], [main],, AC_MSG_ERROR(libgdi32 missing))
AC_CHECK_LIB([comdlg32], [main],, AC_MSG_ERROR(libcomdlg32 missing))
AC_CHECK_LIB([winmm], [main],, AC_MSG_ERROR(libwinmm missing))
AC_CHECK_LIB([shell32], [SHGetSpecialFolderPathW],, AC_MSG_ERROR(libshell32 missing))
AC_CHECK_LIB([shell32], [main],, AC_MSG_ERROR(libshell32 missing))
AC_CHECK_LIB([comctl32], [main],, AC_MSG_ERROR(libcomctl32 missing))
AC_CHECK_LIB([ole32], [CoCreateInstance],, AC_MSG_ERROR(libole32 missing))
AC_CHECK_LIB([ole32], [main],, AC_MSG_ERROR(libole32 missing))
AC_CHECK_LIB([oleaut32], [main],, AC_MSG_ERROR(liboleaut32 missing))
AC_CHECK_LIB([uuid], [main],, AC_MSG_ERROR(libuuid missing))
AC_CHECK_LIB([advapi32], [CryptAcquireContextW],, AC_MSG_ERROR(libadvapi32 missing))
AC_CHECK_LIB([ws2_32], [WSAStartup],, AC_MSG_ERROR(libws2_32 missing))
AC_CHECK_LIB([shlwapi], [PathRemoveFileSpecW],, AC_MSG_ERROR(libshlwapi missing))
AC_CHECK_LIB([iphlpapi], [GetAdaptersAddresses],, AC_MSG_ERROR(libiphlpapi missing))
AC_CHECK_LIB([advapi32], [main],, AC_MSG_ERROR(libadvapi32 missing))
AC_CHECK_LIB([ws2_32], [main],, AC_MSG_ERROR(libws2_32 missing))
AC_CHECK_LIB([shlwapi], [main],, AC_MSG_ERROR(libshlwapi missing))
AC_CHECK_LIB([iphlpapi], [main],, AC_MSG_ERROR(libiphlpapi missing))

dnl -static is interpreted by libtool, where it has a different meaning.
dnl In libtool-speak, it's -all-static.
Expand All @@ -632,6 +632,12 @@ case $host in
fi

CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0501 -DWIN32_LEAN_AND_MEAN"
case $host in
i?86-*) WINDOWS_BITS=32 ;;
x86_64-*) WINDOWS_BITS=64 ;;
*) AC_MSG_ERROR("Could not determine win32/win64 for installer") ;;
esac
AC_SUBST(WINDOWS_BITS)

dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against.
dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override
Expand Down Expand Up @@ -783,6 +789,8 @@ if test x$ac_cv_sys_large_files != x &&
CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
fi

AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"])

AX_GCC_FUNC_ATTRIBUTE([visibility])
AX_GCC_FUNC_ATTRIBUTE([dllexport])
AX_GCC_FUNC_ATTRIBUTE([dllimport])
Expand Down
23 changes: 20 additions & 3 deletions contrib/devtools/security-check.py
Expand Up @@ -194,14 +194,25 @@ def check_ELF_separate_code(executable):

def get_PE_dll_characteristics(executable) -> int:
'''Get PE DllCharacteristics bits'''
return get_PE_dll_arch_and_characteristics(executable)[1]

def get_PE_dll_arch_and_characteristics(executable):
'''
Get PE DllCharacteristics bits.
Returns a tuple (arch,bits) where arch is 'i386:x86-64' or 'i386'
and bits is the DllCharacteristics value.
'''
stdout = run_command([OBJDUMP_CMD, '-x', executable])

arch = ''
bits = 0
for line in stdout.splitlines():
tokens = line.split()
if len(tokens) >= 2 and tokens[0] == 'architecture:':
arch = tokens[1].rstrip(',')
if len(tokens)>=2 and tokens[0] == 'DllCharacteristics':
bits = int(tokens[1],16)
return bits
return (arch,bits)

IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
Expand All @@ -212,12 +223,18 @@ def check_PE_DYNAMIC_BASE(executable) -> bool:
bits = get_PE_dll_characteristics(executable)
return (bits & IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE) == IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE

# (64-bit only:)
# Must support high-entropy 64-bit address space layout randomization
# in addition to DYNAMIC_BASE to have secure ASLR.
def check_PE_HIGH_ENTROPY_VA(executable) -> bool:
'''PIE: DllCharacteristics bit 0x20 signifies high-entropy ASLR'''
bits = get_PE_dll_characteristics(executable)
return (bits & IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA) == IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
(arch,bits) = get_PE_dll_arch_and_characteristics(executable)
if arch == 'i386:x86-64':
reqbits = IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
else: # Unnecessary on 32-bit
assert(arch == 'i386')
reqbits = 0
return (bits & reqbits) == reqbits

def check_PE_RELOC_SECTION(executable) -> bool:
'''Check for a reloc section. This is required for functional ASLR.'''
Expand Down
15 changes: 15 additions & 0 deletions contrib/devtools/test-security-check.py
Expand Up @@ -44,6 +44,21 @@ def test_ELF(self):
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE', '-Wl,-z,separate-code']),
(0, ''))

def test_32bit_PE(self):
source = 'test1.c'
executable = 'test1.exe'
cc = 'i686-w64-mingw32-gcc'
write_testcode(source)

self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--no-nxcompat','-Wl,--no-dynamicbase','-no-pie','-fno-PIE']),
(1, executable+': failed DYNAMIC_BASE NX RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--no-dynamicbase','-no-pie','-fno-PIE']),
(1, executable+': failed DYNAMIC_BASE RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-no-pie','-fno-PIE']),
(1, executable+': failed RELOC_SECTION'))
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-pie','-fPIE']),
(0, ''))

def test_PE(self):
source = 'test1.c'
executable = 'test1.exe'
Expand Down
15 changes: 10 additions & 5 deletions contrib/gitian-descriptors/gitian-win.yml
Expand Up @@ -30,7 +30,7 @@ script: |
set -e -o pipefail
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-w64-mingw32"
HOSTS="i686-w64-mingw32 x86_64-w64-mingw32"
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests"
FAKETIME_HOST_PROGS="ar ranlib nm windres strip objcopy"
FAKETIME_PROGS="date makensis zip"
Expand Down Expand Up @@ -123,6 +123,11 @@ script: |
ORIGPATH="$PATH"
# Extract the git archive into a dir for each host and build
for i in ${HOSTS}; do
case $i in
i?86-* ) bin_name=win32 ;;
x86_64-*) bin_name=win64 ;;
*) bin_name=$i ;;
esac
export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH}
mkdir -p distsrc-${i}
cd distsrc-${i}
Expand All @@ -134,7 +139,7 @@ script: |
make ${MAKEOPTS}
make ${MAKEOPTS} -C src check-security
make ${MAKEOPTS} -C src check-symbols
make deploy BITCOIN_WIN_INSTALLER="${OUTDIR}/${DISTNAME}-win64-setup-unsigned.exe"
make deploy BITCOIN_WIN_INSTALLER="${OUTDIR}/${DISTNAME}-${bin_name}-setup-unsigned.exe"
make install DESTDIR=${INSTALLPATH}
cd installed
mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/
Expand All @@ -144,14 +149,14 @@ script: |
find ${DISTNAME}/bin -type f -executable -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg
find ${DISTNAME}/lib -type f -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg
cp ../doc/README_windows.txt ${DISTNAME}/readme.txt
find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i//x86_64-w64-mingw32/win64}.zip
find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i//x86_64-w64-mingw32/win64}-debug.zip
find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${bin_name}.zip
find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${bin_name}-debug.zip
cd ../../
rm -rf distsrc-${i}
done
cp -rf contrib/windeploy $BUILD_DIR
cd $BUILD_DIR/windeploy
mkdir unsigned
cp ${OUTDIR}/${DISTNAME}-win64-setup-unsigned.exe unsigned/
cp ${OUTDIR}/${DISTNAME}-*setup-unsigned.exe unsigned/
find . | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz
1 change: 1 addition & 0 deletions depends/README.md
Expand Up @@ -24,6 +24,7 @@ Common `host-platform-triplets` for cross compilation are:

- `i686-pc-linux-gnu` for Linux 32 bit
- `x86_64-pc-linux-gnu` for x86 Linux
- `i686-w64-mingw32` for Win32
- `x86_64-w64-mingw32` for Win64
- `x86_64-apple-darwin16` for macOS
- `arm-linux-gnueabihf` for Linux ARM 32 bit
Expand Down
14 changes: 11 additions & 3 deletions share/setup.nsi.in
@@ -1,4 +1,4 @@
Name "@PACKAGE_NAME@ (64-bit)"
Name "@PACKAGE_NAME@ (@WINDOWS_BITS@-bit)"

RequestExecutionLevel highest
SetCompressor /SOLID lzma
Expand Down Expand Up @@ -33,7 +33,9 @@ SetDateSave off
# Included files
!include Sections.nsh
!include MUI2.nsh
!if "@WINDOWS_BITS@" == "64"
!include x64.nsh
!endif

# Variables
Var StartMenuGroup
Expand All @@ -51,7 +53,11 @@ Var StartMenuGroup
!insertmacro MUI_LANGUAGE English

# Installer attributes
!if "@WINDOWS_BITS@" == "64"
InstallDir $PROGRAMFILES64\Bitcoin
!else
InstallDir $PROGRAMFILES\Bitcoin
!endif
CRCCheck on
XPStyle on
BrandingText " "
Expand Down Expand Up @@ -92,7 +98,7 @@ Section -post SEC0001
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory $SMPROGRAMS\$StartMenuGroup
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, 64-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" 1
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" 1
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
Expand Down Expand Up @@ -136,7 +142,7 @@ Section -un.post UNSEC0001
DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, 64-bit).lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk"
Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk"
Delete /REBOOTOK $INSTDIR\uninstall.exe
Delete /REBOOTOK $INSTDIR\debug.log
Expand All @@ -158,13 +164,15 @@ SectionEnd
# Installer functions
Function .onInit
InitPluginsDir
!if "@WINDOWS_BITS@" == "64"
${If} ${RunningX64}
; disable registry redirection (enable access to 64-bit portion of registry)
SetRegView 64
${Else}
MessageBox MB_OK|MB_ICONSTOP "Cannot install 64-bit version on a 32-bit system."
Abort
${EndIf}
!endif
FunctionEnd

# Uninstaller functions
Expand Down
3 changes: 3 additions & 0 deletions src/init.cpp
Expand Up @@ -931,6 +931,9 @@ bool AppInitBasicSetup(ArgsManager& args)
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif
#ifdef WIN32
// Enable Data Execution Prevention (DEP)
SetProcessDEPPolicy(PROCESS_DEP_ENABLE);

// Enable heap terminate-on-corruption
HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
#endif
Expand Down

0 comments on commit 849948e

Please sign in to comment.