xref: /xnu-12377.1.9/doc/mach_ipc/ipc_security_concepts.md (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1Mach IPC Security concepts
2==========================
3
4This documentation aims at documenting various security concepts in this
5subsystem. Each section covers a single concept, and will cover topics such as
6motivation, design of the feature, and implementation details that are
7important.
8
9
10## IPC space policy
11
12### Motivation and design
13
14Over time our IPC policies have grown in complexity and depend on several
15parameters, to name a few: being a simulated process, a platform binary, or
16having browser entitlements.
17
18As a result, a notion of IPC space policy exists that projects all various
19system policies into a single enum per IPC space. This policy is an inherent
20immutable property of an IPC space which allows to query its value without
21holding any locks.
22
23
24### Implementation details
25
26The source of truth for IPC policies is the `struct ipc_space::is_policy` field,
27which can be accessed with the `ipc_space_policy()` accessor.
28
29This field is computed when a task IPC space is enabled (in
30`ipc_task_enable()`), and is immutable for the lifetime of this space. In
31addition to that, the field is dPACed in order to be resilient to early memory
32corruption primitives.
33
34For conveniency reasons, the policy bits of a space are injected in other enums
35(such as `mach_msg_options64_t`).  The `IPC_SPACE_POLICY_BASE()` macro helps
36forming types that extend the space policy.
37
38
39## Pinned Entries
40
41### Motivation and design
42
43Certain kinds of send rights have a well understood lifecycle on the system,
44during which there must always be an extent send right alive for the port.
45Obvious examples of this are task or thread control ports which must have
46a live send right in their corresponding IPC space while the task or thread
47they reference is alive.
48
49In order to catch port management issues that could lead to various confused
50deputies issues, the Mach IPC subsystem provides a notion of pinned send rights.
51Pinned send rights is a concept of the Mach IPC Entry, which denotes that this
52entry must always have at least one extent send right alive.
53
54Pinning can be undone in two ways:
55
56- when a port receive right is destroyed, pinning is no longer effective,
57  and entries will be automatically unpinned as part of the dead-name check;
58- unpinning can be explicitly requested by the kernel.
59
60
61### When and how to used pinned rights?
62
63Pinned rights were designed to protect `mach_task_self()` and
64`_pthread_mach_thread_self_direct()` which can lead to grave security bugs when
65port lifecycle management mistakes are made. The bracketing there is very
66simple:
67
68- task ports are never unpinned;
69- thread ports are unpinned when the thread terminates.
70
71
72There might be other ports on the system which can use this facility, however
73they must have the right shape: either the port dying (the receive right being
74destroyed) is an adequate way to unpin the entry, or there must be a clearly
75identified kernel path that can unpin the entry without any confusion with other
76ports.
77
78Adding unpinning paths that can't verify that the port being unpinned is
79"theirs" would lead to weakening this feature and would reintroduce avenues
80to confuse the system due to port mismanagement bugs.
81
82
83### Implementation details
84
85Pinning is denoted by the `IE_BITS_PINNED_SEND` bit
86of the `struct ipc_entry::ie_bits` field.
87
88IPC entries gain this bit the first time the kernel calls
89`ipc_port_copyout_send_pinned()` for a given port and IPC space.
90
91When the `IE_BITS_PINNED_SEND` is set, then the `MACH_PORT_TYPE_SEND` bit must
92be set too, with the `IE_BITS_UREFS()` for this entry being at least 1.
93
94In order to respect that pinning is ignored immediately when a port becomes
95dead, enforcing `IE_BITS_PINNED_SEND` semantics must be done under the space
96lock, either right after a dead-name conversion check happened
97(`ipc_right_check()` has been called) or by checking explicitly that the port
98is still active (`ip_active()` returns true) when a dead-name conversion isn't
99desirable.
100
101
102### Usage and enforcement
103
104Task and thread control ports are pinned for all processes within the
105owning IPC space of the task in question, for all processes on the system.
106
107The `ipc_control_port_options` boot-arg determines the reaction of the system to
108violations of pinning:
109
110- hardened processes and above have hard enforcement of pinning rules (violating
111  the rules terminates the process);
112- other processes have a soft enforcement: violating pinning rules returns a
113  `KERN_INVALID_CAPABILITY` error and generates a non fatal guard exception.
114
115
116
117