build: compile kernel archives for the selected architecture and iOS version
This commit is contained in:
1 parent
f66b8b8fe6
commit
2d5a60af86
11 files changed
+152
-52
No files matched your search
@@ -0,0 +1,16 @@
|
||||
diff --git a/pexpert/pexpert/arm64/BCM2837.h b/pexpert/pexpert/arm64/BCM2837.h
|
||||
index 9c140d76..5a5574ea 100644
|
||||
--- a/pexpert/pexpert/arm64/BCM2837.h
|
||||
+++ b/pexpert/pexpert/arm64/BCM2837.h
|
||||
@@ -18,6 +18,11 @@
|
||||
#define __ARM_DEBUG__ 7
|
||||
#define __ARM64_PMAP_SUBPAGE_L1__ 1
|
||||
|
||||
+/* Native ARMv8.1+ targets select PAN explicitly; the original A53 target has none. */
|
||||
+#if defined(XNU_NATIVE_PAN) && XNU_NATIVE_PAN
|
||||
+#define __ARM_PAN_AVAILABLE__ 1
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* arm64e on a non-Apple ARMv8.3 CPU: pointer authentication uses the
|
||||
* architectural key registers (see HAS_NATIVE_PAC in arm64/pac_asm.h).
|
||||
@@ -0,0 +1,40 @@
|
||||
diff --git a/osfmk/prng/prng_random.c b/osfmk/prng/prng_random.c
|
||||
index 504b3fa7..3cda99ff 100644
|
||||
--- a/osfmk/prng/prng_random.c
|
||||
+++ b/osfmk/prng/prng_random.c
|
||||
@@ -502,3 +502,35 @@ random_bool_gen_bits(struct bool_gen * bg, unsigned int * buffer, unsigned int c
|
||||
}
|
||||
return rbits;
|
||||
}
|
||||
+
|
||||
+/* Internal source-provider verification; no replacement callbacks or skipped POST. */
|
||||
+#if defined(XNU_SOURCE_CORECRYPTO14)
|
||||
+#include <kern/startup.h>
|
||||
+#include <mach/kmod.h>
|
||||
+#include <mach-o/loader.h>
|
||||
+
|
||||
+extern struct mach_header_64 _mh_execute_header;
|
||||
+extern kern_return_t corecrypto_kext_start(kmod_info_t *, void *);
|
||||
+SECURITY_READ_ONLY_LATE(kern_return_t) source_corecrypto14_status = KERN_FAILURE;
|
||||
+
|
||||
+static void
|
||||
+source_corecrypto14_bootstrap(void)
|
||||
+{
|
||||
+ static kmod_info_t info = {
|
||||
+ .info_version = KMOD_INFO_VERSION,
|
||||
+ .name = "source-corecrypto14-evaluation",
|
||||
+ .version = "14.0",
|
||||
+ };
|
||||
+ uint32_t mode = 0;
|
||||
+
|
||||
+ if (PE_parse_boot_argn("fips_mode", &mode, sizeof(mode)) && mode != 0) {
|
||||
+ panic("source corecrypto verification requires complete default POST");
|
||||
+ }
|
||||
+ info.address = (vm_address_t)&_mh_execute_header;
|
||||
+ source_corecrypto14_status = corecrypto_kext_start(&info, NULL);
|
||||
+ if (source_corecrypto14_status != KERN_SUCCESS) {
|
||||
+ panic("source corecrypto initialization failed: %d", source_corecrypto14_status);
|
||||
+ }
|
||||
+}
|
||||
+STARTUP(EARLY_BOOT, STARTUP_RANK_FIRST, source_corecrypto14_bootstrap);
|
||||
+#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
diff --git a/bsd/kern/source_pthread_bootstrap.c b/bsd/kern/source_pthread_bootstrap.c
|
||||
new file mode 100644
|
||||
index 00000000..86a48e9c
|
||||
--- /dev/null
|
||||
+++ b/bsd/kern/source_pthread_bootstrap.c
|
||||
@@ -0,0 +1,23 @@
|
||||
+/* SPDX-License-Identifier: BSD-2-Clause-Patent */
|
||||
+#include <kern/startup.h>
|
||||
+#include <kern/debug.h>
|
||||
+#include <libkern/section_keywords.h>
|
||||
+#include <mach/kmod.h>
|
||||
+
|
||||
+extern kern_return_t pthread_start(kmod_info_t *, void *);
|
||||
+SECURITY_READ_ONLY_LATE(kern_return_t) source_pthread_status = KERN_FAILURE;
|
||||
+
|
||||
+static void
|
||||
+source_pthread_bootstrap(void)
|
||||
+{
|
||||
+ static kmod_info_t info = {
|
||||
+ .info_version = KMOD_INFO_VERSION,
|
||||
+ .name = "source-libpthread",
|
||||
+ .version = "519.120.4",
|
||||
+ };
|
||||
+ source_pthread_status = pthread_start(&info, NULL);
|
||||
+ if (source_pthread_status != KERN_SUCCESS) {
|
||||
+ panic("source libpthread registration failed: %d", source_pthread_status);
|
||||
+ }
|
||||
+}
|
||||
+STARTUP(EARLY_BOOT, STARTUP_RANK_SECOND, source_pthread_bootstrap);
|
||||
@@ -0,0 +1,7 @@
|
||||
CONFIG_XNU_BUILD_ARCHIVES=y
|
||||
CONFIG_XNU_SOURCE_CORECRYPTO14=y
|
||||
CONFIG_XNU_SOURCE_PTHREAD=y
|
||||
CONFIG_XNU_ARM_DT_PLATFORM=y
|
||||
CONFIG_XNU_ARMCPU=y
|
||||
CONFIG_XNU_NATIVE_ARCH_TIMER=y
|
||||
CONFIG_XNU_NATIVE_PAN=y
|
||||
@@ -25,3 +25,6 @@
|
||||
../../../../../patches/xnu-12377/public-pmap-without-monitor.patch
|
||||
../../../../../patches/xnu-12377/optional-kernel-support-archive.patch
|
||||
../../../../../patches/xnu-12377/public-missing-definitions.patch
|
||||
../../../../../patches/xnu-12377/source-corecrypto14-bootstrap.patch
|
||||
../../../../../patches/xnu-12377/source-pthread-bootstrap.patch
|
||||
../../../../../patches/xnu-12377/native-arm-pan.patch
|
||||
@@ -4,9 +4,10 @@ import argparse
|
||||
import json
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import subprocess
|
||||
|
||||
from kernel_target import TRIPLE, check_object
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
catalog = {entry['id']: entry for entry in tomllib.loads((ROOT / 'components.toml').read_text())['component']
|
||||
@@ -103,20 +104,8 @@ result = subprocess.run(command, cwd=record['directory'], stdout=subprocess.PIPE
|
||||
(out / 'compile.log').write_text(result.stdout)
|
||||
if result.returncode:
|
||||
raise SystemExit(result.stdout[-3500:])
|
||||
data = destination.read_bytes()
|
||||
magic, cpu, subtype, kind, count, size = struct.unpack_from('<6I', data)
|
||||
if (magic, cpu, subtype, kind) != (0xfeedfacf, 0x100000c, 0, 1):
|
||||
raise SystemExit('Unexpected platform object architecture')
|
||||
offset = 32
|
||||
deployment = None
|
||||
for _ in range(count):
|
||||
cmd, length = struct.unpack_from('<II', data, offset)
|
||||
if cmd == 0x32:
|
||||
deployment = struct.unpack_from('<II', data, offset + 8)
|
||||
offset += length
|
||||
if deployment != (2, 0x110000):
|
||||
raise SystemExit(f'Unexpected platform deployment {deployment}')
|
||||
check_object(destination.read_bytes(), component)
|
||||
archive = out / ('lib' + identifier + '.a')
|
||||
archive.unlink(missing_ok=True)
|
||||
subprocess.run(['xcrun', 'ar', 'rcs', archive, destination], check=True)
|
||||
print(f'{identifier}: -Werror build and actual ARM64/iOS 17 object audit passed')
|
||||
print(f'{identifier}: -Werror build and {TRIPLE} object audit passed')
|
||||
@@ -11,12 +11,12 @@ import json
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import subprocess
|
||||
import struct
|
||||
import sys
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / 'scripts'))
|
||||
import pbxproj
|
||||
from kernel_target import TRIPLE, check_object
|
||||
from xnu_symbols import kernel_names
|
||||
SOURCE = ROOT / 'refer/corecrypto-2023'
|
||||
REVISION = '11fba65b12d8830630e248dfa8344caf8b065f26'
|
||||
@@ -74,7 +74,7 @@ for header in SOURCE.glob('*/corecrypto/*.h'):
|
||||
link.symlink_to(header)
|
||||
sdk = subprocess.check_output(['xcrun', '--sdk', 'iphoneos', '--show-sdk-path'], text=True).strip()
|
||||
framework = ROOT / '.cache/fakeroot/System/Library/Frameworks/Kernel.framework/Versions/A'
|
||||
command = ['xcrun', '--sdk', 'iphoneos', 'clang', '-target', 'arm64-apple-ios17.0', '-isysroot', sdk,
|
||||
command = ['xcrun', '--sdk', 'iphoneos', 'clang', '-target', TRIPLE, '-isysroot', sdk,
|
||||
'-mkernel', '-ffreestanding', '-fno-builtin', '-fno-stack-check', '-std=gnu99', '-fblocks', '-O2',
|
||||
'-fno-vectorize', '-fno-slp-vectorize', '-mno-implicit-float',
|
||||
'-DKERNEL=1', '-DKERNEL_PRIVATE=1', '-DBUILDKERNEL=1', '-DCC_USE_ASM=0', '-DNDEBUG=1',
|
||||
@@ -114,7 +114,7 @@ with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
|
||||
failed = [result for result in results if result['exit_code']]
|
||||
report = {'source_url': 'https://github.com/ONLYA/corecrypto-2023', 'source_revision': REVISION,
|
||||
'provenance': 'Third-party source snapshot; not authenticated against an Apple archive',
|
||||
'module_version': '14.0', 'target': 'arm64-apple-ios17.0', 'assembly_enabled': False,
|
||||
'module_version': '14.0', 'target': TRIPLE, 'assembly_enabled': False,
|
||||
'compiled_sources': len(results), 'failures': len(failed), 'objects': results,
|
||||
'kernel_provider_registered': False, 'crypto_selftests_passed': False}
|
||||
(OUT / f'build-report{variant}.json').write_text(json.dumps(report, indent=2) + '\n')
|
||||
@@ -124,19 +124,7 @@ for result in failed[:8]:
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
for result in results:
|
||||
data = (object_dir / result['object']).read_bytes()
|
||||
magic, cpu, subtype, kind, count, size = struct.unpack_from('<6I', data)
|
||||
if (magic, cpu, subtype, kind) != (0xfeedfacf, 0x100000c, 0, 1):
|
||||
raise SystemExit(f'Wrong object architecture: {result["object"]}')
|
||||
offset = 32
|
||||
deployment = None
|
||||
for _ in range(count):
|
||||
cmd, length = struct.unpack_from('<II', data, offset)
|
||||
if cmd == 0x32:
|
||||
deployment = struct.unpack_from('<II', data, offset + 8)
|
||||
offset += length
|
||||
if deployment != (2, 0x110000):
|
||||
raise SystemExit(f'Wrong deployment: {result["object"]}: {deployment}')
|
||||
check_object((object_dir / result['object']).read_bytes(), result['object'])
|
||||
archive = OUT / f'libcorecrypto_kernel_noasm{variant}.a'
|
||||
archive.unlink(missing_ok=True)
|
||||
subprocess.run(['xcrun', 'ar', 'rcs', archive, *[object_dir / result['object'] for result in results]], check=True)
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build the matching Darwin 23 pthread kernel component and its real registration."""
|
||||
"""Build the pthread kernel component of the selected OS profile and its real registration."""
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / 'scripts'))
|
||||
from kernel_target import TRIPLE, check_object
|
||||
from xnu_symbols import kernel_names
|
||||
SOURCE = ROOT / 'refer/libpthread'
|
||||
REVISION = 'c0e60fb5ecfc54cf379c261d3f9572cc22ded891'
|
||||
# The OS profile pins the source; without it, the Darwin 23 revision.
|
||||
REVISION = os.environ.get('UNIXNU_LIBPTHREAD_COMMIT', 'c0e60fb5ecfc54cf379c261d3f9572cc22ded891')
|
||||
if subprocess.check_output(['git', '-C', SOURCE, 'rev-parse', 'HEAD'], text=True).strip() != REVISION:
|
||||
raise SystemExit('Unexpected libpthread source revision')
|
||||
if subprocess.check_output(['git', '-C', SOURCE, 'status', '--porcelain'], text=True):
|
||||
raise SystemExit('The libpthread reference must remain immutable')
|
||||
WORK = ROOT / '.cache/libpthread-work'
|
||||
if WORK.exists() and subprocess.check_output(['git', '-C', WORK, 'rev-parse', 'HEAD'], text=True).strip() != REVISION:
|
||||
shutil.rmtree(WORK)
|
||||
if not WORK.exists():
|
||||
subprocess.run(['git', 'clone', '--shared', SOURCE, WORK], check=True)
|
||||
for patch in sorted((ROOT / 'patches/libpthread').glob('*.patch')):
|
||||
@@ -47,7 +52,7 @@ def compile_one(source, destination, namespace=None):
|
||||
index += 1
|
||||
else:
|
||||
framework = ROOT / '.cache/fakeroot/System/Library/Frameworks/Kernel.framework/Versions/A'
|
||||
command = ['xcrun', '--sdk', 'iphoneos', 'clang', '-target', 'arm64-apple-ios17.0',
|
||||
command = ['xcrun', '--sdk', 'iphoneos', 'clang', '-target', TRIPLE,
|
||||
'-isysroot', sdk, '-mkernel', '-ffreestanding', '-fno-builtin', '-fno-stack-check',
|
||||
'-std=gnu11', '-fblocks', '-O2', '-mno-implicit-float',
|
||||
'-DKERNEL=1', '-DKERNEL_PRIVATE=1', '-DXNU_KERNEL_PRIVATE=1',
|
||||
@@ -62,19 +67,7 @@ def compile_one(source, destination, namespace=None):
|
||||
destination.with_suffix('.log').write_text(result.stdout)
|
||||
if result.returncode:
|
||||
raise SystemExit(result.stdout[-4500:])
|
||||
data = destination.read_bytes()
|
||||
if struct.unpack_from('<4I', data) != (0xfeedfacf, 0x100000c, 0, 1):
|
||||
raise SystemExit('Unexpected pthread object architecture')
|
||||
offset = 32
|
||||
deployment = None
|
||||
for _ in range(struct.unpack_from('<I', data, 16)[0]):
|
||||
cmd, length = struct.unpack_from('<II', data, offset)
|
||||
if cmd == 0x32:
|
||||
deployment = struct.unpack_from('<II', data, offset + 8)
|
||||
offset += length
|
||||
if deployment != (2, 0x110000):
|
||||
raise SystemExit(f'Unexpected pthread deployment: {deployment}')
|
||||
|
||||
check_object(destination.read_bytes(), destination.name)
|
||||
|
||||
def names(path, mode, global_only=True):
|
||||
result = subprocess.check_output(['xcrun', 'nm', *(['-g'] if global_only else []), mode, '-j', path], text=True)
|
||||
@@ -100,7 +93,7 @@ imports = set().union(*(names(path, '-u') for path in objects)) - definitions
|
||||
# The component is statically linked: os_log's DSO identity is the real
|
||||
# executable Mach-O header, synthesized by the Mach-O executable linker.
|
||||
missing = sorted(imports - kernel_names - {'___dso_handle'})
|
||||
report = {'revision': REVISION, 'sources': 3, 'ordinary_arm64_ios17_audited': True,
|
||||
report = {'revision': REVISION, 'sources': 3, 'target': TRIPLE, 'target_audited': True,
|
||||
'namespace_collisions_isolated': sorted(collisions), 'missing_kernel_names': missing,
|
||||
'linker_synthesized_symbols': ['___dso_handle'],
|
||||
'registration_observed': False}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Target of objects linked into the kernel: architecture and iOS deployment of the kernel build.
|
||||
|
||||
The kernel build exports UNIXNU_XNU_ARCH and UNIXNU_IOS_VERSION from the selected profiles. Without them
|
||||
the arm64 iOS 17.0 target is used.
|
||||
"""
|
||||
import os
|
||||
import struct
|
||||
|
||||
ARCH = os.environ.get('UNIXNU_XNU_ARCH', 'arm64')
|
||||
IOS_VERSION = os.environ.get('UNIXNU_IOS_VERSION', '17.0')
|
||||
TRIPLE = f'{ARCH}-apple-ios{IOS_VERSION}'
|
||||
_major, _minor = (IOS_VERSION.split('.') + ['0'])[:2]
|
||||
DEPLOYMENT = (2, int(_major) << 16 | int(_minor) << 8)
|
||||
_SUBTYPES = {'arm64': 0, 'arm64e': 2}
|
||||
if ARCH not in _SUBTYPES:
|
||||
raise SystemExit(f'Unsupported kernel architecture {ARCH}')
|
||||
SUBTYPE = _SUBTYPES[ARCH]
|
||||
|
||||
|
||||
def check_object(data, what):
|
||||
"""Refuse a relocatable object whose architecture or deployment differs from the kernel target."""
|
||||
magic, cpu, subtype, kind, count = struct.unpack_from('<5I', data)
|
||||
if (magic, cpu, subtype & 0xff, kind) != (0xfeedfacf, 0x100000c, SUBTYPE, 1):
|
||||
raise SystemExit(f'{what}: not an {ARCH} object')
|
||||
offset, deployment = 32, None
|
||||
for _ in range(count):
|
||||
command, length = struct.unpack_from('<II', data, offset)
|
||||
if command == 0x32:
|
||||
deployment = struct.unpack_from('<II', data, offset + 8)
|
||||
offset += length
|
||||
if deployment != DEPLOYMENT:
|
||||
raise SystemExit(f'{what}: deployment {deployment}, expected {DEPLOYMENT}')
|
||||
@@ -12,12 +12,15 @@ import json
|
||||
from pathlib import Path
|
||||
import struct
|
||||
|
||||
from kernel_target import ARCH, SUBTYPE
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('kernel', type=Path)
|
||||
args = parser.parse_args()
|
||||
data = bytearray(args.kernel.read_bytes())
|
||||
if struct.unpack_from('<4I', data) != (0xfeedfacf, 0x100000c, 0, 2):
|
||||
raise SystemExit('Expected a source-built ordinary ARM64 MH_EXECUTE kernel')
|
||||
magic, cpu, subtype, kind = struct.unpack_from('<4I', data)
|
||||
if (magic, cpu, subtype & 0xff, kind) != (0xfeedfacf, 0x100000c, SUBTYPE, 2):
|
||||
raise SystemExit(f'Expected a source-built {ARCH} MH_EXECUTE kernel')
|
||||
if b'_source_corecrypto14_bootstrap\0' not in data:
|
||||
raise SystemExit('Input does not contain the explicit source-provider bootstrap')
|
||||
offset = 32
|
||||
|
||||
@@ -23,7 +23,7 @@ def xnu_env(ctx):
|
||||
def version_env(modules, ctx=None):
|
||||
"""Source versions of the Apple references, from feeds.toml, for the kernel scripts."""
|
||||
env = {}
|
||||
for name, prefix in (('xnu', 'XNU'), ('libplatform', 'LIBPLATFORM'), ('libdispatch', 'LIBDISPATCH'), ('AvailabilityVersions', 'AVAILABILITYVERSIONS')):
|
||||
for name, prefix in (('xnu', 'XNU'), ('libplatform', 'LIBPLATFORM'), ('libdispatch', 'LIBDISPATCH'), ('AvailabilityVersions', 'AVAILABILITYVERSIONS'), ('libpthread', 'LIBPTHREAD')):
|
||||
module = modules.get(('refer', name))
|
||||
entry = module.source if module and module.source else {}
|
||||
if entry.get('ref'):
|
||||
|
||||
Reference in new issue
Block a user