Skip to content
101 changes: 100 additions & 1 deletion Build/lldb-mi/lldb-mi-sign.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ parameters:
archs: ["x86_64", "arm64"]

jobs:
- job:
- job: Sign
displayName: Sign LLDB-MI
pool:
name: VSEngSS-MicroBuild2022-1ES
steps:
Expand All @@ -27,4 +28,102 @@ jobs:
inputs:
targetPath: '$(Pipeline.Workspace)\Artifacts\lldb-mi_${{ arch }}.zip'
artifactName: 'lldb-mi_${{ arch }}_zip'

- job: VerifySignatures
displayName: Verify LLDB-MI signatures
dependsOn: Sign
pool:
vmImage: macOS-latest
steps:
- ${{ each arch in parameters.archs }}:
- task: DownloadPipelineArtifact@1
displayName: 'Downloading lldb-mi_${{ arch }}_zip'
inputs:
targetPath: '$(Pipeline.Workspace)/signed_lldb-mi_${{ arch }}'
artifactName: 'lldb-mi_${{ arch }}_zip'

- task: Bash@3
displayName: 'Verify lldb-mi_${{ arch }} signature'
inputs:
targetType: inline
script: |
set -euo pipefail

arch='${{ arch }}'
artifact_dir='$(Pipeline.Workspace)/signed_lldb-mi_${{ arch }}'
zip_path="${artifact_dir}/lldb-mi_${arch}.zip"
extract_dir="${artifact_dir}/extracted"
expected_binary="${extract_dir}/debugAdapters/lldb-mi_${arch}/bin/lldb-mi"
expected_entitlements='$(Build.SourcesDirectory)/Build/lldb-mi/debugger-entitlements.plist'

rm -rf "$extract_dir"
mkdir -p "$extract_dir"
unzip -q "$zip_path" -d "$extract_dir"

binary_count="$(find "$extract_dir" -type f -name lldb-mi | wc -l | tr -d '[:space:]')"
if [[ "$binary_count" != 1 || ! -f "$expected_binary" ]]; then
echo "##[error]Expected exactly one lldb-mi binary at $expected_binary."
find "$extract_dir" -name lldb-mi -print
exit 1
fi

actual_archs="$(lipo -archs "$expected_binary")"
if [[ "$actual_archs" != "$arch" ]]; then
echo "##[error]Expected architecture $arch, found $actual_archs."
exit 1
fi

codesign --verify --strict --verbose=4 "$expected_binary"
signature_details="$(codesign --display --verbose=4 "$expected_binary" 2>&1)"
printf '%s\n' "$signature_details"

if printf '%s\n' "$signature_details" | grep -q '^Signature=adhoc$'; then
echo '##[error]The final lldb-mi binary still has an ad-hoc signature.'
exit 1
fi

authority_count="$(printf '%s\n' "$signature_details" | grep -c '^Authority=' || true)"
if (( authority_count < 2 )); then
echo "##[error]Expected a signing authority chain, found $authority_count authority entries."
exit 1
fi

actual_entitlements="${artifact_dir}/actual-entitlements-${arch}.plist"
codesign --display --entitlements "$actual_entitlements" --xml "$expected_binary"
python3 - "$expected_entitlements" "$actual_entitlements" <<'PY'
import plistlib
import sys

with open(sys.argv[1], "rb") as expected_file:
expected = plistlib.load(expected_file)
with open(sys.argv[2], "rb") as actual_file:
actual = plistlib.load(actual_file)

if actual != expected:
print(f"##[error]Expected entitlements: {expected}")
print(f"##[error]Actual entitlements: {actual}")
sys.exit(1)
PY

tampered_binary="${artifact_dir}/tampered-lldb-mi-${arch}"
cp "$expected_binary" "$tampered_binary"
python3 - "$tampered_binary" <<'PY'
import os
import sys

tamper_offset = 16384
with open(sys.argv[1], "r+b") as binary_file:
if os.fstat(binary_file.fileno()).st_size <= tamper_offset:
print("##[error]The lldb-mi binary is too small for the tamper check.")
sys.exit(1)
binary_file.seek(tamper_offset)
original = binary_file.read(1)
binary_file.seek(tamper_offset)
binary_file.write(bytes([original[0] ^ 1]))
PY

if codesign --verify --strict --verbose=4 "$tampered_binary"; then
echo '##[error]codesign accepted a modified lldb-mi binary.'
exit 1
fi
...
45 changes: 40 additions & 5 deletions Build/lldb-mi/lldb-mi.template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,34 @@ jobs:
- job: LLDB_MI_${{ parameters.llvm_arch }}
timeoutInMinutes: 360
pool:
${{if eq(parameters['llvm_arch'], 'arm64')}}:
name: cpptoolsMacM1pool
name: Azure Pipelines
${{ if eq(parameters['llvm_arch'], 'arm64') }}:
vmImage: macOS-15-arm64
${{ else }}:
vmImage: macOS-latest
vmImage: macOS-15
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.11'
inputs:
versionSpec: '3.11'
${{ if eq(parameters['llvm_arch'], 'arm64') }}:
architecture: arm64
${{ else }}:
architecture: x64

- task: CmdLine@2
displayName: 'Verify Python 3.11'
inputs:
script: |
set -euo pipefail
python_executable="$(command -v python3)"
python_architecture="$("$python_executable" -c 'import platform; print(platform.machine())')"
if [[ "$python_architecture" != '${{ parameters.llvm_arch }}' ]]; then
echo "##[error]Expected Python architecture ${{ parameters.llvm_arch }}, found $python_architecture."
exit 1
fi
"$python_executable" -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))"

- task: CmdLine@2
displayName: 'Install Dependencies'
inputs:
Expand All @@ -53,6 +76,9 @@ jobs:
$1
}

python_executable="$(command -v python3)"
python_home="$("$python_executable" -c 'import sys; print(sys.prefix)')"

log_and_exec_cmd "sudo rm -rf /Library/Developer/CommandLineTools"
log_and_exec_cmd "sudo xcode-select --switch /Applications/XCode.app"

Expand All @@ -62,6 +88,11 @@ jobs:
log_and_exec_cmd "git clone ${{ parameters.llvm_repo }} llvm-project"
log_and_exec_cmd "cd llvm-project"
log_and_exec_cmd "git checkout ${{ parameters.llvm_commit }}"
if ! log_and_exec_cmd "git cherry-pick --no-commit 81fc5f7909a4ef5a8d4b5da2a10f77f7cb01ba63 73e15b5edb4fa4a77e68c299a6e3b21e610d351f f0a25fe0b746f56295d5c02116ba28d2f965c175"
then
echo "##[error] applying LLVM compatibility fixes failed"
exit 1
fi

log_and_exec_cmd "./lldb/scripts/macos-setup-codesign.sh"

Expand All @@ -70,7 +101,7 @@ jobs:
log_and_exec_cmd "mkdir $(Build.StagingDirectory)/buildspace/llvm-build"
log_and_exec_cmd "cd $(Build.StagingDirectory)/buildspace/llvm-build"

log_and_exec_cmd "cmake -DLLVM_ENABLE_PROJECTS=clang;lldb -DCMAKE_BUILD_TYPE=${{ parameters.llvm_build_type }} -DCMAKE_INSTALL_PREFIX=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=${{ parameters.llvm_arch }} ${{ parameters.llvm_additional_parameters }} -GNinja $(Build.StagingDirectory)/llvm-project/llvm"
log_and_exec_cmd "cmake -DLLVM_ENABLE_PROJECTS=clang;lldb -DCMAKE_BUILD_TYPE=${{ parameters.llvm_build_type }} -DCMAKE_INSTALL_PREFIX=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=${{ parameters.llvm_arch }} -DPYTHON_HOME=$python_home -DPython3_EXECUTABLE=$python_executable ${{ parameters.llvm_additional_parameters }} -GNinja $(Build.StagingDirectory)/llvm-project/llvm"
if [[ $? -ne 0 ]]
then
echo "##[error] cmake llvm failed"
Expand Down Expand Up @@ -112,7 +143,11 @@ jobs:
# Create a separate build directory for building lldb-mi.
log_and_exec_cmd "mkdir build"
log_and_exec_cmd "cd build"
log_and_exec_cmd "cmake -DCMAKE_PREFIX_PATH=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=${{ parameters.llvm_arch }} ${{ parameters.lldb_mi_additional_parameters }} -GNinja .."
if ! log_and_exec_cmd "cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_PREFIX_PATH=$(Build.StagingDirectory)/buildspace/llvm-inst/ -DCMAKE_OSX_ARCHITECTURES=${{ parameters.llvm_arch }} ${{ parameters.lldb_mi_additional_parameters }} -GNinja .."
then
echo "##[error] cmake lldb-mi failed"
exit 1
fi
log_and_exec_cmd "ninja"
if [[ $? -ne 0 ]]
then
Expand Down
Loading