Skip to content
Closed
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
60 changes: 0 additions & 60 deletions drivers/pmdomain/apple/pmgr-pwrstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/reset-controller.h>
Expand Down Expand Up @@ -371,63 +370,12 @@ static int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev,
return 0;
}

/*
* genpd adds a power state that is on only below parents that are on. With a
* single parent the platform bus has already attached this device to it and
* powered it on before probe; with more than one it attaches to none, so a
* domain the boot loader left on (DISPEXT1_SYS on the J616s, below FAB7_SOC
* and its PMP request) could not be added. Power every parent on through a
* virtual device until the subdomain links hold them.
*/
static int apple_pmgr_ps_hold_parents(struct apple_pmgr_ps *ps, bool active,
struct dev_pm_domain_list **parents)
{
static const struct dev_pm_domain_attach_data data = {
.pd_flags = PD_FLAG_NO_DEV_LINK,
};
struct dev_pm_domain_list *list = NULL;
unsigned int i;
int ret;

*parents = NULL;
if (!active || of_count_phandle_with_args(ps->dev->of_node, "power-domains",
"#power-domain-cells") < 2)
return 0;

ret = dev_pm_domain_attach_list(ps->dev, &data, &list);
if (ret <= 0)
return ret;
for (i = 0; i < list->num_pds; i++) {
ret = pm_runtime_resume_and_get(list->pd_devs[i]);
if (ret < 0) {
while (i--)
pm_runtime_put(list->pd_devs[i]);
dev_pm_domain_detach_list(list);
return dev_err_probe(ps->dev, ret, "cannot power parent domain %u\n", i);
}
}
*parents = list;
return 0;
}

static void apple_pmgr_ps_release_parents(struct dev_pm_domain_list *parents)
{
unsigned int i;

if (!parents)
return;
for (i = 0; i < parents->num_pds; i++)
pm_runtime_put(parents->pd_devs[i]);
dev_pm_domain_detach_list(parents);
}

static int apple_pmgr_ps_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct apple_pmgr_ps *ps;
struct regmap *regmap;
struct dev_pm_domain_list *parents = NULL;
struct of_phandle_iterator it;
int ret;
const char *name;
Expand Down Expand Up @@ -580,10 +528,6 @@ static int apple_pmgr_ps_probe(struct platform_device *pdev)
return ret;
}

ret = apple_pmgr_ps_hold_parents(ps, active, &parents);
if (ret < 0)
goto err_remove;

of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) {
struct of_phandle_args parent, child;

Expand All @@ -604,9 +548,6 @@ static int apple_pmgr_ps_probe(struct platform_device *pdev)
}
}

/* The subdomain links hold the parents now. */
apple_pmgr_ps_release_parents(parents);

/*
* Do not participate in regular PM; parent power domains are handled via the
* genpd hierarchy.
Expand All @@ -626,7 +567,6 @@ static int apple_pmgr_ps_probe(struct platform_device *pdev)

return 0;
err_remove:
apple_pmgr_ps_release_parents(parents);
of_genpd_del_provider(node);
pm_genpd_remove(&ps->genpd);
return ret;
Expand Down
132 changes: 13 additions & 119 deletions drivers/soc/apple/bio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use kernel::ioctl::{_IO, _IOR, _IOW, _IOWR};
use kernel::prelude::*;
use kernel::uaccess::{UserPtr, UserSlice};

pub(crate) const IFACE_VERSION: u32 = 5;
pub(crate) const IFACE_VERSION: u32 = 4;

pub(crate) const ENROL_USER_ID: i32 = 1000;

Expand Down Expand Up @@ -100,35 +100,10 @@ struct List {
#[repr(C)]
struct EnrolStart {
flags: u32,
account_uid: u32,
finger: u32,
reserved: u32,
label: [u8; LABEL_LEN],
}

#[repr(C)]
pub(crate) struct EnclaveList {
pub(crate) count: u32,
pub(crate) reserved: u32,
pub(crate) uuid: [[u8; UUID_LEN]; MAX_IDENTITIES],
}

impl EnclaveList {
pub(crate) fn new() -> Self {
Self { count: 0, reserved: 0, uuid: [[0; UUID_LEN]; MAX_IDENTITIES] }
}

pub(crate) fn push(&mut self, uuid: [u8; UUID_LEN]) -> Result<()> {
let at = self.count as usize;
if at >= MAX_IDENTITIES {
return Err(EOVERFLOW);
}
self.uuid[at] = uuid;
self.count += 1;
Ok(())
}
}

#[repr(C)]
#[derive(Default)]
struct EnrolPoll {
Expand Down Expand Up @@ -161,8 +136,8 @@ struct VerifyPoll {
}

#[repr(C)]
pub(crate) struct Delete {
pub(crate) uuid: [u8; UUID_LEN],
struct Delete {
uuid: [u8; UUID_LEN],
}

pub(crate) const ATTEST_CHALLENGE_LEN: usize = 32;
Expand All @@ -187,8 +162,7 @@ pub(crate) struct Attest {
static_assert!(core::mem::size_of::<Identity>() == 144);
static_assert!(core::mem::size_of::<Info>() == 32);
static_assert!(core::mem::size_of::<List>() == 4616);
static_assert!(core::mem::size_of::<EnrolStart>() == 144);
static_assert!(core::mem::size_of::<EnclaveList>() == 520);
static_assert!(core::mem::size_of::<EnrolStart>() == 136);
static_assert!(core::mem::size_of::<EnrolPoll>() == 40);
static_assert!(core::mem::size_of::<VerifyStart>() == 40);
static_assert!(core::mem::size_of::<VerifyPoll>() == 72);
Expand All @@ -208,7 +182,7 @@ macro_rules! ioctl_pod {
};
}
ioctl_pod! {
to_user: Info, List, EnclaveList, EnrolPoll, VerifyPoll, Attest;
to_user: Info, List, EnrolPoll, VerifyPoll, Attest;
from_user: EnrolStart, VerifyStart, Delete, Attest
}

Expand All @@ -224,9 +198,6 @@ const IOC_CANCEL: u32 = _IO(MAGIC, 0x07);
const IOC_DELETE: u32 = _IOW::<Delete>(MAGIC, 0x08);
const IOC_DELETE_ALL: u32 = _IO(MAGIC, 0x09);
pub(crate) const IOC_ATTEST: u32 = _IOWR::<Attest>(MAGIC, 0x0a);
pub(crate) const IOC_LIST_ENCLAVE: u32 = _IOR::<EnclaveList>(MAGIC, 0x0b);
pub(crate) const IOC_DELETE_ORPHAN: u32 = _IOW::<Delete>(MAGIC, 0x0c);
pub(crate) const IOC_PREPARE_ENROL: u32 = _IOW::<EnrolStart>(MAGIC, 0x0d);

pub(crate) struct MatchEvidence {
identity: [u8; UUID_LEN],
Expand Down Expand Up @@ -367,10 +338,6 @@ impl IdentityIndex {
self.save(store)
}

pub(crate) fn can_persist_next(&self, store: &Store) -> bool {
store.can_write(&identity_key(), 8 + (self.entries.len() + 1) * (UUID_LEN + LABEL_LEN))
}

pub(crate) fn identity_v1_for(
&self,
uuid: &[u8; UUID_LEN],
Expand Down Expand Up @@ -514,7 +481,7 @@ pub(crate) struct Handled {
pub(crate) delete_identities: KVec<crate::sbio::IdentityV1>,
}

pub(crate) fn ok() -> Result<Handled> {
fn ok() -> Result<Handled> {
Ok(Handled {
ret: 0,
wake: false,
Expand All @@ -525,20 +492,14 @@ pub(crate) fn ok() -> Result<Handled> {
})
}

pub(crate) fn require_admin() -> Result<()> {
fn require_admin() -> Result<()> {
if crate::shim::capable_admin() {
Ok(())
} else {
Err(EPERM)
}
}

pub(crate) fn orphan_delete(identity: crate::sbio::IdentityV1) -> Result<Handled> {
let mut handled = ok()?;
handled.delete_identity = Some(identity);
Ok(handled)
}

fn require_sensor(present: bool) -> Result<()> {
if present {
Ok(())
Expand Down Expand Up @@ -606,85 +567,22 @@ fn list(ctx: &mut Context<'_>, user: UserPtr) -> Result<Handled> {
ok()
}

fn validate_enrol_request(request: &EnrolStart) -> Result<()> {
// NSS account resolution occurs in libfprint. This ABI requires its
// resolved uid, the named finger and the generated user label.
if request.flags != 0 || request.reserved != 0
|| request.account_uid == u32::MAX || !(1..=10).contains(&request.finger)
|| !request.label.starts_with(b"FP1-")
|| request.label[12] != b'-' || request.label[14] != b'-'
|| request.label[23] != b'-' || request.label[24] == 0
|| request.label[13] != b"123456789A"[request.finger as usize - 1]
|| !request.label.contains(&0)
{
return Err(EINVAL);
}
Ok(())
}

pub(crate) fn validate_enrol_start_arg(arg: usize) -> Result<()> {
let user = UserPtr::from_addr(arg);
let request: EnrolStart = UserSlice::new(user, core::mem::size_of::<EnrolStart>())
.reader().read()?;
validate_enrol_request(&request)
}

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

fn valid() -> EnrolStart {
let mut request = EnrolStart {
flags: 0, account_uid: 1000, finger: 7, reserved: 0,
label: [0; LABEL_LEN],
};
request.label[..28].copy_from_slice(b"FP1-20261027-7-12345678-user");
request
}

#[test]
fn resolved_account_and_known_finger() {
assert!(validate_enrol_request(&valid()).is_ok());
}

#[test]
fn missing_uid_is_refused() {
let mut request = valid();
request.account_uid = u32::MAX;
assert!(validate_enrol_request(&request).is_err());
}

#[test]
fn unknown_or_mismatched_finger_is_refused() {
let mut request = valid();
request.finger = 0;
assert!(validate_enrol_request(&request).is_err());
request.finger = 6;
assert!(validate_enrol_request(&request).is_err());
}

#[test]
fn missing_username_is_refused() {
let mut request = valid();
request.label[24] = 0;
assert!(validate_enrol_request(&request).is_err());
}
}

fn enrol_start(ctx: &mut Context<'_>, user: UserPtr) -> Result<Handled> {
require_admin()?;
let request: EnrolStart = UserSlice::new(user, core::mem::size_of::<EnrolStart>())
.reader()
.read()?;
validate_enrol_request(&request)?;
if request.flags != 0 || request.reserved != 0 {
return Err(EINVAL);
}
require_sensor(ctx.sensor_present)?;

if ctx.session.worker_epoch.is_some() || !ctx.session.op.may_start() {
return Err(EBUSY);
}
let count = ctx.live_identity_count.ok_or(EIO)?;
if count >= SEP_USER_CAPACITY || ctx.index.total() >= MAX_IDENTITIES {
if matches!(ctx.live_identity_count, Some(count) if count >= SEP_USER_CAPACITY)
|| ctx.index.total() >= MAX_IDENTITIES
{
return Err(ENOSPC);
}

Expand Down Expand Up @@ -1062,10 +960,6 @@ pub(crate) fn starts_capture(cmd: u32) -> bool {
cmd == IOC_ENROL_START || cmd == IOC_VERIFY_START
}

pub(crate) fn idle_for_mutation(session: &Session) -> bool {
session.worker_epoch.is_none() && session.op.may_start()
}

fn delete(ctx: &mut Context<'_>, user: UserPtr) -> Result<Handled> {
require_admin()?;
if !ctx.session.op.may_start() {
Expand Down
18 changes: 0 additions & 18 deletions drivers/soc/apple/catacomb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,6 @@ pub(crate) fn is_kind(kind: u8) -> bool {
path_for(kind).is_some()
}

pub(crate) fn writable(kind: u8) -> bool {
path_for(kind)
.and_then(|path| shim::StoreFile::open_writable_existing(path).ok())
.is_some()
}

/// Reserve a missing Linux owner file before SELECT_CONTEXT changes SEP state.
/// A corrupt existing file is never truncated here: it is failure evidence.
pub(crate) fn prepare_missing_owner() -> Result<()> {
let path = path_for(crate::PRIVATE_TYPE_CATACOMB_OWNER).ok_or(EINVAL)?;
let (file, created) = shim::StoreFile::open_host(path)?;
if !created {
return Err(ENODATA);
}
file.sync()?;
file.sync_parent()
}

pub(crate) fn write(kind: u8, blob: &[u8]) -> Result<()> {
let path = path_for(kind).ok_or(EINVAL)?;
if blob.len() > MAX_CATACOMB {
Expand Down
Loading
Loading