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`.
#
# 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_file = os.path.join(dst, 'entitlements.txt')
sky_utils.write_codesign_config(with_entitlements_file, with_entitlements)
# Binaries that must be codesigned and DO NOT require entitlements.
without_entitlements = [
'Flutter.xcframework/ios-arm64/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_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:
without_entitlements.extend([
unsigned_binaries.extend([
'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',
])
without_entitlements_file = os.path.join(dst, 'without_entitlements.txt')
sky_utils.write_codesign_config(without_entitlements_file, without_entitlements)
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
zip_contents = [
@ -193,9 +200,12 @@ def zip_archive(dst, args):
'Flutter.xcframework',
'entitlements.txt',
'without_entitlements.txt',
'unsigned_binaries.txt',
'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)

View File

@ -121,28 +121,38 @@ def zip_xcframework_archive(dst, args):
# the framework's `verifyCodeSignedTestRunner`.
#
# 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_file = os.path.join(dst, 'entitlements.txt')
sky_utils.write_codesign_config(with_entitlements_file, with_entitlements)
# Binaries that must be codesigned and DO NOT require entitlements.
without_entitlements = [
'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')
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
zip_contents = [
'FlutterMacOS.xcframework',
'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)

View File

@ -25,7 +25,9 @@ def assert_file(path, what):
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.
All Mach-O binaries found within zip_contents exactly must be listed in
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')
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')
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):
binaries.add(os.path.relpath(file, framework_dir))
# Verify that all Mach-O binaries are listed in either entitlements or without_entitlements.
listed_binaries = set(entitlements + without_entitlements)
# Verify that all Mach-O binaries are listed in either entitlements,
# without_entitlements, or unsigned_binaries.
listed_binaries = set(entitlements + without_entitlements + unsigned_binaries)
if listed_binaries != binaries:
log_error(
'ERROR: binaries listed in entitlements.txt and without_entitlements.txt do not '
'match the set of binaries in the files to be zipped'
'ERROR: binaries listed in entitlements.txt, without_entitlements.txt, and'
'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:')
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)
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:
log_error(' ' + file)
not_found = sorted(listed_binaries - binaries)
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:
log_error(' ' + file)
sys.exit(os.EX_NOINPUT)