iOS,macOS: add unsigned_binaries.txt (flutter/engine#54977)

There are three categories of binaries produced as part of the framework artifacts:
* Those that use APIs that require entitlements and must be code-signed; e.g. gen_snapshot
* Those that do not use APIs that require entitlements and must be code-signed; e.g. Flutter.framework dylib.
* Those that do not need to be code-signed; e.g. Flutter.dSYM symbols.

Until now, our signing infrastructure has assumed that all mach-o binaries in the artifacts we produce require a signature. dSYM files are not required to be codesigned, although the xcframework containing them are, and as such they cannot be removed or tampered with.

The framework code-signing tests in `dev/bots/suite_runners/run_verify_binaries_codesigned_tests.dart` are only run on post-submit on release branches, and thus, this issue was not uncovered until the first release after all the dSYM work landed. Those tests were updated in https://github.com/flutter/flutter/pull/154591. This updates the framework and artifact archive generation code to also explicitly exclude those files from signing.

Issue: https://github.com/flutter/flutter/issues/154571
Related: https://github.com/flutter/flutter/issues/116493
Related: https://github.com/flutter/flutter/issues/153532

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
Chris Bracken 2024-09-05 16:12:42 -07:00 committed by GitHub
parent 3bef64d52b
commit 0669d07612
3 changed files with 52 additions and 19 deletions

View File

@ -168,24 +168,31 @@ def zip_archive(dst, args):
# the framework's `verifyCodeSignedTestRunner`. # the framework's `verifyCodeSignedTestRunner`.
# #
# See: https://github.com/flutter/flutter/blob/62382c7b83a16b3f48dc06c19a47f6b8667005a5/dev/bots/suite_runners/run_verify_binaries_codesigned_tests.dart#L82-L130 # See: https://github.com/flutter/flutter/blob/62382c7b83a16b3f48dc06c19a47f6b8667005a5/dev/bots/suite_runners/run_verify_binaries_codesigned_tests.dart#L82-L130
# Binaries that must be codesigned and require entitlements for particular APIs.
with_entitlements = ['gen_snapshot_arm64'] with_entitlements = ['gen_snapshot_arm64']
with_entitlements_file = os.path.join(dst, 'entitlements.txt') with_entitlements_file = os.path.join(dst, 'entitlements.txt')
sky_utils.write_codesign_config(with_entitlements_file, with_entitlements) sky_utils.write_codesign_config(with_entitlements_file, with_entitlements)
# Binaries that must be codesigned and DO NOT require entitlements.
without_entitlements = [ without_entitlements = [
'Flutter.xcframework/ios-arm64/Flutter.framework/Flutter', 'Flutter.xcframework/ios-arm64/Flutter.framework/Flutter',
'Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter', 'Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter',
'extension_safe/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter', 'extension_safe/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter',
'extension_safe/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter', 'extension_safe/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter',
] ]
without_entitlements_file = os.path.join(dst, 'without_entitlements.txt')
sky_utils.write_codesign_config(without_entitlements_file, without_entitlements)
# Binaries that will not be codesigned.
unsigned_binaries = []
if args.dsym: if args.dsym:
without_entitlements.extend([ unsigned_binaries.extend([
'Flutter.xcframework/ios-arm64/dSYMs/Flutter.framework.dSYM/Contents/Resources/DWARF/Flutter', 'Flutter.xcframework/ios-arm64/dSYMs/Flutter.framework.dSYM/Contents/Resources/DWARF/Flutter',
'extension_safe/Flutter.xcframework/ios-arm64/dSYMs/Flutter.framework.dSYM/Contents/Resources/DWARF/Flutter', 'extension_safe/Flutter.xcframework/ios-arm64/dSYMs/Flutter.framework.dSYM/Contents/Resources/DWARF/Flutter',
]) ])
unsigned_binaries_file = os.path.join(dst, 'unsigned_binaries.txt')
without_entitlements_file = os.path.join(dst, 'without_entitlements.txt') sky_utils.write_codesign_config(unsigned_binaries_file, unsigned_binaries)
sky_utils.write_codesign_config(without_entitlements_file, without_entitlements)
# pylint: enable=line-too-long # pylint: enable=line-too-long
zip_contents = [ zip_contents = [
@ -193,9 +200,12 @@ def zip_archive(dst, args):
'Flutter.xcframework', 'Flutter.xcframework',
'entitlements.txt', 'entitlements.txt',
'without_entitlements.txt', 'without_entitlements.txt',
'unsigned_binaries.txt',
'extension_safe/Flutter.xcframework', 'extension_safe/Flutter.xcframework',
] ]
sky_utils.assert_valid_codesign_config(dst, zip_contents, with_entitlements, without_entitlements) sky_utils.assert_valid_codesign_config(
dst, zip_contents, with_entitlements, without_entitlements, unsigned_binaries
)
sky_utils.create_zip(dst, 'artifacts.zip', zip_contents) sky_utils.create_zip(dst, 'artifacts.zip', zip_contents)

View File

@ -121,28 +121,38 @@ def zip_xcframework_archive(dst, args):
# the framework's `verifyCodeSignedTestRunner`. # the framework's `verifyCodeSignedTestRunner`.
# #
# See: https://github.com/flutter/flutter/blob/62382c7b83a16b3f48dc06c19a47f6b8667005a5/dev/bots/suite_runners/run_verify_binaries_codesigned_tests.dart#L82-L130 # See: https://github.com/flutter/flutter/blob/62382c7b83a16b3f48dc06c19a47f6b8667005a5/dev/bots/suite_runners/run_verify_binaries_codesigned_tests.dart#L82-L130
# Binaries that must be codesigned and require entitlements for particular APIs.
with_entitlements = [] with_entitlements = []
with_entitlements_file = os.path.join(dst, 'entitlements.txt') with_entitlements_file = os.path.join(dst, 'entitlements.txt')
sky_utils.write_codesign_config(with_entitlements_file, with_entitlements) sky_utils.write_codesign_config(with_entitlements_file, with_entitlements)
# Binaries that must be codesigned and DO NOT require entitlements.
without_entitlements = [ without_entitlements = [
'FlutterMacOS.xcframework/macos-arm64_x86_64/FlutterMacOS.framework/Versions/A/FlutterMacOS', 'FlutterMacOS.xcframework/macos-arm64_x86_64/FlutterMacOS.framework/Versions/A/FlutterMacOS',
] ]
if args.dsym:
without_entitlements.extend([
'FlutterMacOS.xcframework/macos-arm64_x86_64/dSYMs/FlutterMacOS.framework.dSYM/Contents/Resources/DWARF/FlutterMacOS',
])
without_entitlements_file = os.path.join(dst, 'without_entitlements.txt') without_entitlements_file = os.path.join(dst, 'without_entitlements.txt')
sky_utils.write_codesign_config(without_entitlements_file, without_entitlements) sky_utils.write_codesign_config(without_entitlements_file, without_entitlements)
# Binaries that will not be codesigned.
unsigned_binaries = []
if args.dsym:
unsigned_binaries.extend([
'FlutterMacOS.xcframework/macos-arm64_x86_64/dSYMs/FlutterMacOS.framework.dSYM/Contents/Resources/DWARF/FlutterMacOS',
])
unsigned_binaries_file = os.path.join(dst, 'unsigned_binaries.txt')
sky_utils.write_codesign_config(unsigned_binaries_file, unsigned_binaries)
# pylint: enable=line-too-long # pylint: enable=line-too-long
zip_contents = [ zip_contents = [
'FlutterMacOS.xcframework', 'FlutterMacOS.xcframework',
'entitlements.txt', 'entitlements.txt',
'without_entitlements.txt', 'without_entitlements.txt',
'unsigned_binaries.txt',
] ]
sky_utils.assert_valid_codesign_config(dst, zip_contents, with_entitlements, without_entitlements) sky_utils.assert_valid_codesign_config(
dst, zip_contents, with_entitlements, without_entitlements, unsigned_binaries
)
sky_utils.create_zip(dst, 'framework.zip', zip_contents) sky_utils.create_zip(dst, 'framework.zip', zip_contents)

View File

@ -25,7 +25,9 @@ def assert_file(path, what):
sys.exit(os.EX_NOINPUT) sys.exit(os.EX_NOINPUT)
def assert_valid_codesign_config(framework_dir, zip_contents, entitlements, without_entitlements): def assert_valid_codesign_config(
framework_dir, zip_contents, entitlements, without_entitlements, unsigned_binaries
):
"""Exits with exit code 1 if the codesign configuration contents are incorrect. """Exits with exit code 1 if the codesign configuration contents are incorrect.
All Mach-O binaries found within zip_contents exactly must be listed in All Mach-O binaries found within zip_contents exactly must be listed in
either entitlements or without_entitlements.""" either entitlements or without_entitlements."""
@ -37,7 +39,11 @@ def assert_valid_codesign_config(framework_dir, zip_contents, entitlements, with
log_error('ERROR: duplicate value(s) found in without_entitlements.txt') log_error('ERROR: duplicate value(s) found in without_entitlements.txt')
sys.exit(os.EX_DATAERR) sys.exit(os.EX_DATAERR)
if _contains_duplicates(entitlements + without_entitlements): if _contains_duplicates(unsigned_binaries):
log_error('ERROR: duplicate value(s) found in unsigned_binaries.txt')
sys.exit(os.EX_DATAERR)
if _contains_duplicates(entitlements + without_entitlements + unsigned_binaries):
log_error('ERROR: value(s) found in both entitlements and without_entitlements.txt') log_error('ERROR: value(s) found in both entitlements and without_entitlements.txt')
sys.exit(os.EX_DATAERR) sys.exit(os.EX_DATAERR)
@ -52,12 +58,13 @@ def assert_valid_codesign_config(framework_dir, zip_contents, entitlements, with
if _is_macho_binary(file): if _is_macho_binary(file):
binaries.add(os.path.relpath(file, framework_dir)) binaries.add(os.path.relpath(file, framework_dir))
# Verify that all Mach-O binaries are listed in either entitlements or without_entitlements. # Verify that all Mach-O binaries are listed in either entitlements,
listed_binaries = set(entitlements + without_entitlements) # without_entitlements, or unsigned_binaries.
listed_binaries = set(entitlements + without_entitlements + unsigned_binaries)
if listed_binaries != binaries: if listed_binaries != binaries:
log_error( log_error(
'ERROR: binaries listed in entitlements.txt and without_entitlements.txt do not ' 'ERROR: binaries listed in entitlements.txt, without_entitlements.txt, and'
'match the set of binaries in the files to be zipped' 'unsigned_binaries.txt do not match the set of binaries in the files to be zipped'
) )
log_error('Binaries found in files to be zipped:') log_error('Binaries found in files to be zipped:')
for file in sorted(binaries): for file in sorted(binaries):
@ -65,13 +72,19 @@ def assert_valid_codesign_config(framework_dir, zip_contents, entitlements, with
not_listed = sorted(binaries - listed_binaries) not_listed = sorted(binaries - listed_binaries)
if not_listed: if not_listed:
log_error('Binaries NOT LISTED in entitlements.txt/without_entitlements.txt:') log_error(
'Binaries NOT LISTED in entitlements.txt, without_entitlements.txt, '
'unsigned_binaries.txt:'
)
for file in not_listed: for file in not_listed:
log_error(' ' + file) log_error(' ' + file)
not_found = sorted(listed_binaries - binaries) not_found = sorted(listed_binaries - binaries)
if not_found: if not_found:
log_error('Binaries listed in entitlements.txt/without_entitlements.txt but NOT FOUND:') log_error(
'Binaries listed in entitlements.txt, without_entitlements.txt, '
'unsigned_binaries.txt but NOT FOUND:'
)
for file in not_found: for file in not_found:
log_error(' ' + file) log_error(' ' + file)
sys.exit(os.EX_NOINPUT) sys.exit(os.EX_NOINPUT)