xref: /xnu-11417.121.6/doc/mach_ipc/guard_exceptions.md (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
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**: always zero,
167- **Payload meaning**: always zero.
168
169This exception is thrown when a process is trying to use the
170`thread_set_state()` interface, or any interface leading to it (such as trying
171to change thread state via replying to a Mach exception message), and that this
172is disallowed by policy for this process.
173
174
175### `kGUARD_EXC_EXCEPTION_BEHAVIOR_ENFORCE` 0x00000006
176
177- **ReportCrash Name**: N/A,
178- **Target meaning**: always zero,
179- **Payload meaning**: always zero.
180
181This exception is thrown when a process is trying to register an exception port
182for a behavior not using a task identity port, and that this is disallowed by
183policy for this process.
184
185
186### `kGUARD_EXC_SERVICE_PORT_VIOLATION_FATAL` 0x00000007
187
188- **ReportCrash Name**: N/A,
189- **Target meaning**: the type of service port defense violation,
190- **Payload meaning**: violator port name if we have it, zero otherwise.
191
192This exception is thrown when the `service_port_defense_enabled` bootarg is set and a
193process violates service port defense policy, which includes copyin a service port receive
194right from process other than launchd, arming pd notification on a service port if the
195process is not launchd, and setting a service port as exception port.
196
197### `kGUARD_EXC_UNGUARDED` 0x00000008
198
199- **ReportCrash Name**: UNGUARDED,
200- **Target meaning**: the mach port name the incorrect operation targets,
201- **Payload meaning**: always zero.
202
203This exception is thrown when a process is trying to perform an operation (such
204as `mach_port_unguard()` on a port that isn't guarded.
205
206This is usually a sign of port right mismanagement.
207
208
209### `kGUARD_EXC_INCORRECT_GUARD` 0x00000010
210
211- **ReportCrash Name**: INCORRECT\_GUARD,
212- **Target meaning**: the mach port name the incorrect operation targets,
213- **Payload meaning**: the value of the context guarding the Mach Port.
214
215This exception is thrown when a process is attemtping a guarded operation but
216passed a context to the call that doesn't match the context actually guarding
217this port.
218
219This is usually a sign of port right mismanagement.
220
221
222### `kGUARD_EXC_IMMOVABLE` 0x00000020
223
224- **ReportCrash Name**: ILLEGAL\_MOVE,
225- **Target meaning**: the mach port name the incorrect operation targets,
226- **Payload meaning**: always zero.
227
228This exception is thrown when a process is attempting to move a port right,
229and this has been disallowed by policy for this port type and process.
230
231This is usually a programming mistake (or legacy code that hasn't been updated
232to the most recent Mach IPC policies).
233
234
235### `kGUARD_EXC_STRICT_REPLY` 0x00000040
236
237This exception is thrown for reply port semantics mistakes, if the
238`enforce_strict_reply` boot-arg is set.  As this is not a default config at this
239point, and that this is likely going to be phased out in favor of tracking reply
240ports at the port type level, this is left mostly undocumented on purpose.
241
242
243### `kGUARD_EXC_MSG_FILTERED` 0x00000080
244
245- **ReportCrash Name**: MSG\_FILTERED,
246- **Target meaning**: the mach port name the incorrect operation targets,
247- **Payload meaning**: the message ID of the filtered message.
248
249This exception is thrown when a process is not allowed to send the specified
250message due to sandboxing, and that a hard failure has been requested by either
251the client or the Sandbox.
252
253
254## List of optionally fatal Mach Port Guard Exceptions
255
256Some of the exceptions are optionally fatal. Hitting them will only terminate
257the process when it is opted for a hardened Mach IPC environment. Such processes
258are:
259
260- platform binaries,
261- processes with a browser entitlement (`com.apple.developer.web-browser-engine.*`).
262
263The `task_exc_guard_default` boot-arg can be used to change these defaults.
264
265Note: using the `amfi=-1` or similar boot-args will make all processes appear to
266be platform binaries, which in turn will turn a lot of bugs in 3p software into
267hard crashes. Most notably at this time, electron apps cause several guard
268exceptions in the Mach IPC and VM world. This is not a supported configuration.
269
270
271### `kGUARD_EXC_INVALID_RIGHT` 0x00000100
272
273- **ReportCrash Name**: INVALID\_RIGHT,
274- **Target meaning**: the mach port name the incorrect operation targets,
275- **Payload meaning**: always zero.
276
277This exception is thrown when an operation is targetting a port which rights do
278not match the caller's expectations. Examples of such mistakes are:
279
280- performing an operation expecting a port-set name, but passing a port name
281  instead,
282- trying to receive a message and not owning the receive right for it.
283
284These correspond to cases leading to the `KERN_INVALID_RIGHT` or
285`KERN_INVALID_CAPABILITY` error codes of most Mach IPC interfaces.
286
287This is usually a sign of port right mismanagement.
288
289
290### `kGUARD_EXC_INVALID_NAME` 0x00000200
291
292- **ReportCrash Name**: INVALID\_NAME,
293- **Target meaning**: the mach port name the incorrect operation targets,
294- **Payload meaning**: always zero.
295
296This exception is thrown when an operation is targetting a name for which
297the caller holds no right.
298
299These correspond to cases leading to the `KERN_INVALID_NAME` error code of most
300Mach IPC interfaces.
301
302This is usually a sign of port right mismanagement.
303
304
305### `kGUARD_EXC_INVALID_VALUE` 0x00000400
306
307- **ReportCrash Name**: INVALID\_VALUE,
308- **Target meaning**: the mach port name the incorrect operation targets,
309- **Payload meaning**: always zero.
310
311This exception is thrown when:
312
313- the caller is trying to apply a delta to the number of send rights of a port
314  name, and this would overflow the send right count, which is usually a sign of
315  port right mismanagement,
316
317- the trailer related arguments to `mach_port_peek()` are invalid, which is
318  typicaly a programming mistake.
319
320These correspond to cases leading to the `KERN_INVALID_VALUE` error code of most
321Mach IPC interfaces.
322
323
324### `kGUARD_EXC_INVALID_ARGUMENT` 0x00000800
325
326- **ReportCrash Name**: INVALID\_ARGUMENT,
327- **Target meaning**: the mach port name the incorrect operation targets,
328- **Payload meaning**: the correct value of the context guarding the Mach Port.
329
330This exception is thrown when a caller is trying to guard an already guarded
331port. This should really have been named `kGUARD_EXC_ALREADY_GUARDED`.
332
333This is usually a sign of port right mismanagement.
334
335
336### `kGUARD_EXC_KERN_FAILURE` 0x00004000
337
338- **ReportCrash Name**: KERN\_FAILURE,
339- **Target meaning**: the mach port name the incorrect operation targets,
340- **Payload meaning**: always zero.
341
342This exception is thrown when a caller is trying to request a port-destroyed
343notification that is disallowed by system policy.  This should really have been
344named `kGUARD_EXC_INVALID_PDREQUEST`.
345
346This is usually a sign of port right mismanagement.
347
348
349### `kGUARD_EXC_SEND_INVALID_REPLY` 0x00010000
350
351- **ReportCrash Name**: SEND\_INVALID\_REPLY,
352- **Target meaning**: the mach port name the incorrect operation targets,
353- **Payload meaning**: always zero.
354
355This exception is thrown when a caller is trying to send a message whose reply
356port (the `msgh_local_port` field of a Mach message) violates policies around
357reply ports or its disposition.
358
359This is usually a sign of port right mismanagement.
360
361
362### `kGUARD_EXC_SEND_INVALID_RIGHT` 0x00020000
363
364- **ReportCrash Name**: SEND\_INVALID\_RIGHT,
365- **Target meaning**: the mach port name the incorrect operation targets,
366- **Payload meaning**: always zero.
367
368This exception is thrown when a caller is trying to send a message where one of
369the port descriptors denotes a right that doesn't match the requested
370disposition (for example, a make-send disposition for a port where the process
371doesn't own a receive right).
372
373This is usually a sign of port right mismanagement.
374
375
376### `kGUARD_EXC_SEND_INVALID_VOUCHER` 0x00040000
377
378- **ReportCrash Name**: SEND\_INVALID\_VOUCHER,
379- **Target meaning**: the mach port name the incorrect operation targets,
380- **Payload meaning**: always zero.
381
382This exception is thrown when a caller is trying to send a message whose voucher
383port (the `msgh_voucher_port` field of a Mach message) violates policies around
384voucher ports or its disposition.
385
386This is usually a sign of port right mismanagement.
387
388
389### `kGUARD_EXC_RCV_INVALID_NAME` 0x00080000
390
391- **ReportCrash Name**: RCV\_INVALID\_NAME,
392- **Target meaning**: the mach port name the incorrect operation targets,
393- **Payload meaning**: always zero.
394
395This exception is thrown when a caller is trying to receive a message on a mach
396port name for which it doesn't hold a port-set or receive right.
397
398This is usually a sign of port right mismanagement.
399
400
401## List of soft Mach Port Guard Exceptions
402
403Some of the exceptions are never fatal (hitting them will only emit a simulated
404crash log, and the process will keep going).
405
406
407### `kGUARD_EXC_RCV_GUARDED_DESC` 0x00100000
408
409- **ReportCrash Name**: RCV\_GUARDED\_DESC,
410- **Target meaning**: the mach port name the incorrect operation targets,
411- **Payload meaning**: always zero.
412
413This exception is thrown when a caller is trying to receive a message containing
414guarded port descriptors and it hasn't indicated that it knows how to parse them
415(by passing the `MACH_RCV_GUARDED_DESC` flag to `mach_msg()`).
416
417The usage of guarded port descriptor is a protocol agreement between the client
418and the server, and a disagreement here is a programming mistake.
419
420This guard is only enabled on development kernels at this time.
421
422### `kGUARD_EXC_SERVICE_PORT_VIOLATION_NON_FATAL` 0x00100001
423
424- **ReportCrash Name**: N/A,
425- **Target meaning**: the type of service port defense violation,
426- **Payload meaning**: violator port name if we have it, zero otherwise.
427
428This is the non fatal version of `kGUARD_EXC_SERVICE_PORT_VIOLATION_FATAL`, which is
429used when the `service_port_defense_enabled` bootarg is not set.
430
431
432### `kGUARD_EXC_PROVISIONAL_REPLY_PORT` 0x00100002
433
434- **ReportCrash Name**: N/A,
435- **Target meaning**: always zero,
436- **Payload meaning**: always zero.
437
438This exception is thrown when a 1p process is trying to create a provisional
439reply port on iOS. It is currently a soft crash to collect telemetry before
440the actual enforcement.
441
442
443### `kGUARD_EXC_MOD_REFS_NON_FATAL` 0x00200000
444
445- **ReportCrash Name**: OVERDEALLOC\_SOFT,
446- **Target meaning**: the mach port name the incorrect operation targets,
447- **Payload meaning**: always zero.
448
449This is the same as `kGUARD_EXC_MOD_REFS`, except that this is delivered as a
450soft error.
451
452
453### `kGUARD_EXC_IMMOVABLE_NON_FATAL` 0x00400000
454
455- **ReportCrash Name**: ILLEGALMOVE\_SOFT.
456- **Target meaning**: the mach port name the incorrect operation targets,
457- **Payload meaning**: always zero.
458
459This is the same as `kGUARD_EXC_IMMOVABLE`, except that this is delivered as a
460soft error.
461
462
463### `kGUARD_EXC_REQUIRE_REPLY_PORT_SEMANTICS` 0x00800000
464
465- **ReportCrash Name**: REQUIRE\_REPLY\_PORT\_SEMANTICS,
466- **Target meaning**: the mach port name the incorrect operation targets,
467- **Payload meaning**: always zero.
468
469This exception is thrown when a caller is violating the reply port semantics in
470a process where this is disallowed by policy. This is used to gather telemetry
471around violators pending enforcement in a future release.
472
473This is usually a sign of a programming mistake (violation of the reply port
474semantics rules).
475
476