]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
Windows: Embed an application manifest in the EXE files
authorLasse Collin <lasse.collin@tukaani.org>
Tue, 1 Oct 2024 09:10:23 +0000 (12:10 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Tue, 1 Oct 2024 10:23:16 +0000 (13:23 +0300)
IMPORTANT: This includes a security fix to command line tool
           argument handling.

Some toolchains embed an application manifest by default to declare
UAC-compliance. Some also declare compatibility with Vista/8/8.1/10/11
to let the app access features newer than those of Vista.

We want all the above but also two more things:

  - Declare that the app is long path aware to support paths longer
    than 259 characters (this may also require a registry change).

  - Force the code page to UTF-8. This allows the command line tools
    to access files whose names contain characters that don't exist
    in the current legacy code page (except unpaired surrogates).
    The UTF-8 code page also fixes security issues in command line
    argument handling which can be exploited with malicious filenames.

Thanks to Orange Tsai and splitline from DEVCORE Research Team
for discovering this issue.

Thanks to Vijay Sarvepalli for reporting the issue to me.

Thanks to Kelvin Lee for testing with MSVC and helping with
the required build system fixes.

(cherry picked from commit 46ee0061629fb075d61d83839e14dd193337af59)

CMakeLists.txt
src/Makefile.am
src/common/common_w32res.rc
src/common/w32_application.manifest [new file with mode: 0644]

index 33fc36755b6e2081a372e821c85fb3fca92416af..a55892fd1c5672e6b85e420445db386aa09dbf3e 100644 (file)
@@ -112,6 +112,24 @@ else()
     set(PACKAGE_NAME "XZ Utils")
 endif()
 
+# When used with MSVC, CMake can merge .manifest files with
+# linker-generated manifests and embed the result in an executable.
+# However, when paired with MinGW-w64, CMake (3.30) ignores .manifest
+# files. Embedding a manifest with a resource file works with both
+# toochains. It's also the way to do it with Autotools.
+#
+# With MSVC, we need to disable the default manifest; attempting to add
+# two manifest entries would break the build. The flag /MANIFEST:NO
+# goes to the linker and it also affects behavior of CMake itself: it
+# looks what flags are being passed to the linker and when CMake sees
+# the /MANIFEST:NO option, other manifest-related linker flags are
+# no longer added (see the file Source/cmcmd.cxx in CMake).
+#
+# See: https://gitlab.kitware.com/cmake/cmake/-/issues/23066
+if(MSVC)
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
+endif()
+
 # Definitions common to all targets:
 add_compile_definitions(
     # Package info:
index d199e858a8d498069a5dea92343221d049573a56..a461a440a4bb414bca7a4b8422f768ca6d78e4e9 100644 (file)
@@ -39,4 +39,5 @@ EXTRA_DIST = \
        common/tuklib_physmem.c \
        common/tuklib_physmem.h \
        common/tuklib_progname.c \
-       common/tuklib_progname.h
+       common/tuklib_progname.h \
+       common/w32_application.manifest
index d05d22e761954556e5aa91c350e54ecf70ffc3a8..1f82577d5732dd105981f7a58c428be259f0900c 100644 (file)
@@ -50,3 +50,8 @@ BEGIN
         VALUE "Translation", 0x409, 1200
     END
 END
+
+/* Omit the manifest on Cygwin and MSYS2 (both define __CYGWIN__). */
+#if MY_TYPE == VFT_APP && !defined(__CYGWIN__)
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "w32_application.manifest"
+#endif
diff --git a/src/common/w32_application.manifest b/src/common/w32_application.manifest
new file mode 100644 (file)
index 0000000..2f87508
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+        <application>
+            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!-- Vista -->
+            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!-- 7 -->
+            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!-- 8 -->
+            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!-- 8.1 -->
+            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- 10/11 -->
+        </application>
+    </compatibility>
+
+    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+        <security>
+            <requestedPrivileges>
+                <requestedExecutionLevel level="asInvoker"/>
+            </requestedPrivileges>
+        </security>
+    </trustInfo>
+
+    <application xmlns="urn:schemas-microsoft-com:asm.v3">
+        <windowsSettings>
+            <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
+            <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
+        </windowsSettings>
+    </application>
+</assembly>