Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/sep-source.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
python3 -O -m unittest tools/aurora-sep/tests/test_store_open_errors.py -v
python3 -m unittest tools/aurora-sep/tests/test_identity_preservation.py -v
python3 -O -m unittest tools/aurora-sep/tests/test_identity_preservation.py -v
- name: Test selected-policy diagnostics
run: |
python3 -m unittest tools/aurora-sep/tests/test_diag_policy.py tools/aurora-sep/tests/test_diag_sensor.py -v
python3 -O -m unittest tools/aurora-sep/tests/test_diag_policy.py tools/aurora-sep/tests/test_diag_sensor.py -v
- name: Test recovery utility and package sources
run: |
python3 -m unittest tools/aurora-sep/tests/test_sep_bio_identities.py -v
Expand Down
49 changes: 46 additions & 3 deletions Documentation/ABI/testing/sysfs-driver-apple-sep
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ Date: October 2026
KernelVersion: 7.1
Contact: Chris Kearney <chris@kearneymail.com>
Description:
(RO) Version of the diag interface: "2" for the attributes
(RO) Version of the diag interface: "3" for the attributes
and values described in this file. Version 2 added
sensor_attach and restore; version 1 had neither.
sensor_attach and restore; version 1 had neither. Version 3
adds the policy snapshot.

Within a version, attributes are only added, and an existing
attribute keeps its values and their meaning. A reader tests
Expand All @@ -19,7 +20,8 @@ Description:
bring-up got without reading the kernel log. It exists while
the driver is bound to the SEP: it is created at probe and
removed at unbind. Every attribute in it is read-only and
reads as one ASCII token followed by a newline.
reads as ASCII followed by a newline. The policy snapshot
contains space-separated key=value tokens.

Each value is the state the driver recorded when it made the
corresponding decision. Reading an attribute sends nothing
Expand All @@ -30,6 +32,26 @@ Description:
by the boot-time bring-up, so the sensor and touchid
attributes only move on once something has opened it.

This deployment uses the existing T8122 profile and v4
/dev/sep-bio interface. It does not add a new sensor protocol.
OS firmware and system firmware are separate: qualify both.

For an existing bag, select xart_writes=1, provision_keybag=0,
xart_guard=1 and xarm_trace=1. trusted_keys=0 and
filevault_api=0 omit the optional kernel APIs; both default
to 1 to preserve existing deployments. There is no boot_uuid
parameter: the OS identity comes from /chosen/apfs-preboot-uuid.
Writable J613 26.6.2 attachment rejects a missing DT identity,
explicit UUID override or disabled guard before opening xART.
Host-store or identity-index read failure refuses attachment.

Preserve the current keybag, host store, reference key, three
Catacombs, ownership journal and fprint records. Different
Linux roots must share the same current files globally, before
module load; the kernel opens them from init_task's root.
Never replace them with a snapshot or enrol again to migrate.
Readiness diagnostics do not prove a successful finger match.

What: /sys/bus/platform/devices/<unit>.sep/diag/profile
Date: October 2026
KernelVersion: 7.1
Expand Down Expand Up @@ -359,3 +381,24 @@ Description:
tools/aurora-sep/XART-SAFETY.md. During a boot the value
can only move from "unverified" to "blocked", once the guard
refuses a write.

What: /sys/bus/platform/devices/<unit>.sep/diag/policy
Date: November 2026
KernelVersion: 7.2
Contact: Satya Benson <satya@benson.earth>
Description:
(RO, ABI 3) A space-separated key=value snapshot of the
driver policy selected at probe: xart_writes (effective store
writability), provision_keybag, xart_guard (effective level),
trusted_keys, filevault_api, xarm_trace, refkey_v2 and
identity_override (0 or 1). API flags describe the selected
policy, not successful registration if that API later fails.

identity_source is pending before the driver selects it, dt
for /chosen/apfs-preboot-uuid, override for explicit parameters,
or missing. It is updated at the actual identity decision.
No UUID value, state, identity or key bytes are exposed.
Reads only use cached facts and never contact the enclave.
Module-parameter sysfs files need not exist; their absence
is not evidence of a mismatched policy. Older diagnostic
ABIs retain xart/xart_guard and kernel decision messages.
44 changes: 44 additions & 0 deletions drivers/soc/apple/diag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ extern "C" {
sepos13: bool,
xart: bool,
) -> c_int;
fn sep_diag_set_policy(
provision_keybag: bool,
trusted_keys: bool,
filevault_api: bool,
xarm_trace: bool,
refkey_v2: bool,
identity_override: bool,
);
fn sep_diag_set_identity_source(source: c_uint);
fn sep_diag_set_attach(attached: bool);
fn sep_diag_set_endpoints(count: c_uint);
fn sep_diag_set_keystore_open();
Expand Down Expand Up @@ -66,6 +75,28 @@ pub(crate) enum Restore {
Unproven = 3,
}

/// Boot-time policy, without identity values or key material.
pub(crate) struct Policy {
pub provision_keybag: bool,
pub trusted_keys: bool,
pub filevault_api: bool,
pub xarm_trace: bool,
pub refkey_v2: bool,
pub identity_override: bool,
}

/// The source selected by prepare_os_uuid, not the UUID itself.
pub(crate) enum IdentitySource {
DeviceTree = 1,
Override = 2,
Missing = 3,
}

pub(crate) fn identity_source(source: IdentitySource) {
// SAFETY: this only stores the source enum in the passive cache.
unsafe { sep_diag_set_identity_source(source as c_uint) };
}

/// Adds the `diag` group to the SEP device, with the facts fixed at probe. The
/// group goes away when the driver unbinds.
///
Expand All @@ -76,6 +107,7 @@ pub(crate) fn register(
profile: &profile::PlatformProfile,
xart_writable: bool,
guard: Option<(u8, bool)>,
policy: Policy,
) -> Result {
// Exhaustive, so a new bootstrap or key store fails to build here until
// the ABI has a value for it.
Expand All @@ -97,6 +129,18 @@ pub(crate) fn register(
// SAFETY: no preconditions; stores three words.
unsafe { sep_diag_set_xart_guard(c_uint::from(level), list_loaded, matching() as c_int) };

// SAFETY: the facts are fixed before the attribute group is published.
unsafe {
sep_diag_set_policy(
policy.provision_keybag,
policy.trusted_keys,
policy.filevault_api,
policy.xarm_trace,
policy.refkey_v2,
policy.identity_override,
)
};

// SAFETY: `dev` is bound for the duration of the call, which is what devres
// needs. `profile.name` is a `str`, valid for reads of `profile.name.len()`
// bytes; the shim copies at most that many, needs no NUL terminator, and
Expand Down
58 changes: 57 additions & 1 deletion drivers/soc/apple/diag_shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "shim.h"

/* The contract version; see Documentation/ABI/testing/sysfs-driver-apple-sep. */
#define SEP_DIAG_ABI 2
#define SEP_DIAG_ABI 3

#define SEP_DIAG_ATTACH_PENDING 0
#define SEP_DIAG_ATTACH_ATTACHED 1
Expand Down Expand Up @@ -64,6 +64,13 @@ static struct {
bool cold;
bool sepos13;
bool xart;
bool provision_keybag;
bool trusted_keys;
bool filevault_api;
bool xarm_trace;
bool refkey_v2;
bool identity_override;
atomic_t identity_source;
/* The xART guard's effective level (0: none runs), and its list. */
unsigned int xart_guard;
bool xart_guard_list;
Expand Down Expand Up @@ -120,6 +127,54 @@ static ssize_t xart_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(xart);

/* Parameter policy is captured at probe; the identity choice is cached later. */
static ssize_t policy_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
const char *identity;

switch (atomic_read(&sep_diag.identity_source)) {
case 1:
identity = "dt";
break;
case 2:
identity = "override";
break;
case 3:
identity = "missing";
break;
default:
identity = "pending";
break;
}
return sysfs_emit(buf,
"xart_writes=%u provision_keybag=%u xart_guard=%u "
"trusted_keys=%u filevault_api=%u xarm_trace=%u "
"refkey_v2=%u identity_override=%u identity_source=%s\n",
sep_diag.xart, sep_diag.provision_keybag, sep_diag.xart_guard,
sep_diag.trusted_keys, sep_diag.filevault_api, sep_diag.xarm_trace,
sep_diag.refkey_v2, sep_diag.identity_override, identity);
}
static DEVICE_ATTR_RO(policy);

void sep_diag_set_policy(bool provision_keybag, bool trusted_keys,
bool filevault_api, bool xarm_trace, bool refkey_v2,
bool identity_override)
{
sep_diag.provision_keybag = provision_keybag;
sep_diag.trusted_keys = trusted_keys;
sep_diag.filevault_api = filevault_api;
sep_diag.xarm_trace = xarm_trace;
sep_diag.refkey_v2 = refkey_v2;
sep_diag.identity_override = identity_override;
atomic_set(&sep_diag.identity_source, 0);
}

void sep_diag_set_identity_source(unsigned int source)
{
atomic_set(&sep_diag.identity_source, source);
}

static ssize_t attach_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
Expand Down Expand Up @@ -346,6 +401,7 @@ static struct attribute *sep_diag_attrs[] = {
&dev_attr_boot.attr,
&dev_attr_protocol.attr,
&dev_attr_xart.attr,
&dev_attr_policy.attr,
&dev_attr_attach.attr,
&dev_attr_endpoints.attr,
&dev_attr_keystore.attr,
Expand Down
27 changes: 27 additions & 0 deletions drivers/soc/apple/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,3 +720,30 @@ mod dart_window_tests {
}
}
}

/// The owner-qualified J613 OS-firmware lane; system firmware may differ.
pub(crate) fn j613_26_6_2() -> bool {
machine_has(b"apple,j613")
&& chosen_string(c"asahi,os-fw-version")
.as_deref()
.is_some_and(os_firmware_26_6_2)
}

fn os_firmware_26_6_2(raw: &[u8]) -> bool {
raw == b"26.6.2" || raw == b"26.6.2\0"
}

#[cfg(CONFIG_APPLE_SEP_KUNIT_TEST)]
#[kernel::macros::kunit_tests(apple_sep_j613_firmware)]
mod j613_firmware_tests {
use super::*;

#[test]
fn exact_os_firmware_only() {
assert!(os_firmware_26_6_2(b"26.6.2"));
assert!(os_firmware_26_6_2(b"26.6.2\0"));
for raw in [&b"14.8.3"[..], &b"26.6.20"[..], &b"27.0"[..], &b""[..]] {
assert!(!os_firmware_26_6_2(raw));
}
}
}
51 changes: 46 additions & 5 deletions drivers/soc/apple/sep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,18 @@ impl SepData {
let xart_start = module_parameters::xart_start_sector.value();
let xart_guard =
xart_guard::level(module_parameters::xart_guard.value(), profile.xart_guard);
// The qualified 26.6.2 lane uses only the boot-forwarded identity.
// Check before opening the shared xART store writable.
if profile::j613_26_6_2() && xart_writes {
if dt::preboot_uuid().is_none()
|| module_parameters::os_uuid_hi.value() != 0
|| module_parameters::os_uuid_lo.value() != 0
|| xart_guard.is_none()
{
dev_err!(dev, "J613 26.6.2 requires a DT identity and xART guard\n");
return Err(EINVAL);
}
}
let store = match xart_store::Store::open_owner(xart_writes, xart_start) {
Ok(mut store) => {
match xart_guard {
Expand Down Expand Up @@ -897,13 +909,18 @@ impl SepData {
let mut host_store = match store::Store::open() {
Ok(store) => Some(store),
Err(e) => {
if profile::j613_26_6_2() {
dev_err!(dev, "J613 26.6.2 host-state store unavailable: {:?}\n", e);
return Err(e);
}
dev_warn!(dev, "Linux host-state store unavailable: {:?}\n", e);
None
}
};

let bio_index = match host_store.as_mut().map(bio::IdentityIndex::load) {
Some(Ok(index)) => index,
Some(Err(e)) if profile::j613_26_6_2() => return Err(e),
Some(Err(_)) => bio::IdentityIndex::new(),
None => bio::IdentityIndex::new(),
};
Expand Down Expand Up @@ -1551,14 +1568,17 @@ impl SepData {
match os_identity::select(hi, lo, dt::preboot_uuid) {
os_identity::Selection::Explicit(uuid) => {
self.xarm.lock().os_uuid = Some(uuid);
diag::identity_source(diag::IdentitySource::Override);
dev_info!(self.dev, "xART: using explicit OS identity\n");
}
os_identity::Selection::Chosen(uuid) => {
self.xarm.lock().os_uuid = Some(uuid);
diag::identity_source(diag::IdentitySource::DeviceTree);
dev_info!(self.dev, "xART: using /chosen/apfs-preboot-uuid\n");
}
os_identity::Selection::Unavailable => {
self.xarm.lock().os_uuid = None;
diag::identity_source(diag::IdentitySource::Missing);
dev_warn!(self.dev, "xART: /chosen/apfs-preboot-uuid is unavailable\n");
}
}
Expand Down Expand Up @@ -2660,20 +2680,33 @@ impl platform::Driver for SepDriver {
// As soon as the fixed facts are known, so a tool can watch the attach
// from "pending" on. Diagnostics are not worth failing the probe for.
let guard = data.with_store(|store| store.guard_state()).flatten();
if let Err(e) = diag::register(dev, data.profile, data.xart_writable(), guard) {
let policy = diag::Policy {
provision_keybag: module_parameters::provision_keybag.value() != 0,
trusted_keys: module_parameters::trusted_keys.value() != 0,
filevault_api: module_parameters::filevault_api.value() != 0,
xarm_trace: module_parameters::xarm_trace.value() != 0,
refkey_v2: module_parameters::refkey_v2.value() != 0,
identity_override: module_parameters::os_uuid_hi.value() != 0
|| module_parameters::os_uuid_lo.value() != 0,
};
if let Err(e) = diag::register(dev, data.profile, data.xart_writable(), guard, policy) {
dev_warn!(dev, "diag: could not add the sysfs attributes ({:?})\n", e);
}

*data.mbox.lock() = Some(Mailbox::new_byname(dev, c"mbox", data.clone())?);

data.attach(&sep_node)?;

if let Err(e) = data.register_fv_kernel() {
dev_err!(dev, "could not register the FileVault kernel API: {:?}\n", e);
if module_parameters::filevault_api.value() != 0 {
if let Err(e) = data.register_fv_kernel() {
dev_err!(dev, "could not register the FileVault kernel API: {:?}\n", e);
}
}

if let Err(e) = trusted::register(data.clone()) {
dev_warn!(data.dev, "trusted-keys: registration failed ({:?})\n", e);
if module_parameters::trusted_keys.value() != 0 {
if let Err(e) = trusted::register(data.clone()) {
dev_warn!(data.dev, "trusted-keys: registration failed ({:?})\n", e);
}
}

if let Err(e) = pm::register(data.clone()) {
Expand Down Expand Up @@ -2740,6 +2773,14 @@ module! {
description: "Apple SEP coprocessor: warm attach, endpoint discovery and tag-correlated control endpoint",
license: "Dual MIT/GPL",
params: {
trusted_keys: u8 {
default: 1,
description: "Register the SEP trusted-key source; 0 leaves it disabled",
},
filevault_api: u8 {
default: 1,
description: "Register the SEP FileVault kernel API; 0 leaves it disabled",
},
xart_writes: u8 {
default: 1,
description: "Allow shared xART writes only if APFS proves a single unsnapshotted .gl extent; set to 0 for read-only operation",
Expand Down
4 changes: 4 additions & 0 deletions drivers/soc/apple/shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ struct device;

int sep_diag_register(struct device *dev, const char *profile,
size_t profile_len, bool cold, bool sepos13, bool xart);
void sep_diag_set_policy(bool provision_keybag, bool trusted_keys,
bool filevault_api, bool xarm_trace, bool refkey_v2,
bool identity_override);
void sep_diag_set_identity_source(unsigned int source);
void sep_diag_set_attach(bool attached);
void sep_diag_set_endpoints(unsigned int count);
void sep_diag_set_keystore_open(void);
Expand Down
Loading