xref: /xnu-12377.1.9/doc/mach_ipc/guard_exceptions.md (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1Mach Port Guard exceptions
2==========================
3
4Mach Port Guard exceptions are used to denote various misuses of Mach IPC.
5This document covers their meaning, as well as hints on how to debug issues.
6
7## Anatomy of a Mach Port Guard Exception
8
9Mach Port Guard Exception is delivered via a Mach exception. These constructs
10are described in the `<kern/exc_guard.h>` header:
11
12```
13/*
14 * Mach port guards use the exception codes like this:
15 *
16 * code:
17 * +-----------------------------+----------------+-----------------+
18 * |[63:61] GUARD_TYPE_MACH_PORT | [60:32] flavor | [31:0] target   |
19 * +-----------------------------+----------------+-----------------+
20 *
21 * subcode:
22 * +----------------------------------------------------------------+
23 * |[63:0] payload                                                  |
24 * +----------------------------------------------------------------+
25 */
26
27#define GUARD_TYPE_MACH_PORT    0x1      /* guarded mach port */
28```
29
30This description is mostly useful to implementors of a Mach exception handler,
31most clients will instead receive a crash log where ReportCrash tried its best
32to decode the message above, however sometimes it lags behind the introduction
33of new guards, and this document helps decoding the matrix.
34
35A properly decoded crashlog will contain information like this:
36
37```
38Exception Type: EXC_GUARD (SIGKILL)
39Exception Subtype: GUARD_TYPE_MACH_PORT
40Exception Message: INVALID_NAME on mach port 9987 (guarded with 0x0000000000000000)
41Exception Codes: 0x0000000000002703, 0x0000000000000000
42Termination Reason: GUARD 2305845208236959491
43```
44
45However, in some cases, the decoding is partial and one needs to decode
46these by hand. In all cases, ReportCrash will always recognize Mach Port Guards,
47and the `Exception Codes` and `Termination Reason` are the lines we need,
48in terms of the kernel defined fields, they follow this template:
49
50```
51Exception Codes: $(code.target), $(subcode.payload)
52Termination Reason: GUARD $(code)
53```
54
55When applying it to the example above, we can see that:
56
57- the code is `2305845208236959491 == 0x2000020000002703` which decodes into
58  `{ guard_type: GUARD_TYPE_MACH_PORT, flavor: 0x200, target: 0x2703 }`
59- the payload is `0`.
60
61
62## Typical Mach Port bugs, and how to reason about them
63
64In this section, we will describe the most common cases of Mach IPC issues
65that are reported by Mach Port Guard exceptions, and how to reason about them.
66
67### Port right mismanagement
68
69This is by far the most common source of issues with Mach IPC. Unlike file
70descriptors which have a really simple lifecycle (you destroy them with
71`close()`), Mach ports have several associated rights that must be managed
72properly.
73
74Port right mismanagement usually happens when some subsystem has a dangling
75reference to a Mach port name that it has already destroyed, and keeps using it.
76This is the analogous to a use-after-free for allocated memory.
77
78The most common sources of issues are:
79
80- confusions in accounting of the receive right and send rights, due to the
81  arcane `mach_port_mod_refs` API being misused. We recommend using
82  `mach_port_destruct()` for receive rights, and `mach_port_deallocate()`
83  for send or send-once rights.
84
85- dangling port names: the port name management was correct, but the reference
86  to the port wasn't reset to `MACH_PORT_NULL`, leading to eventual over-releases.
87
88- threading safety related issues where the port management isn't properly
89  synchronized.
90
91
92## List of fatal Mach Port Guard Exceptions
93
94Some of the exceptions are always fatal (hitting them will cause the process to
95be terminated) regardless of the process kind.
96
97
98### `kGUARD_EXC_DESTROY` 0x00000001
99
100- **ReportCrash Name**: DESTROY,
101- **Target meaning**: the mach port name the incorrect operation targets,
102- **Payload meaning**: the correct value of the context guarding the Mach Port.
103
104This exception is thrown when a guarded receive right is being destroyed
105with an incorrect or missing context presented by the caller.
106
107Receive rights can be guarded with a caller chosen context via mechanisms such
108as:
109
110- `mach_port_guard()` being called,
111- the right being made using the `MPO_CONTEXT_AS_GUARD` flag of
112  `mach_port_construct()`,
113- the usage of a guarded port descriptor in a Mach message.
114
115
116Examples of such ports are the receive rights used for XPC Connections,
117hitting such a bug usually is a sign of port right mismanagement.
118
119
120### `kGUARD_EXC_MOD_REFS` 0x00000002
121
122- **ReportCrash Name**: `OVER_DEALLOC` or `MOD_REFS`,
123- **Target meaning**: the mach port name the incorrect operation targets,
124- **Payload meaning**:
125   - `0x0100000000000000`: a `deallocate` function,
126   - `0x0200000000000000`: a `destroy` function,
127   - `0x0300000000000000`: via the side effect of a message send (port copyin).
128
129This exception is thrown when the last send right of a pinned mach port is being
130destroyed. Pinned ports must never have a send right count going to zero in a
131given IPC space.
132
133Examples of such ports are thread and task control ports.  This is usually a
134sign of port-right mismanagement.
135
136
137### `kGUARD_EXC_INVALID_OPTIONS` 0x00000003
138
139- **ReportCrash Name**: `INVALID_OPTIONS`,
140- **Target meaning**: the message ID of a rejected message via the legacy
141  `mach_msg_trap()` or zero,
142- **Payload meaning**: the kernel sanitized (see `ipc_current_user_policy()`)
143  for the rejected `mach_msg2()` call.
144
145There are several policies dictating the shape of options passed to calls of the
146`mach_msg()` family. These correspond to programming mistakes.
147
148
149### `kGUARD_EXC_SET_CONTEXT` 0x00000004
150
151- **ReportCrash Name**: `SET_CONTEXT`,
152- **Target meaning**: the mach port name the incorrect operation targets,
153- **Payload meaning**: the value of the context guarding the Mach Port.
154
155This exception is thrown when `mach_port_set_context()` or
156`mach_port_swap_guard()` is used against a Mach Port using a strict guard (a
157Mach Port constructed with the `MPO_STRICT | MPO_CONTEXT_AS_GUARD` flags).
158
159Examples of such ports are the client-side receive right for XPC connections.
160This is usually a sign of port right mismanagement.
161
162
163### `kGUARD_EXC_THREAD_SET_STATE` 0x00000005
164
165- **ReportCrash Name**: N/A,
166- **Target meaning**: exception flavor,
167- **Payload meaning**:
168  - `0x0100000000000000`: tss called from userspace exception handler,
169  - `0x0200000000000000`: tss with flavor that modifies cpu registers,
170  - `0x0300000000000000`: tss called from fatal PAC exception.
171
172This exception is thrown when a process is trying to use the
173`thread_set_state()` interface, or any interface leading to it (such as trying
174to change thread state via replying to a Mach exception message), and that this
175is disallowed by policy for this process.
176
177
178### `kGUARD_EXC_EXCEPTION_BEHAVIOR_ENFORCE` 0x00000006
179
180- **ReportCrash Name**: N/A,
181- **Target meaning**: the new exception behavior,
182- **Payload meaning**: the exception mask.
183
184This exception is thrown when a process is trying to register an exception port
185for a behavior not using a task identity port, and that this is disallowed by
186policy for this process.
187
188
189### `kGUARD_EXC_SERVICE_PORT_VIOLATION_FATAL` 0x00000007
190
191- **ReportCrash Name**: N/A,
192- **Target meaning**: the type of service port defense violation,
193- **Payload meaning**: violator port name if we have it, zero otherwise.
194
195This exception is thrown when the `service_port_defense_enabled` bootarg is set and a
196process violates service port defense policy, which includes copyin a service port receive
197right from process other than launchd, arming pd notification on a service port if the
198process is not launchd, and setting a service port as exception port.
199
200### `kGUARD_EXC_UNGUARDED` 0x00000008
201
202- **ReportCrash Name**: UNGUARDED,
203- **Target meaning**: the mach port name the incorrect operation targets,
204- **Payload meaning**: always zero.
205
206This exception is thrown when a process is trying to perform an operation (such
207as `mach_port_unguard()` on a port that isn't guarded.
208
209This is usually a sign of port right mismanagement.
210
211### `kGUARD_EXC_KOBJECT_REPLY_PORT_SEMANTICS` 0x00000009
212
213- **ReportCrash Name**: KOBJECT\_REPLY\_PORT\_SEMANTICS,
214- **Target meaning**: the mach port name the incorrect operation targets,
215- **Payload meaning**: always zero.
216
217This exception is thrown when a hardened process is trying to send a message
218to a kobject port without using an `IOT_REPLY_PORT` to receive the reply.
219
220### `kGUARD_EXC_REQUIRE_REPLY_PORT_SEMANTICS` 0x0000000a
221
222- **ReportCrash Name**: `REQUIRE_REPLY_PORT_SEMANTICS`,
223- **Target meaning**: the mach port name the incorrect operation targets,
224- **Payload meaning**: 1 if the port is a bootstrap port, 0 otherwise.
225
226This exception is thrown when a caller is violating the reply port semantics in
227a process where this is disallowed by policy. This is used to gather telemetry
228around violators pending enforcement in a future release.
229
230This is usually a sign of a programming mistake (violation of the reply port
231semantics rules).
232
233### `kGUARD_EXC_INCORRECT_GUARD` 0x00000010
234
235- **ReportCrash Name**: `INCORRECT_GUARD`,
236- **Target meaning**: the mach port name the incorrect operation targets,
237- **Payload meaning**: the value of the context guarding the Mach Port.
238
239This exception is thrown when a process is attemtping a guarded operation but
240passed a context to the call that doesn't match the context actually guarding
241this port.
242
243This is usually a sign of port right mismanagement.
244
245
246### `kGUARD_EXC_IMMOVABLE` 0x00000020
247
248- **ReportCrash Name**: `ILLEGAL_MOVE`,
249- **Target meaning**: the mach port name the incorrect operation targets,
250- **Payload meaning**: (target port type << 32) | disposition.
251
252This exception is thrown when a process is attempting to move a port right,
253and this has been disallowed by policy for this port type and process.
254
255This is usually a programming mistake (or legacy code that hasn't been updated
256to the most recent Mach IPC policies).
257
258
259### `kGUARD_EXC_STRICT_REPLY` 0x00000040
260
261This exception is thrown for reply port semantics mistakes, if the
262`enforce_strict_reply` boot-arg is set.  As this is not a default config at this
263point, and that this is likely going to be phased out in favor of tracking reply
264ports at the port type level, this is left mostly undocumented on purpose.
265
266
267### `kGUARD_EXC_INVALID_NOTIFICATION_REQ` 0x00000041
268
269- **ReportCrash Name**: INVALID\_NOTIFICATION\_REQ,
270- **Target meaning**: IOT_ port type that you are trying to arm the notification on
271- **Payload meaning**: The type of notification you were registering for
272
273This exception is thrown when a process is trying to arm a notification
274on a port type that disallows such requests.
275
276
277### `kGUARD_EXC_INVALID_MPO_ENTITLEMENT` 0x00000042
278
279- **ReportCrash Name**: `INVALID_MPO_ENTITLEMENT`,
280- **Target meaning**: The `mpo_flags_t` that were passed into `mach_port_construct`
281
282This exception is thrown when you try to construct a mach port type that is disallowed
283for your process based on entitlements.
284
285### `kGUARD_EXC_DESCRIPTOR_VIOLATION` 0x00000043
286
287- **ReportCrash Name**: `DESCRIPTOR_VIOLATION`,
288- **Target meaning**: The IPC space policy.
289- **Payload meaning**:
290   - `(violation_type << 56) | aux` : the violation's type, among with associated metadata
291
292This exception is thrown when a process attempts to violate any
293Mach message descriptor policies.
294
295### `kGUARD_EXC_MSG_FILTERED` 0x00000080
296
297- **ReportCrash Name**: `MSG_FILTERED`,
298- **Target meaning**: the mach port name the incorrect operation targets,
299- **Payload meaning**: the message ID of the filtered message.
300
301This exception is thrown when a process is not allowed to send the specified
302message due to sandboxing, and that a hard failure has been requested by either
303the client or the Sandbox.
304
305
306## List of optionally fatal Mach Port Guard Exceptions
307
308Some of the exceptions are optionally fatal. Hitting them will only terminate
309the process when it is opted for a hardened Mach IPC environment. Such processes
310are:
311
312- platform binaries,
313- processes with a browser entitlement (`com.apple.developer.web-browser-engine.*`).
314
315The `task_exc_guard_default` boot-arg can be used to change these defaults.
316
317Note: using the `amfi=-1` or similar boot-args will make all processes appear to
318be platform binaries, which in turn will turn a lot of bugs in 3p software into
319hard crashes. Most notably at this time, electron apps cause several guard
320exceptions in the Mach IPC and VM world. This is not a supported configuration.
321
322
323### `kGUARD_EXC_INVALID_RIGHT` 0x00000100
324
325- **ReportCrash Name**: `INVALID_RIGHT`,
326- **Target meaning**: the mach port name the incorrect operation targets,
327- **Payload meaning**:
328   - `0x01 << 56`                              : `ipc_port_translate_receive` failed,
329   - `(0x02 << 56) | (right << 32) | ie_bits`  : `ipc_right_delta` failed,
330   - `(0x03 << 56) | ie_bits`                  : `ipc_right_destruct` failed,
331   - `(0x04 << 56) | (reason << 32) | ie_bits` : `ipc_right_copyin` failed,
332   - `(0x05 << 56) | ie_bits`                  : `ipc_right_dealloc` failed,
333   - `(0x06 << 56) | (otype << 32) | io_type`  : `ipc_right_deallocate_kernel` failed,
334   - `(0x07 << 56) | ie_bits`                  : invalid port in `ipc_object_translate_port_pset`,
335   - `(0x08 << 56) | ie_bits`                  : invalid pset in `ipc_object_translate_port_pset`.
336
337This exception is thrown when an operation is targetting a port which rights do
338not match the caller's expectations. Examples of such mistakes are:
339
340- performing an operation expecting a port-set name, but passing a port name
341  instead,
342- trying to receive a message and not owning the receive right for it.
343
344These correspond to cases leading to the `KERN_INVALID_RIGHT` or
345`KERN_INVALID_CAPABILITY` error codes of most Mach IPC interfaces.
346
347This is usually a sign of port right mismanagement.
348
349
350### `kGUARD_EXC_INVALID_NAME` 0x00000200
351
352- **ReportCrash Name**: `INVALID_NAME`,
353- **Target meaning**: the mach port name the incorrect operation targets,
354- **Payload meaning**: always zero.
355
356This exception is thrown when an operation is targetting a name for which
357the caller holds no right.
358
359These correspond to cases leading to the `KERN_INVALID_NAME` error code of most
360Mach IPC interfaces.
361
362This is usually a sign of port right mismanagement.
363
364
365### `kGUARD_EXC_INVALID_VALUE` 0x00000400
366
367- **ReportCrash Name**: `INVALID_VALUE`,
368- **Target meaning**: the mach port name the incorrect operation targets,
369- **Payload meaning**:
370   - `(0x01 << 56) | (type << 32)  | size`                     : invalid trailer in `mach_port_peek`,
371   - `(0x02 << 56) | (right << 32) | (delta << 16) | ie_bits`  : `ipc_right_delta` failed,
372   - `(0x03 << 56) | (srdelta << 32) | ie_bits`                : `ipc_right_destruct` failed,
373
374This exception is thrown when:
375
376- the caller is trying to apply a delta to the number of send rights of a port
377  name, and this would overflow the send right count, which is usually a sign of
378  port right mismanagement,
379
380- the trailer related arguments to `mach_port_peek()` are invalid, which is
381  typicaly a programming mistake.
382
383These correspond to cases leading to the `KERN_INVALID_VALUE` error code of most
384Mach IPC interfaces.
385
386
387### `kGUARD_EXC_INVALID_ARGUMENT` 0x00000800
388
389- **ReportCrash Name**: `INVALID_ARGUMENT`,
390- **Target meaning**: the mach port name the incorrect operation targets,
391- **Payload meaning**: the correct value of the context guarding the Mach Port.
392
393This exception is thrown when a caller is trying to guard an already guarded
394port. This should really have been named `kGUARD_EXC_ALREADY_GUARDED`.
395
396This is usually a sign of port right mismanagement.
397
398
399### `kGUARD_EXC_KERN_FAILURE` 0x00004000
400
401- **ReportCrash Name**: `KERN_FAILURE`,
402- **Target meaning**: always zero,
403- **Payload meaning**:
404   - `0x0100000000000000`: task other than launchd arm pd on service ports,
405   - `0x0200000000000000`: not using IOT_NOTIFICATION_PORT for pd notification,
406   - `0x0300000000000000`: notification port not owned by launchd,
407   - `0x0400000000000000`: register multiple pd notification.
408
409This exception is thrown when a caller is trying to request a port-destroyed
410notification that is disallowed by system policy.  This should really have been
411named `kGUARD_EXC_INVALID_PDREQUEST`.
412
413This is usually a sign of port right mismanagement.
414
415
416### `kGUARD_EXC_SEND_INVALID_REPLY` 0x00010000
417
418- **ReportCrash Name**: `SEND_INVALID_REPLY`,
419- **Target meaning**: the mach port name the incorrect operation targets,
420- **Payload meaning**: (reply port ie bits << 32) | disposition.
421
422This exception is thrown when a caller is trying to send a message whose reply
423port (the `msgh_local_port` field of a Mach message) violates policies around
424reply ports or its disposition.
425
426This is usually a sign of port right mismanagement.
427
428
429### `kGUARD_EXC_SEND_INVALID_RIGHT` 0x00020000
430
431- **ReportCrash Name**: `SEND_INVALID_RIGHT`,
432- **Target meaning**: the mach port name the incorrect operation targets,
433- **Payload meaning**:
434   - `(0x01 << 56) | disposition`: copyin port descriptor failed,
435   - `(0x02 << 56) | disposition`: copyin ool port descriptor failed,
436   - `(0x03 << 56) | disposition`: copyin guarded port descriptor failed,
437
438This exception is thrown when a caller is trying to send a message where one of
439the port descriptors denotes a right that doesn't match the requested
440disposition (for example, a make-send disposition for a port where the process
441doesn't own a receive right).
442
443This is usually a sign of port right mismanagement.
444
445
446### `kGUARD_EXC_SEND_INVALID_VOUCHER` 0x00040000
447
448- **ReportCrash Name**: `SEND_INVALID_VOUCHER`,
449- **Target meaning**: the mach port name the incorrect operation targets,
450- **Payload meaning**: disposition of the voucher port.
451
452This exception is thrown when a caller is trying to send a message whose voucher
453port (the `msgh_voucher_port` field of a Mach message) violates policies around
454voucher ports or its disposition.
455
456This is usually a sign of port right mismanagement.
457
458
459### `kGUARD_EXC_RCV_INVALID_NAME` 0x00080000
460
461- **ReportCrash Name**: `RCV_INVALID_NAME`,
462- **Target meaning**: the mach port name the incorrect operation targets,
463- **Payload meaning**: always zero.
464
465This exception is thrown when a caller is trying to receive a message on a mach
466port name for which it doesn't hold a port-set or receive right.
467
468This is usually a sign of port right mismanagement.
469
470
471## List of soft Mach Port Guard Exceptions
472
473Some of the exceptions are never fatal (hitting them will only emit a simulated
474crash log, and the process will keep going).
475
476
477### `kGUARD_EXC_RCV_GUARDED_DESC` 0x00100000
478
479- **ReportCrash Name**: `RCV_GUARDED_DESC`,
480- **Target meaning**: the mach port name the incorrect operation targets,
481- **Payload meaning**: always zero.
482
483This exception is thrown when a caller is trying to receive a message containing
484guarded port descriptors and it hasn't indicated that it knows how to parse them
485(by passing the `MACH_RCV_GUARDED_DESC` flag to `mach_msg()`).
486
487The usage of guarded port descriptor is a protocol agreement between the client
488and the server, and a disagreement here is a programming mistake.
489
490This guard is only enabled on development kernels at this time.
491
492### `kGUARD_EXC_SERVICE_PORT_VIOLATION_NON_FATAL` 0x00100001
493
494- **ReportCrash Name**: N/A,
495- **Target meaning**: the type of service port defense violation,
496- **Payload meaning**: violator port name if we have it, zero otherwise.
497
498This is the non fatal version of `kGUARD_EXC_SERVICE_PORT_VIOLATION_FATAL`, which is
499used when the `service_port_defense_enabled` bootarg is not set.
500
501
502### `kGUARD_EXC_PROVISIONAL_REPLY_PORT` 0x00100002
503
504- **ReportCrash Name**: N/A,
505- **Target meaning**: always zero,
506- **Payload meaning**: always zero.
507
508This exception is thrown when a 1p process is trying to create a provisional
509reply port on iOS. It is currently a soft crash to collect telemetry before
510the actual enforcement.
511
512
513### `kGUARD_EXC_OOL_PORT_ARRAY_CREATION` 0x00100003
514
515- **ReportCrash Name**: N/A,
516- **Target meaning**: always zero.
517- **Payload meaning**: always zero.
518
519This is telemetry for processes creating a port with flag
520MPO_CONNECTION_PORT_WITH_PORT_ARRAY without an entitlement
521
522
523### `kGUARD_EXC_MOVE_PROVISIONAL_REPLY_PORT` 0x00100004
524
525- **ReportCrash Name**: N/A,
526- **Target meaning**: the mach port name of the provisional reply port,
527- **Payload meaning**: always zero.
528
529This exception is thrown when a process opted for enhanced security v2 moves
530the receive right of a provisional reply port out of its ipc space.
531
532### `kGUARD_EXC_REPLY_PORT_SINGLE_SO_RIGHT` 0x00100005
533
534- **ReportCrash Name**: N/A,
535- **Target meaning**: the mach port name of the reply port,
536- **Payload meaning**: the copyin reason.
537
538This exception is thrown when a process attempts to create more than
539one single send-once right for a reply port. Reply ports are not allowed
540to extend more than one single send-once right at any given moment.
541
542
543### `kGUARD_EXC_MOD_REFS_NON_FATAL` 0x00200000
544
545- **ReportCrash Name**: `OVERDEALLOC_SOFT`,
546- **Target meaning**: the mach port name the incorrect operation targets,
547- **Payload meaning**: same as `kGUARD_EXC_MOD_REFS`.
548
549This is the same as `kGUARD_EXC_MOD_REFS`, except that this is delivered as a
550soft error.
551
552
553### `kGUARD_EXC_IMMOVABLE_NON_FATAL` 0x00400000
554
555- **ReportCrash Name**: `ILLEGALMOVE_SOFT`.
556- **Target meaning**: the mach port name the incorrect operation targets,
557- **Payload meaning**: same as `kGUARD_EXC_IMMOVABLE`.
558
559This is the same as `kGUARD_EXC_IMMOVABLE`, except that this is delivered as a
560soft error.
561
562