0

[Mac] Add a crash key containing System Integrity Protection state

There have been several confusing crashes in the last few months where
knowing that SIP was a factor would have made them easier to
investigate.

System Integrity Policy is available via the private
`csr_get_active_config` system call, with CSR standing for Configurable
Security Restrictions. The raw policy value is logged along with two
specific flags that are of interest.

Change-Id: Ie92dad97308155a75416740edfba926b513b8a31
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6174054
Reviewed-by: Avi Drissman <avi@chromium.org>
Commit-Queue: Mark Rowe <markrowe@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1406432}
This commit is contained in:
Mark Rowe
2025-01-14 16:40:36 -08:00
committed by Chromium LUCI CQ
parent 19e42617c3
commit eda907474c
6 changed files with 120 additions and 71 deletions

@ -6,7 +6,7 @@
#import <Cocoa/Cocoa.h>
#include "content/common/mac/task_port_policy.h"
#include "content/common/mac/system_policy.h"
namespace content {

@ -17,7 +17,7 @@
#include "mojo/public/cpp/system/platform_handle.h"
#if BUILDFLAG(IS_MAC)
#include "content/common/mac/task_port_policy.h"
#include "content/common/mac/system_policy.h"
#endif
namespace content {

@ -338,8 +338,8 @@ source_set("common") {
sources += [
"mac/attributed_string_type_converters.h",
"mac/attributed_string_type_converters.mm",
"mac/task_port_policy.cc",
"mac/task_port_policy.h",
"mac/system_policy.cc",
"mac/system_policy.h",
]
deps += [ "//sandbox/mac:seatbelt" ]
}

@ -0,0 +1,113 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/mac/system_policy.h"
#include "base/debug/crash_logging.h"
#include "base/strings/stringprintf.h"
extern "C" {
int __mac_syscall(const char* policy, int op, void* arg);
int csr_get_active_config(uint32_t* config);
}
namespace content {
namespace {
// From AppleMobileFileIntegrity.kext`policy_syscall() on macOS 12.4 21F79.
enum AmfiStatusFlags {
// Boot arg: `amfi_unrestrict_task_for_pid`.
kAmfiOverrideUnrestrictedDebugging = 1 << 0,
// Boot arg: `amfi_allow_any_signature`.
kAmfiAllowInvalidSignatures = 1 << 1,
// Boot arg: `amfi_get_out_of_my_way`.
kAmfiAllowEverything = 1 << 2,
};
// From
// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.41.3/bsd/sys/csr.h
enum SystemSecurityPolicy : uint32_t {
AllowUntrustedKernelExtensions = 1 << 0,
AllowUnrestrictedFileSystem = 1 << 1,
AllowTaskForPid = 1 << 2,
AllowKernelDebugger = 1 << 3,
AllowAppleInternal = 1 << 4,
AllowUnrestrictedDTrace = 1 << 5,
AllowUnrestrictedNVRAM = 1 << 6,
AllowDeviceConfiguration = 1 << 7,
AllowAnyRecoveryOS = 1 << 8,
AllowUnapprovedKernelExtensions = 1 << 9,
AllowExecutablePolicyOverride = 1 << 10,
AllowUnauthenticatedRoot = 1 < 11,
AllowResearchGuests = 1 << 12,
};
base::expected<SystemSecurityPolicy, int> GetSystemSecurityPolicy() {
uint32_t policy = 0;
if (int error = csr_get_active_config(&policy)) {
return base::unexpected(error);
}
return base::expected<SystemSecurityPolicy, int>(
static_cast<SystemSecurityPolicy>(policy));
}
} // namespace
bool MachTaskPortPolicy::AmfiIsAllowEverything() const {
return (amfi_status & kAmfiAllowEverything) != 0;
}
base::expected<MachTaskPortPolicy, int> GetMachTaskPortPolicy() {
MachTaskPortPolicy policy;
// Undocumented MACF system call to Apple Mobile File Integrity.kext. In
// macOS 12.4 21F79 (and at least back to macOS 12.0), this returns a
// bitmask containing the AMFI status flags.
if (__mac_syscall("AMFI", 0x60, &policy.amfi_status) != 0) {
return base::unexpected(errno);
}
return policy;
}
void SetSystemPolicyCrashKeys() {
static auto* task_port_policy_crash_key = base::debug::AllocateCrashKeyString(
"amfi-status", base::debug::CrashKeySize::Size64);
static auto* system_security_policy_crash_key =
base::debug::AllocateCrashKeyString("system-integrity-protection",
base::debug::CrashKeySize::Size64);
auto task_port_policy = GetMachTaskPortPolicy();
if (task_port_policy.has_value()) {
base::debug::SetCrashKeyString(
task_port_policy_crash_key,
base::StringPrintf("rv=0 status=0x%llx allow_everything=%d",
task_port_policy->amfi_status,
task_port_policy->AmfiIsAllowEverything()));
} else {
base::debug::SetCrashKeyString(
task_port_policy_crash_key,
base::StringPrintf("rv=%d", task_port_policy.error()));
}
auto system_security_policy = GetSystemSecurityPolicy();
if (system_security_policy.has_value()) {
base::debug::SetCrashKeyString(
system_security_policy_crash_key,
base::StringPrintf(
"rv=0 status=0x%llx task_for_pid=%d kernel_debugger=%d",
system_security_policy.value(),
(system_security_policy.value() & AllowTaskForPid) != 0,
(system_security_policy.value() & AllowKernelDebugger) != 0));
} else {
base::debug::SetCrashKeyString(
system_security_policy_crash_key,
base::StringPrintf("rv=%d", task_port_policy.error()));
}
}
} // namespace content

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_MAC_TASK_PORT_POLICY_H_
#define CONTENT_COMMON_MAC_TASK_PORT_POLICY_H_
#ifndef CONTENT_COMMON_MAC_SYSTEM_POLICY_H_
#define CONTENT_COMMON_MAC_SYSTEM_POLICY_H_
#include <stdint.h>
@ -31,4 +31,4 @@ void SetSystemPolicyCrashKeys();
} // namespace content
#endif // CONTENT_COMMON_MAC_TASK_PORT_POLICY_H_
#endif // CONTENT_COMMON_MAC_SYSTEM_POLICY_H_

@ -1,64 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/mac/task_port_policy.h"
#include "base/debug/crash_logging.h"
#include "base/strings/stringprintf.h"
extern "C" {
int __mac_syscall(const char* policy, int op, void* arg);
}
namespace content {
namespace {
// From AppleMobileFileIntegrity.kext`policy_syscall() on macOS 12.4 21F79.
enum AmfiStatusFlags {
// Boot arg: `amfi_unrestrict_task_for_pid`.
kAmfiOverrideUnrestrictedDebugging = 1 << 0,
// Boot arg: `amfi_allow_any_signature`.
kAmfiAllowInvalidSignatures = 1 << 1,
// Boot arg: `amfi_get_out_of_my_way`.
kAmfiAllowEverything = 1 << 2,
};
} // namespace
bool MachTaskPortPolicy::AmfiIsAllowEverything() const {
return (amfi_status & kAmfiAllowEverything) != 0;
}
base::expected<MachTaskPortPolicy, int> GetMachTaskPortPolicy() {
MachTaskPortPolicy policy;
// Undocumented MACF system call to Apple Mobile File Integrity.kext. In
// macOS 12.4 21F79 (and at least back to macOS 12.0), this returns a
// bitmask containing the AMFI status flags.
if (__mac_syscall("AMFI", 0x60, &policy.amfi_status) != 0) {
return base::unexpected(errno);
}
return policy;
}
void SetSystemPolicyCrashKeys() {
static auto* crash_key = base::debug::AllocateCrashKeyString(
"amfi-status", base::debug::CrashKeySize::Size64);
auto task_port_policy = GetMachTaskPortPolicy();
if (task_port_policy.has_value()) {
base::debug::SetCrashKeyString(
crash_key,
base::StringPrintf("rv=0 status=0x%llx allow_everything=%d",
task_port_policy->amfi_status,
task_port_policy->AmfiIsAllowEverything()));
} else {
base::debug::SetCrashKeyString(
crash_key, base::StringPrintf("rv=%d", task_port_policy.error()));
}
}
} // namespace content