mirror of
https://github.com/dart-lang/sdk
synced 2024-10-02 23:39:19 +00:00
[gn] Support producing signed builds on Mac
This can be controlled via codesigning_identity GN arg. For example, setting codesigning_identity="-" would produce ad-hoc signed binaries. This CL also includes changes in vm/cc tests which are needed for tests to be green when running with hardened runtime. Issue https://github.com/dart-lang/sdk/issues/53928 Tested: enabled ad-hoc signing and tested on bots. Cq-Include-Trybots: luci.dart.try:vm-mac-debug-arm64-try,vm-mac-release-arm64-try,vm-mac-release-x64-try,vm-mac-debug-x64-try Change-Id: I3c3a6265c62b2904e43a326b7d8223bcfd393577 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/333401 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
parent
ad2708d071
commit
4ce23629eb
|
@ -14,6 +14,7 @@ assert(host_os == "mac")
|
|||
import("//build/config/sysroot.gni")
|
||||
import("//build/toolchain/goma.gni")
|
||||
import("//build/toolchain/rbe.gni")
|
||||
import("//build/toolchain/signing.gni")
|
||||
|
||||
if (use_goma) {
|
||||
assembler_prefix = "$goma_dir/gomacc "
|
||||
|
@ -189,20 +190,44 @@ template("mac_toolchain") {
|
|||
stripped_outfile = "{{root_out_dir}}/exe.stripped/$exename"
|
||||
}
|
||||
|
||||
command = "$ld $sysroot_flags $toolchain_flags {{ldflags}} -Xlinker -rpath -Xlinker @executable_path/Frameworks -o $outfile -Wl,-filelist,$rspfile {{solibs}} {{libs}} {{frameworks}}"
|
||||
commands = [ "$ld $sysroot_flags $toolchain_flags {{ldflags}} -Xlinker -rpath -Xlinker @executable_path/Frameworks -o $outfile -Wl,-filelist,$rspfile {{solibs}} {{libs}} {{frameworks}}" ]
|
||||
|
||||
symbolizer_script =
|
||||
rebase_path("//runtime/tools/dart_profiler_symbols.py")
|
||||
symbolize_command =
|
||||
"$symbolizer_script --nm $nm --output $symfile --binary $outfile"
|
||||
command += " && $symbolize_command"
|
||||
commands +=
|
||||
[ "$symbolizer_script --nm $nm --output $symfile --binary $outfile" ]
|
||||
|
||||
if (defined(invoker.strip)) {
|
||||
strip = invoker.strip
|
||||
strip_command = "${strip} -x -o $stripped_outfile $outfile"
|
||||
command += " && " + strip_command
|
||||
commands += [ "${strip} -x -o $stripped_outfile $outfile" ]
|
||||
}
|
||||
|
||||
if (codesigning_identity != "") {
|
||||
# codesign tool performs signing in-place. This does not fit very well
|
||||
# into the overall build: we would have to produce unsigned binary with
|
||||
# some suffix (e.g. dart_unsigned), then copy it to the final location
|
||||
# and sign. To avoid this dance we choose to perform signing here
|
||||
# at the link step. Unfortunately this also comes with some limitations:
|
||||
# executable target can't push arbitrary configuration variables down
|
||||
# to the link step. Which means we can't specify per target
|
||||
# entitlement files - and instead rely on dart_codesign.py script to
|
||||
# match binaries to their entitlement files by name.
|
||||
signing_script = rebase_path("//runtime/tools/dart_codesign.py")
|
||||
binaries_to_sign = [
|
||||
"--binary",
|
||||
outfile,
|
||||
]
|
||||
if (defined(stripped_outfile)) {
|
||||
binaries_to_sign += [
|
||||
"--binary",
|
||||
stripped_outfile,
|
||||
]
|
||||
}
|
||||
commands += [ "$signing_script --identity $codesigning_identity " +
|
||||
string_join(" ", binaries_to_sign) ]
|
||||
}
|
||||
|
||||
command = string_join(" && ", commands)
|
||||
description = "LINK $outfile"
|
||||
rspfile_content = "{{inputs_newline}}"
|
||||
outputs = [
|
||||
|
|
16
build/toolchain/signing.gni
Normal file
16
build/toolchain/signing.gni
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
# Defines code signing configuration for Mac builds.
|
||||
|
||||
declare_args() {
|
||||
# If codesigning_identity is not empty then all executables will be
|
||||
# signed using the specified identity and using corresponding entitlements
|
||||
# from runtime/tools/entitlements/${binary_name}.plist.
|
||||
#
|
||||
# You can specify codesigning_identity = "-" to use ad-hoc codesigning.
|
||||
#
|
||||
# See also runtime/tools/dart_codesigning.py script.
|
||||
codesigning_identity = ""
|
||||
}
|
63
runtime/tools/dart_codesign.py
Executable file
63
runtime/tools/dart_codesign.py
Executable file
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
#
|
||||
# Sign given binaries with using the specified signing identity and
|
||||
# using entitlements from runtime/tools/entitlement/${binary_name}.plist
|
||||
# if any.
|
||||
#
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
def SignBinary(identity, binary):
|
||||
codesign_args = [
|
||||
"--deep", "--force", "--verify", "--verbose", "--timestamp",
|
||||
"--options", "runtime", "--sign", identity
|
||||
]
|
||||
|
||||
name = os.path.basename(binary)
|
||||
|
||||
# Check if we have a matching entitlements file and apply it.
|
||||
# It would be simpler if we could specify it from outside but
|
||||
# GN does not give us tools for doing that: executable target can't
|
||||
# push arbitrary configuration down to the link tool where
|
||||
# we would like to perform code signing.
|
||||
entitlements_file = os.path.join(SCRIPT_DIR, "entitlements",
|
||||
name + ".plist")
|
||||
if os.path.exists(entitlements_file):
|
||||
codesign_args += ["--entitlements", entitlements_file]
|
||||
cmd = ["codesign"] + codesign_args + [binary]
|
||||
result = subprocess.run(cmd, capture_output=True, encoding="utf8")
|
||||
if result.returncode != 0:
|
||||
print("failed to run: " + " ".join(cmd))
|
||||
print(f"exit code: {result.returncode}")
|
||||
print("stdout:")
|
||||
print(result.stdout)
|
||||
print("stdout:")
|
||||
print(result.stderr)
|
||||
raise Exception("failed to codesign")
|
||||
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("--identity", type="string", help="Code signing identity")
|
||||
parser.add_option("--binary",
|
||||
type="string",
|
||||
action="append",
|
||||
help="Binary to sign")
|
||||
options = parser.parse_args()[0]
|
||||
|
||||
if not options.identity:
|
||||
raise Exception("Missing code signing identity (--identity)")
|
||||
|
||||
if not options.binary:
|
||||
raise Exception("Missing binaries to sign (--binary)")
|
||||
|
||||
for binary in options.binary:
|
||||
SignBinary(options.identity, binary)
|
6
runtime/tools/entitlements/README.md
Normal file
6
runtime/tools/entitlements/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
These entitlement configurations are used when GN arg codesigning_identity
|
||||
is set to non-empty string.
|
||||
|
||||
They must be kept in sync with [entitlements][1] used for codesigning releases:
|
||||
|
||||
[1]: https://dart.googlesource.com/recipes/+/refs/heads/main/recipes/release/sign-mac.resources/Entitlements_dart.plist
|
10
runtime/tools/entitlements/dart.plist
Normal file
10
runtime/tools/entitlements/dart.plist
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
10
runtime/tools/entitlements/dart_precompiled_runtime.plist
Normal file
10
runtime/tools/entitlements/dart_precompiled_runtime.plist
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
8
runtime/tools/entitlements/gen_snapshot.plist
Normal file
8
runtime/tools/entitlements/gen_snapshot.plist
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
8
runtime/tools/entitlements/gen_snapshot_product.plist
Normal file
8
runtime/tools/entitlements/gen_snapshot_product.plist
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
10
runtime/tools/entitlements/run_vm_tests.plist
Normal file
10
runtime/tools/entitlements/run_vm_tests.plist
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -199,7 +199,7 @@ static void TestRegress38528(intptr_t header_overlap) {
|
|||
const uword page = VirtualMemory::PageSize();
|
||||
std::unique_ptr<VirtualMemory> blob(VirtualMemory::Allocate(
|
||||
2 * page,
|
||||
/*is_executable=*/false, /*is_compressed*/ false, "test"));
|
||||
/*is_executable=*/true, /*is_compressed=*/false, "test"));
|
||||
const intptr_t remainder_size = page / 2;
|
||||
const intptr_t alloc_size = page - header_overlap * kObjectAlignment;
|
||||
void* const other_code =
|
||||
|
|
|
@ -109,8 +109,18 @@ VM_UNIT_TEST_CASE(DuplicateRXVirtualMemory) {
|
|||
reinterpret_cast<void*>(page_start), 2 * page_size);
|
||||
EXPECT_NE(nullptr, vm);
|
||||
|
||||
#if defined(DART_HOST_OS_MACOS) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
// If we are not going to use vm_remap then we need to pass
|
||||
// is_executable=true so that pages get allocated with MAP_JIT flag if
|
||||
// necessary. Otherwise OS will kill us with a codesigning violation if
|
||||
// hardened runtime is enabled.
|
||||
const bool is_executable = true;
|
||||
#else
|
||||
const bool is_executable = false;
|
||||
#endif
|
||||
|
||||
VirtualMemory* vm2 = VirtualMemory::AllocateAligned(
|
||||
vm->size(), kPageSize, /*is_executable=*/false,
|
||||
vm->size(), kPageSize, is_executable,
|
||||
/*is_compressed=*/false, "FfiCallbackMetadata::TrampolinePage");
|
||||
bool ok = vm->DuplicateRX(vm2);
|
||||
EXPECT_EQ(true, ok);
|
||||
|
|
|
@ -330,6 +330,9 @@ def ToGnArgs(args, mode, arch, target_os, sanitizer, verify_sdk_hash):
|
|||
|
||||
gn_args['verify_sdk_hash'] = verify_sdk_hash
|
||||
|
||||
if args.codesigning_identity != '':
|
||||
gn_args['codesigning_identity'] = args.codesigning_identity
|
||||
|
||||
return gn_args
|
||||
|
||||
|
||||
|
@ -518,6 +521,10 @@ def AddCommonGnOptionArgs(parser):
|
|||
default=False,
|
||||
dest='use_mallinfo2',
|
||||
action='store_true')
|
||||
parser.add_argument('--codesigning-identity',
|
||||
help='Sign executables using the given identity.',
|
||||
default='',
|
||||
type=str)
|
||||
|
||||
|
||||
def AddCommonConfigurationArgs(parser):
|
||||
|
|
Loading…
Reference in a new issue