2 * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1987 Carnegie-Mellon University
31 * All rights reserved. The CMU software License Agreement specifies
32 * the terms and conditions for use and redistribution.
35 * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
36 * support for mandatory and extensible security protections. This notice
37 * is included in support of clause 2.2 (b) of the Apple Public License,
40 #include <vm/vm_options.h>
42 #include <kern/task.h>
43 #include <kern/thread.h>
44 #include <kern/debug.h>
45 #include <kern/extmod_statistics.h>
46 #include <mach/mach_traps.h>
47 #include <mach/port.h>
49 #include <mach/task.h>
50 #include <mach/task_access.h>
51 #include <mach/task_special_ports.h>
52 #include <mach/time_value.h>
53 #include <mach/vm_map.h>
54 #include <mach/vm_param.h>
55 #include <mach/vm_prot.h>
57 #include <sys/file_internal.h>
58 #include <sys/param.h>
59 #include <sys/systm.h>
61 #include <sys/namei.h>
62 #include <sys/proc_internal.h>
63 #include <sys/kauth.h>
66 #include <sys/vnode_internal.h>
67 #include <sys/mount.h>
68 #include <sys/trace.h>
69 #include <sys/kernel.h>
70 #include <sys/ubc_internal.h>
72 #include <sys/syslog.h>
74 #include <sys/sysproto.h>
76 #include <sys/sysctl.h>
77 #include <sys/cprotect.h>
78 #include <sys/kpi_socket.h>
79 #include <sys/kas_info.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
86 #include <security/audit/audit.h>
87 #include <security/mac.h>
88 #include <bsm/audit_kevents.h>
90 #include <kern/kalloc.h>
91 #include <vm/vm_map.h>
92 #include <vm/vm_kern.h>
93 #include <vm/vm_pageout.h>
95 #include <mach/shared_region.h>
96 #include <vm/vm_shared_region.h>
98 #include <vm/vm_protos.h>
100 #include <sys/kern_memorystatus.h>
103 #include <security/mac_framework.h>
108 #endif /* CONFIG_CSR */
110 int _shared_region_map_and_slide(struct proc
*, int, unsigned int, struct shared_file_mapping_np
*, uint32_t, user_addr_t
, user_addr_t
);
111 int shared_region_copyin_mappings(struct proc
*, user_addr_t
, unsigned int, struct shared_file_mapping_np
*);
113 #if VM_MAP_DEBUG_APPLE_PROTECT
114 SYSCTL_INT(_vm
, OID_AUTO
, map_debug_apple_protect
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_map_debug_apple_protect
, 0, "");
115 #endif /* VM_MAP_DEBUG_APPLE_PROTECT */
117 #if VM_MAP_DEBUG_FOURK
118 SYSCTL_INT(_vm
, OID_AUTO
, map_debug_fourk
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_map_debug_fourk
, 0, "");
119 #endif /* VM_MAP_DEBUG_FOURK */
121 #if DEVELOPMENT || DEBUG
124 sysctl_kmem_alloc_contig SYSCTL_HANDLER_ARGS
126 #pragma unused(arg1, arg2)
132 error
= sysctl_handle_int(oidp
, &size
, 0, req
);
133 if (error
|| !req
->newptr
)
136 kr
= kmem_alloc_contig(kernel_map
, &kaddr
, (vm_size_t
)size
, 0, 0, 0, 0, VM_KERN_MEMORY_IOKIT
);
138 if (kr
== KERN_SUCCESS
)
139 kmem_free(kernel_map
, kaddr
, size
);
144 SYSCTL_PROC(_vm
, OID_AUTO
, kmem_alloc_contig
, CTLTYPE_INT
|CTLFLAG_WR
|CTLFLAG_LOCKED
|CTLFLAG_MASKED
,
145 0, 0, &sysctl_kmem_alloc_contig
, "I", "");
147 extern int vm_region_footprint
;
148 SYSCTL_INT(_vm
, OID_AUTO
, region_footprint
, CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
, &vm_region_footprint
, 0, "");
150 sysctl_vm_self_region_footprint SYSCTL_HANDLER_ARGS
152 #pragma unused(arg1, arg2, oidp)
156 value
= task_self_region_footprint();
157 error
= SYSCTL_OUT(req
, &value
, sizeof (int));
166 error
= SYSCTL_IN(req
, &value
, sizeof (int));
170 task_self_region_footprint_set(value
);
173 SYSCTL_PROC(_vm
, OID_AUTO
, self_region_footprint
, CTLTYPE_INT
|CTLFLAG_RW
|CTLFLAG_ANYBODY
|CTLFLAG_LOCKED
|CTLFLAG_MASKED
, 0, 0, &sysctl_vm_self_region_footprint
, "I", "");
175 #endif /* DEVELOPMENT || DEBUG */
180 #if DEVELOPMENT || DEBUG
181 extern int panic_on_unsigned_execute
;
182 SYSCTL_INT(_vm
, OID_AUTO
, panic_on_unsigned_execute
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &panic_on_unsigned_execute
, 0, "");
183 #endif /* DEVELOPMENT || DEBUG */
185 extern int log_executable_mem_entry
;
186 extern int cs_executable_create_upl
;
187 extern int cs_executable_mem_entry
;
188 extern int cs_executable_wire
;
189 SYSCTL_INT(_vm
, OID_AUTO
, log_executable_mem_entry
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &log_executable_mem_entry
, 0, "");
190 SYSCTL_INT(_vm
, OID_AUTO
, cs_executable_create_upl
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_executable_create_upl
, 0, "");
191 SYSCTL_INT(_vm
, OID_AUTO
, cs_executable_mem_entry
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_executable_mem_entry
, 0, "");
192 SYSCTL_INT(_vm
, OID_AUTO
, cs_executable_wire
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_executable_wire
, 0, "");
193 #endif /* CONFIG_EMBEDDED */
195 #if DEVELOPMENT || DEBUG
196 extern int radar_20146450
;
197 SYSCTL_INT(_vm
, OID_AUTO
, radar_20146450
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &radar_20146450
, 0, "");
199 extern int macho_printf
;
200 SYSCTL_INT(_vm
, OID_AUTO
, macho_printf
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &macho_printf
, 0, "");
202 extern int apple_protect_pager_data_request_debug
;
203 SYSCTL_INT(_vm
, OID_AUTO
, apple_protect_pager_data_request_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &apple_protect_pager_data_request_debug
, 0, "");
205 #if __arm__ || __arm64__
206 /* These are meant to support the page table accounting unit test. */
207 extern unsigned int arm_hardware_page_size
;
208 extern unsigned int arm_pt_desc_size
;
209 extern unsigned int arm_pt_root_size
;
210 extern unsigned int free_page_size_tt_count
;
211 extern unsigned int free_two_page_size_tt_count
;
212 extern unsigned int free_tt_count
;
213 extern unsigned int inuse_user_tteroot_count
;
214 extern unsigned int inuse_kernel_tteroot_count
;
215 extern unsigned int inuse_user_ttepages_count
;
216 extern unsigned int inuse_kernel_ttepages_count
;
217 extern unsigned int inuse_user_ptepages_count
;
218 extern unsigned int inuse_kernel_ptepages_count
;
219 SYSCTL_UINT(_vm
, OID_AUTO
, native_hw_pagesize
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &arm_hardware_page_size
, 0, "");
220 SYSCTL_UINT(_vm
, OID_AUTO
, arm_pt_desc_size
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &arm_pt_desc_size
, 0, "");
221 SYSCTL_UINT(_vm
, OID_AUTO
, arm_pt_root_size
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &arm_pt_root_size
, 0, "");
222 SYSCTL_UINT(_vm
, OID_AUTO
, free_1page_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &free_page_size_tt_count
, 0, "");
223 SYSCTL_UINT(_vm
, OID_AUTO
, free_2page_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &free_two_page_size_tt_count
, 0, "");
224 SYSCTL_UINT(_vm
, OID_AUTO
, free_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &free_tt_count
, 0, "");
225 SYSCTL_UINT(_vm
, OID_AUTO
, user_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_user_tteroot_count
, 0, "");
226 SYSCTL_UINT(_vm
, OID_AUTO
, kernel_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_kernel_tteroot_count
, 0, "");
227 SYSCTL_UINT(_vm
, OID_AUTO
, user_tte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_user_ttepages_count
, 0, "");
228 SYSCTL_UINT(_vm
, OID_AUTO
, kernel_tte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_kernel_ttepages_count
, 0, "");
229 SYSCTL_UINT(_vm
, OID_AUTO
, user_pte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_user_ptepages_count
, 0, "");
230 SYSCTL_UINT(_vm
, OID_AUTO
, kernel_pte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_kernel_ptepages_count
, 0, "");
231 #endif /* __arm__ || __arm64__ */
234 extern int fourk_pager_data_request_debug
;
235 SYSCTL_INT(_vm
, OID_AUTO
, fourk_pager_data_request_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &fourk_pager_data_request_debug
, 0, "");
236 #endif /* __arm64__ */
237 #endif /* DEVELOPMENT || DEBUG */
239 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_compressor
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_compressor
, 0, "");
240 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_compressor_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_compressor_pages
, 0, "");
241 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_terminate
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_terminate
, 0, "");
242 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_terminate_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_terminate_failure
, 0, "");
243 SYSCTL_INT(_vm
, OID_AUTO
, vm_should_cow_but_wired
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.should_cow_but_wired
, 0, "");
244 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_extra_cow
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_extra_cow
, 0, "");
245 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_extra_cow_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_extra_cow_pages
, 0, "");
246 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_lookup_failure_write
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_lookup_failure_write
, 0, "");
247 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_lookup_failure_copy
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_lookup_failure_copy
, 0, "");
248 #if VM_SCAN_FOR_SHADOW_CHAIN
249 static int vm_shadow_max_enabled
= 0; /* Disabled by default */
250 extern int proc_shadow_max(void);
252 vm_shadow_max SYSCTL_HANDLER_ARGS
254 #pragma unused(arg1, arg2, oidp)
257 if (vm_shadow_max_enabled
)
258 value
= proc_shadow_max();
260 return SYSCTL_OUT(req
, &value
, sizeof(value
));
262 SYSCTL_PROC(_vm
, OID_AUTO
, vm_shadow_max
, CTLTYPE_INT
|CTLFLAG_RD
|CTLFLAG_LOCKED
,
263 0, 0, &vm_shadow_max
, "I", "");
265 SYSCTL_INT(_vm
, OID_AUTO
, vm_shadow_max_enabled
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_shadow_max_enabled
, 0, "");
267 #endif /* VM_SCAN_FOR_SHADOW_CHAIN */
269 SYSCTL_INT(_vm
, OID_AUTO
, vm_debug_events
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_debug_events
, 0, "");
271 __attribute__((noinline
)) int __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(
272 mach_port_t task_access_port
, int32_t calling_pid
, uint32_t calling_gid
, int32_t target_pid
);
274 * Sysctl's related to data/stack execution. See osfmk/vm/vm_map.c
277 #if DEVELOPMENT || DEBUG
278 extern int allow_stack_exec
, allow_data_exec
;
280 SYSCTL_INT(_vm
, OID_AUTO
, allow_stack_exec
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &allow_stack_exec
, 0, "");
281 SYSCTL_INT(_vm
, OID_AUTO
, allow_data_exec
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &allow_data_exec
, 0, "");
283 #endif /* DEVELOPMENT || DEBUG */
285 static const char *prot_values
[] = {
297 log_stack_execution_failure(addr64_t vaddr
, vm_prot_t prot
)
299 printf("Data/Stack execution not permitted: %s[pid %d] at virtual address 0x%qx, protections were %s\n",
300 current_proc()->p_comm
, current_proc()->p_pid
, vaddr
, prot_values
[prot
& VM_PROT_ALL
]);
304 * shared_region_unnest_logging: level of logging of unnesting events
306 * 1 - throttled logging of unexpected unnesting events (default)
307 * 2 - unthrottled logging of unexpected unnesting events
308 * 3+ - unthrottled logging of all unnesting events
310 int shared_region_unnest_logging
= 1;
312 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_unnest_logging
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
313 &shared_region_unnest_logging
, 0, "");
315 int vm_shared_region_unnest_log_interval
= 10;
316 int shared_region_unnest_log_count_threshold
= 5;
319 * Shared cache path enforcement.
322 #ifndef CONFIG_EMBEDDED
323 static int scdir_enforce
= 1;
324 static char scdir_path
[] = "/var/db/dyld/";
326 static int scdir_enforce
= 0;
327 static char scdir_path
[] = "/System/Library/Caches/com.apple.dyld/";
330 #ifndef SECURE_KERNEL
331 static int sysctl_scdir_enforce SYSCTL_HANDLER_ARGS
334 if (csr_check(CSR_ALLOW_UNRESTRICTED_FS
) != 0) {
335 printf("Failed attempt to set vm.enforce_shared_cache_dir sysctl\n");
338 #endif /* CONFIG_CSR */
339 return sysctl_handle_int(oidp
, arg1
, arg2
, req
);
342 SYSCTL_PROC(_vm
, OID_AUTO
, enforce_shared_cache_dir
, CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, &scdir_enforce
, 0, sysctl_scdir_enforce
, "I", "");
345 /* These log rate throttling state variables aren't thread safe, but
346 * are sufficient unto the task.
348 static int64_t last_unnest_log_time
= 0;
349 static int shared_region_unnest_log_count
= 0;
356 boolean_t is_nested_map
,
357 vm_map_offset_t lowest_unnestable_addr
)
361 if (shared_region_unnest_logging
== 0)
364 if (shared_region_unnest_logging
<= 2 &&
366 s
>= lowest_unnestable_addr
) {
368 * Unnesting of writable map entries is fine.
373 if (shared_region_unnest_logging
<= 1) {
375 if ((tv
.tv_sec
- last_unnest_log_time
) <
376 vm_shared_region_unnest_log_interval
) {
377 if (shared_region_unnest_log_count
++ >
378 shared_region_unnest_log_count_threshold
)
381 last_unnest_log_time
= tv
.tv_sec
;
382 shared_region_unnest_log_count
= 0;
386 DTRACE_VM4(log_unnest_badness
,
390 vm_map_offset_t
, lowest_unnestable_addr
);
391 printf("%s[%d] triggered unnest of range 0x%qx->0x%qx of DYLD shared region in VM map %p. While not abnormal for debuggers, this increases system memory footprint until the target exits.\n", current_proc()->p_comm
, current_proc()->p_pid
, (uint64_t)s
, (uint64_t)e
, (void *) VM_KERNEL_ADDRPERM(m
));
403 return (vm_map_check_protection(
405 vm_map_trunc_page(addr
,
406 vm_map_page_mask(map
)),
407 vm_map_round_page(addr
+len
,
408 vm_map_page_mask(map
)),
409 prot
== B_READ
? VM_PROT_READ
: VM_PROT_WRITE
));
421 kret
= vm_map_wire_kernel(map
,
422 vm_map_trunc_page(addr
,
423 vm_map_page_mask(map
)),
424 vm_map_round_page(addr
+len
,
425 vm_map_page_mask(map
)),
426 VM_PROT_READ
| VM_PROT_WRITE
, VM_KERN_MEMORY_BSD
,
432 case KERN_INVALID_ADDRESS
:
435 case KERN_PROTECTION_FAILURE
:
446 __unused
int dirtied
)
451 vm_map_offset_t vaddr
;
461 pmap
= get_task_pmap(current_task());
462 for (vaddr
= vm_map_trunc_page(addr
, PAGE_MASK
);
463 vaddr
< vm_map_round_page(addr
+len
, PAGE_MASK
);
464 vaddr
+= PAGE_SIZE
) {
465 paddr
= pmap_extract(pmap
, vaddr
);
466 pg
= PHYS_TO_VM_PAGE(paddr
);
467 vm_page_set_modified(pg
);
474 kret
= vm_map_unwire(map
,
475 vm_map_trunc_page(addr
,
476 vm_map_page_mask(map
)),
477 vm_map_round_page(addr
+len
,
478 vm_map_page_mask(map
)),
483 case KERN_INVALID_ADDRESS
:
486 case KERN_PROTECTION_FAILURE
:
500 character
= (char)byte
;
501 return (copyout((void *)&(character
), addr
, sizeof(char)) == 0 ? 0 : -1);
511 character
= (char)byte
;
512 return (copyout((void *)&(character
), addr
, sizeof(char)) == 0 ? 0 : -1);
515 int fubyte(user_addr_t addr
)
519 if (copyin(addr
, (void *) &byte
, sizeof(char)))
524 int fuibyte(user_addr_t addr
)
528 if (copyin(addr
, (void *) &(byte
), sizeof(char)))
538 return (copyout((void *) &word
, addr
, sizeof(int)) == 0 ? 0 : -1);
541 long fuword(user_addr_t addr
)
545 if (copyin(addr
, (void *) &word
, sizeof(int)))
550 /* suiword and fuiword are the same as suword and fuword, respectively */
557 return (copyout((void *) &word
, addr
, sizeof(int)) == 0 ? 0 : -1);
560 long fuiword(user_addr_t addr
)
564 if (copyin(addr
, (void *) &word
, sizeof(int)))
570 * With a 32-bit kernel and mixed 32/64-bit user tasks, this interface allows the
571 * fetching and setting of process-sized size_t and pointer values.
574 sulong(user_addr_t addr
, int64_t word
)
577 if (IS_64BIT_PROCESS(current_proc())) {
578 return(copyout((void *)&word
, addr
, sizeof(word
)) == 0 ? 0 : -1);
580 return(suiword(addr
, (long)word
));
585 fulong(user_addr_t addr
)
589 if (IS_64BIT_PROCESS(current_proc())) {
590 if (copyin(addr
, (void *)&longword
, sizeof(longword
)) != 0)
594 return((int64_t)fuiword(addr
));
599 suulong(user_addr_t addr
, uint64_t uword
)
602 if (IS_64BIT_PROCESS(current_proc())) {
603 return(copyout((void *)&uword
, addr
, sizeof(uword
)) == 0 ? 0 : -1);
605 return(suiword(addr
, (uint32_t)uword
));
610 fuulong(user_addr_t addr
)
614 if (IS_64BIT_PROCESS(current_proc())) {
615 if (copyin(addr
, (void *)&ulongword
, sizeof(ulongword
)) != 0)
619 return((uint64_t)fuiword(addr
));
624 swapon(__unused proc_t procp
, __unused
struct swapon_args
*uap
, __unused
int *retval
)
632 * Find the BSD process ID for the Mach task associated with the given Mach port
635 * Parameters: args User argument descriptor (see below)
637 * Indirect parameters: args->t Mach port name
638 * args->pid Process ID (returned value; see below)
640 * Returns: KERL_SUCCESS Success
641 * KERN_FAILURE Not success
643 * Implicit returns: args->pid Process ID
648 struct pid_for_task_args
*args
)
650 mach_port_name_t t
= args
->t
;
651 user_addr_t pid_addr
= args
->pid
;
655 kern_return_t err
= KERN_SUCCESS
;
657 AUDIT_MACH_SYSCALL_ENTER(AUE_PIDFORTASK
);
658 AUDIT_ARG(mach_port1
, t
);
660 t1
= port_name_to_task_inspect(t
);
662 if (t1
== TASK_NULL
) {
666 p
= get_bsdtask_info(t1
);
670 } else if (is_corpsetask(t1
)) {
680 (void) copyout((char *) &pid
, pid_addr
, sizeof(int));
681 AUDIT_MACH_SYSCALL_EXIT(err
);
687 * tfp_policy = KERN_TFP_POLICY_DENY; Deny Mode: None allowed except for self
688 * tfp_policy = KERN_TFP_POLICY_DEFAULT; default mode: all posix checks and upcall via task port for authentication
691 static int tfp_policy
= KERN_TFP_POLICY_DEFAULT
;
694 * Routine: task_for_pid_posix_check
696 * Verify that the current process should be allowed to
697 * get the target process's task port. This is only
699 * - The current process is root
700 * OR all of the following are true:
701 * - The target process's real, effective, and saved uids
702 * are the same as the current proc's euid,
703 * - The target process's group set is a subset of the
704 * calling process's group set, and
705 * - The target process hasn't switched credentials.
707 * Returns: TRUE: permitted
711 task_for_pid_posix_check(proc_t target
)
713 kauth_cred_t targetcred
, mycred
;
717 /* No task_for_pid on bad targets */
718 if (target
->p_stat
== SZOMB
) {
722 mycred
= kauth_cred_get();
723 myuid
= kauth_cred_getuid(mycred
);
725 /* If we're running as root, the check passes */
726 if (kauth_cred_issuser(mycred
))
729 /* We're allowed to get our own task port */
730 if (target
== current_proc())
734 * Under DENY, only root can get another proc's task port,
735 * so no more checks are needed.
737 if (tfp_policy
== KERN_TFP_POLICY_DENY
) {
741 targetcred
= kauth_cred_proc_ref(target
);
744 /* Do target's ruid, euid, and saved uid match my euid? */
745 if ((kauth_cred_getuid(targetcred
) != myuid
) ||
746 (kauth_cred_getruid(targetcred
) != myuid
) ||
747 (kauth_cred_getsvuid(targetcred
) != myuid
)) {
752 /* Are target's groups a subset of my groups? */
753 if (kauth_cred_gid_subset(targetcred
, mycred
, &allowed
) ||
759 /* Has target switched credentials? */
760 if (target
->p_flag
& P_SUGID
) {
766 kauth_cred_unref(&targetcred
);
771 * __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__
773 * Description: Waits for the user space daemon to respond to the request
774 * we made. Function declared non inline to be visible in
775 * stackshots and spindumps as well as debugging.
777 __attribute__((noinline
)) int __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(
778 mach_port_t task_access_port
, int32_t calling_pid
, uint32_t calling_gid
, int32_t target_pid
)
780 return check_task_access(task_access_port
, calling_pid
, calling_gid
, target_pid
);
784 * Routine: task_for_pid
786 * Get the task port for another "process", named by its
787 * process ID on the same host as "target_task".
789 * Only permitted to privileged processes, or processes
790 * with the same user ID.
792 * Note: if pid == 0, an error is return no matter who is calling.
794 * XXX This should be a BSD system call, not a Mach trap!!!
798 struct task_for_pid_args
*args
)
800 mach_port_name_t target_tport
= args
->target_tport
;
802 user_addr_t task_addr
= args
->t
;
803 proc_t p
= PROC_NULL
;
804 task_t t1
= TASK_NULL
;
805 task_t task
= TASK_NULL
;
806 mach_port_name_t tret
= MACH_PORT_NULL
;
807 ipc_port_t tfpport
= MACH_PORT_NULL
;
811 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID
);
813 AUDIT_ARG(mach_port1
, target_tport
);
815 /* Always check if pid == 0 */
817 (void ) copyout((char *)&t1
, task_addr
, sizeof(mach_port_name_t
));
818 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE
);
819 return(KERN_FAILURE
);
822 t1
= port_name_to_task(target_tport
);
823 if (t1
== TASK_NULL
) {
824 (void) copyout((char *)&t1
, task_addr
, sizeof(mach_port_name_t
));
825 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE
);
826 return(KERN_FAILURE
);
831 if (p
== PROC_NULL
) {
832 error
= KERN_FAILURE
;
837 AUDIT_ARG(process
, p
);
840 if (!(task_for_pid_posix_check(p
))) {
841 error
= KERN_FAILURE
;
845 if (p
->task
== TASK_NULL
) {
846 error
= KERN_SUCCESS
;
851 error
= mac_proc_check_get_task(kauth_cred_get(), p
);
853 error
= KERN_FAILURE
;
858 /* Grab a task reference since the proc ref might be dropped if an upcall to task access server is made */
860 task_reference(task
);
862 /* If we aren't root and target's task access port is set... */
863 if (!kauth_cred_issuser(kauth_cred_get()) &&
864 p
!= current_proc() &&
865 (task_get_task_access_port(task
, &tfpport
) == 0) &&
866 (tfpport
!= IPC_PORT_NULL
)) {
868 if (tfpport
== IPC_PORT_DEAD
) {
869 error
= KERN_PROTECTION_FAILURE
;
874 * Drop the proc_find proc ref before making an upcall
875 * to taskgated, since holding a proc_find
876 * ref while making an upcall can cause deadlock.
881 /* Call up to the task access server */
882 error
= __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport
, proc_selfpid(), kauth_getgid(), pid
);
884 if (error
!= MACH_MSG_SUCCESS
) {
885 if (error
== MACH_RCV_INTERRUPTED
)
886 error
= KERN_ABORTED
;
888 error
= KERN_FAILURE
;
893 /* Grant task port access */
894 extmod_statistics_incr_task_for_pid(task
);
895 sright
= (void *) convert_task_to_port(task
);
897 /* Check if the task has been corpsified */
898 if (is_corpsetask(task
)) {
899 /* task ref consumed by convert_task_to_port */
901 ipc_port_release_send(sright
);
902 error
= KERN_FAILURE
;
906 /* task ref consumed by convert_task_to_port */
908 tret
= ipc_port_copyout_send(
910 get_task_ipcspace(current_task()));
912 error
= KERN_SUCCESS
;
916 AUDIT_ARG(mach_port2
, tret
);
917 (void) copyout((char *) &tret
, task_addr
, sizeof(mach_port_name_t
));
919 if (tfpport
!= IPC_PORT_NULL
) {
920 ipc_port_release_send(tfpport
);
922 if (task
!= TASK_NULL
) {
923 task_deallocate(task
);
927 AUDIT_MACH_SYSCALL_EXIT(error
);
932 * Routine: task_name_for_pid
934 * Get the task name port for another "process", named by its
935 * process ID on the same host as "target_task".
937 * Only permitted to privileged processes, or processes
938 * with the same user ID.
940 * XXX This should be a BSD system call, not a Mach trap!!!
945 struct task_name_for_pid_args
*args
)
947 mach_port_name_t target_tport
= args
->target_tport
;
949 user_addr_t task_addr
= args
->t
;
950 proc_t p
= PROC_NULL
;
952 mach_port_name_t tret
;
954 int error
= 0, refheld
= 0;
955 kauth_cred_t target_cred
;
957 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKNAMEFORPID
);
959 AUDIT_ARG(mach_port1
, target_tport
);
961 t1
= port_name_to_task(target_tport
);
962 if (t1
== TASK_NULL
) {
963 (void) copyout((char *)&t1
, task_addr
, sizeof(mach_port_name_t
));
964 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE
);
965 return(KERN_FAILURE
);
969 if (p
!= PROC_NULL
) {
970 AUDIT_ARG(process
, p
);
971 target_cred
= kauth_cred_proc_ref(p
);
974 if ((p
->p_stat
!= SZOMB
)
975 && ((current_proc() == p
)
976 || kauth_cred_issuser(kauth_cred_get())
977 || ((kauth_cred_getuid(target_cred
) == kauth_cred_getuid(kauth_cred_get())) &&
978 ((kauth_cred_getruid(target_cred
) == kauth_getruid()))))) {
980 if (p
->task
!= TASK_NULL
) {
981 task_reference(p
->task
);
983 error
= mac_proc_check_get_task_name(kauth_cred_get(), p
);
985 task_deallocate(p
->task
);
989 sright
= (void *)convert_task_name_to_port(p
->task
);
990 tret
= ipc_port_copyout_send(sright
,
991 get_task_ipcspace(current_task()));
993 tret
= MACH_PORT_NULL
;
995 AUDIT_ARG(mach_port2
, tret
);
996 (void) copyout((char *)&tret
, task_addr
, sizeof(mach_port_name_t
));
998 error
= KERN_SUCCESS
;
1006 task_deallocate(t1
);
1007 tret
= MACH_PORT_NULL
;
1008 (void) copyout((char *) &tret
, task_addr
, sizeof(mach_port_name_t
));
1009 error
= KERN_FAILURE
;
1012 kauth_cred_unref(&target_cred
);
1015 AUDIT_MACH_SYSCALL_EXIT(error
);
1020 pid_suspend(struct proc
*p __unused
, struct pid_suspend_args
*args
, int *ret
)
1022 task_t target
= NULL
;
1023 proc_t targetproc
= PROC_NULL
;
1024 int pid
= args
->pid
;
1028 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_SUSPEND
);
1040 targetproc
= proc_find(pid
);
1041 if (targetproc
== PROC_NULL
) {
1046 if (!task_for_pid_posix_check(targetproc
)) {
1051 target
= targetproc
->task
;
1052 #ifndef CONFIG_EMBEDDED
1053 if (target
!= TASK_NULL
) {
1054 mach_port_t tfpport
;
1056 /* If we aren't root and target's task access port is set... */
1057 if (!kauth_cred_issuser(kauth_cred_get()) &&
1058 targetproc
!= current_proc() &&
1059 (task_get_task_access_port(target
, &tfpport
) == 0) &&
1060 (tfpport
!= IPC_PORT_NULL
)) {
1062 if (tfpport
== IPC_PORT_DEAD
) {
1067 /* Call up to the task access server */
1068 error
= __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport
, proc_selfpid(), kauth_getgid(), pid
);
1070 if (error
!= MACH_MSG_SUCCESS
) {
1071 if (error
== MACH_RCV_INTERRUPTED
)
1081 task_reference(target
);
1082 error
= task_pidsuspend(target
);
1084 if (error
== KERN_INVALID_ARGUMENT
) {
1090 #if CONFIG_MEMORYSTATUS
1092 memorystatus_on_suspend(targetproc
);
1096 task_deallocate(target
);
1099 if (targetproc
!= PROC_NULL
)
1100 proc_rele(targetproc
);
1106 pid_resume(struct proc
*p __unused
, struct pid_resume_args
*args
, int *ret
)
1108 task_t target
= NULL
;
1109 proc_t targetproc
= PROC_NULL
;
1110 int pid
= args
->pid
;
1114 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_RESUME
);
1126 targetproc
= proc_find(pid
);
1127 if (targetproc
== PROC_NULL
) {
1132 if (!task_for_pid_posix_check(targetproc
)) {
1137 target
= targetproc
->task
;
1138 #ifndef CONFIG_EMBEDDED
1139 if (target
!= TASK_NULL
) {
1140 mach_port_t tfpport
;
1142 /* If we aren't root and target's task access port is set... */
1143 if (!kauth_cred_issuser(kauth_cred_get()) &&
1144 targetproc
!= current_proc() &&
1145 (task_get_task_access_port(target
, &tfpport
) == 0) &&
1146 (tfpport
!= IPC_PORT_NULL
)) {
1148 if (tfpport
== IPC_PORT_DEAD
) {
1153 /* Call up to the task access server */
1154 error
= __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport
, proc_selfpid(), kauth_getgid(), pid
);
1156 if (error
!= MACH_MSG_SUCCESS
) {
1157 if (error
== MACH_RCV_INTERRUPTED
)
1169 resume_proc_sockets(targetproc
);
1170 #endif /* SOCKETS */
1171 #endif /* CONFIG_EMBEDDED */
1173 task_reference(target
);
1175 #if CONFIG_MEMORYSTATUS
1176 memorystatus_on_resume(targetproc
);
1179 error
= task_pidresume(target
);
1181 if (error
== KERN_INVALID_ARGUMENT
) {
1184 if (error
== KERN_MEMORY_ERROR
) {
1185 psignal(targetproc
, SIGKILL
);
1192 task_deallocate(target
);
1195 if (targetproc
!= PROC_NULL
)
1196 proc_rele(targetproc
);
1204 * Freeze the specified process (provided in args->pid), or find and freeze a PID.
1205 * When a process is specified, this call is blocking, otherwise we wake up the
1206 * freezer thread and do not block on a process being frozen.
1209 pid_hibernate(struct proc
*p __unused
, struct pid_hibernate_args
*args
, int *ret
)
1212 proc_t targetproc
= PROC_NULL
;
1213 int pid
= args
->pid
;
1215 #ifndef CONFIG_FREEZE
1220 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_HIBERNATE
);
1228 * If a pid has been provided, we obtain the process handle and call task_for_pid_posix_check().
1232 targetproc
= proc_find(pid
);
1234 if (targetproc
== PROC_NULL
) {
1239 if (!task_for_pid_posix_check(targetproc
)) {
1246 vm_pageout_anonymous_pages();
1247 } else if (pid
== -1) {
1248 memorystatus_on_inactivity(targetproc
);
1250 error
= memorystatus_freeze_process_sync(targetproc
);
1255 #endif /* CONFIG_FREEZE */
1257 if (targetproc
!= PROC_NULL
)
1258 proc_rele(targetproc
);
1262 #endif /* CONFIG_EMBEDDED */
1266 networking_memstatus_callout(proc_t p
, uint32_t status
)
1268 struct filedesc
*fdp
;
1272 * proc list lock NOT held
1273 * proc lock NOT held
1274 * a reference on the proc has been held / shall be dropped by the caller.
1276 LCK_MTX_ASSERT(proc_list_mlock
, LCK_MTX_ASSERT_NOTOWNED
);
1277 LCK_MTX_ASSERT(&p
->p_mlock
, LCK_MTX_ASSERT_NOTOWNED
);
1281 for (i
= 0; i
< fdp
->fd_nfiles
; i
++) {
1282 struct fileproc
*fp
;
1284 fp
= fdp
->fd_ofiles
[i
];
1285 if (fp
== NULL
|| (fdp
->fd_ofileflags
[i
] & UF_RESERVED
) != 0) {
1288 switch (FILEGLOB_DTYPE(fp
->f_fglob
)) {
1290 case DTYPE_NETPOLICY
:
1291 necp_fd_memstatus(p
, status
,
1292 (struct necp_fd_data
*)fp
->f_fglob
->fg_data
);
1306 networking_defunct_callout(proc_t p
, void *arg
)
1308 struct pid_shutdown_sockets_args
*args
= arg
;
1309 int pid
= args
->pid
;
1310 int level
= args
->level
;
1311 struct filedesc
*fdp
;
1316 for (i
= 0; i
< fdp
->fd_nfiles
; i
++) {
1317 struct fileproc
*fp
= fdp
->fd_ofiles
[i
];
1318 struct fileglob
*fg
;
1320 if (fp
== NULL
|| (fdp
->fd_ofileflags
[i
] & UF_RESERVED
) != 0) {
1325 switch (FILEGLOB_DTYPE(fg
)) {
1326 case DTYPE_SOCKET
: {
1327 struct socket
*so
= (struct socket
*)fg
->fg_data
;
1328 if (p
->p_pid
== pid
|| so
->last_pid
== pid
||
1329 ((so
->so_flags
& SOF_DELEGATED
) && so
->e_pid
== pid
)) {
1330 /* Call networking stack with socket and level */
1331 (void) socket_defunct(p
, so
, level
);
1336 case DTYPE_NETPOLICY
:
1337 /* first pass: defunct necp and get stats for ntstat */
1338 if (p
->p_pid
== pid
) {
1340 (struct necp_fd_data
*)fg
->fg_data
);
1351 return (PROC_RETURNED
);
1355 pid_shutdown_sockets(struct proc
*p __unused
, struct pid_shutdown_sockets_args
*args
, int *ret
)
1358 proc_t targetproc
= PROC_NULL
;
1359 int pid
= args
->pid
;
1360 int level
= args
->level
;
1362 if (level
!= SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC
&&
1363 level
!= SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL
) {
1369 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_SHUTDOWN_SOCKETS
);
1376 targetproc
= proc_find(pid
);
1377 if (targetproc
== PROC_NULL
) {
1382 if (!task_for_pid_posix_check(targetproc
)) {
1387 proc_iterate(PROC_ALLPROCLIST
| PROC_NOWAITTRANS
,
1388 networking_defunct_callout
, args
, NULL
, NULL
);
1391 if (targetproc
!= PROC_NULL
)
1392 proc_rele(targetproc
);
1397 #endif /* SOCKETS */
1400 sysctl_settfp_policy(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1401 __unused
int arg2
, struct sysctl_req
*req
)
1406 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
1407 if (error
|| req
->newptr
== USER_ADDR_NULL
)
1410 if (!kauth_cred_issuser(kauth_cred_get()))
1413 if ((error
= SYSCTL_IN(req
, &new_value
, sizeof(int)))) {
1416 if ((new_value
== KERN_TFP_POLICY_DENY
)
1417 || (new_value
== KERN_TFP_POLICY_DEFAULT
))
1418 tfp_policy
= new_value
;
1426 #if defined(SECURE_KERNEL)
1427 static int kern_secure_kernel
= 1;
1429 static int kern_secure_kernel
= 0;
1432 SYSCTL_INT(_kern
, OID_AUTO
, secure_kernel
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &kern_secure_kernel
, 0, "");
1434 SYSCTL_NODE(_kern
, KERN_TFP
, tfp
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "tfp");
1435 SYSCTL_PROC(_kern_tfp
, KERN_TFP_POLICY
, policy
, CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
1436 &tfp_policy
, sizeof(uint32_t), &sysctl_settfp_policy
,"I","policy");
1438 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_trace_level
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
1439 &shared_region_trace_level
, 0, "");
1440 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_version
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1441 &shared_region_version
, 0, "");
1442 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_persistence
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
1443 &shared_region_persistence
, 0, "");
1446 * shared_region_check_np:
1448 * This system call is intended for dyld.
1450 * dyld calls this when any process starts to see if the process's shared
1451 * region is already set up and ready to use.
1452 * This call returns the base address of the first mapping in the
1453 * process's shared region's first mapping.
1454 * dyld will then check what's mapped at that address.
1456 * If the shared region is empty, dyld will then attempt to map the shared
1457 * cache file in the shared region via the shared_region_map_np() system call.
1459 * If something's already mapped in the shared region, dyld will check if it
1460 * matches the shared cache it would like to use for that process.
1461 * If it matches, evrything's ready and the process can proceed and use the
1463 * If it doesn't match, dyld will unmap the shared region and map the shared
1464 * cache into the process's address space via mmap().
1467 * EINVAL no shared region
1468 * ENOMEM shared region is empty
1469 * EFAULT bad address for "start_address"
1472 shared_region_check_np(
1473 __unused
struct proc
*p
,
1474 struct shared_region_check_np_args
*uap
,
1475 __unused
int *retvalp
)
1477 vm_shared_region_t shared_region
;
1478 mach_vm_offset_t start_address
= 0;
1482 SHARED_REGION_TRACE_DEBUG(
1483 ("shared_region: %p [%d(%s)] -> check_np(0x%llx)\n",
1484 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1485 p
->p_pid
, p
->p_comm
,
1486 (uint64_t)uap
->start_address
));
1488 /* retrieve the current tasks's shared region */
1489 shared_region
= vm_shared_region_get(current_task());
1490 if (shared_region
!= NULL
) {
1491 /* retrieve address of its first mapping... */
1492 kr
= vm_shared_region_start_address(shared_region
,
1494 if (kr
!= KERN_SUCCESS
) {
1497 /* ... and give it to the caller */
1498 error
= copyout(&start_address
,
1499 (user_addr_t
) uap
->start_address
,
1500 sizeof (start_address
));
1502 SHARED_REGION_TRACE_ERROR(
1503 ("shared_region: %p [%d(%s)] "
1505 "copyout(0x%llx) error %d\n",
1506 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1507 p
->p_pid
, p
->p_comm
,
1508 (uint64_t)uap
->start_address
, (uint64_t)start_address
,
1512 vm_shared_region_deallocate(shared_region
);
1514 /* no shared region ! */
1518 SHARED_REGION_TRACE_DEBUG(
1519 ("shared_region: %p [%d(%s)] check_np(0x%llx) <- 0x%llx %d\n",
1520 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1521 p
->p_pid
, p
->p_comm
,
1522 (uint64_t)uap
->start_address
, (uint64_t)start_address
, error
));
1529 shared_region_copyin_mappings(
1531 user_addr_t user_mappings
,
1532 unsigned int mappings_count
,
1533 struct shared_file_mapping_np
*mappings
)
1536 vm_size_t mappings_size
= 0;
1538 /* get the list of mappings the caller wants us to establish */
1539 mappings_size
= (vm_size_t
) (mappings_count
* sizeof (mappings
[0]));
1540 error
= copyin(user_mappings
,
1544 SHARED_REGION_TRACE_ERROR(
1545 ("shared_region: %p [%d(%s)] map(): "
1546 "copyin(0x%llx, %d) failed (error=%d)\n",
1547 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1548 p
->p_pid
, p
->p_comm
,
1549 (uint64_t)user_mappings
, mappings_count
, error
));
1554 * shared_region_map_np()
1556 * This system call is intended for dyld.
1558 * dyld uses this to map a shared cache file into a shared region.
1559 * This is usually done only the first time a shared cache is needed.
1560 * Subsequent processes will just use the populated shared region without
1561 * requiring any further setup.
1564 _shared_region_map_and_slide(
1567 uint32_t mappings_count
,
1568 struct shared_file_mapping_np
*mappings
,
1570 user_addr_t slide_start
,
1571 user_addr_t slide_size
)
1575 struct fileproc
*fp
;
1576 struct vnode
*vp
, *root_vp
, *scdir_vp
;
1577 struct vnode_attr va
;
1579 memory_object_size_t file_size
;
1581 vm_prot_t maxprot
= VM_PROT_ALL
;
1583 memory_object_control_t file_control
;
1584 struct vm_shared_region
*shared_region
;
1587 SHARED_REGION_TRACE_DEBUG(
1588 ("shared_region: %p [%d(%s)] -> map\n",
1589 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1590 p
->p_pid
, p
->p_comm
));
1592 shared_region
= NULL
;
1597 /* get file structure from file descriptor */
1598 error
= fp_lookup(p
, fd
, &fp
, 0);
1600 SHARED_REGION_TRACE_ERROR(
1601 ("shared_region: %p [%d(%s)] map: "
1602 "fd=%d lookup failed (error=%d)\n",
1603 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1604 p
->p_pid
, p
->p_comm
, fd
, error
));
1608 /* make sure we're attempting to map a vnode */
1609 if (FILEGLOB_DTYPE(fp
->f_fglob
) != DTYPE_VNODE
) {
1610 SHARED_REGION_TRACE_ERROR(
1611 ("shared_region: %p [%d(%s)] map: "
1612 "fd=%d not a vnode (type=%d)\n",
1613 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1614 p
->p_pid
, p
->p_comm
,
1615 fd
, FILEGLOB_DTYPE(fp
->f_fglob
)));
1620 /* we need at least read permission on the file */
1621 if (! (fp
->f_fglob
->fg_flag
& FREAD
)) {
1622 SHARED_REGION_TRACE_ERROR(
1623 ("shared_region: %p [%d(%s)] map: "
1624 "fd=%d not readable\n",
1625 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1626 p
->p_pid
, p
->p_comm
, fd
));
1631 /* get vnode from file structure */
1632 error
= vnode_getwithref((vnode_t
) fp
->f_fglob
->fg_data
);
1634 SHARED_REGION_TRACE_ERROR(
1635 ("shared_region: %p [%d(%s)] map: "
1636 "fd=%d getwithref failed (error=%d)\n",
1637 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1638 p
->p_pid
, p
->p_comm
, fd
, error
));
1641 vp
= (struct vnode
*) fp
->f_fglob
->fg_data
;
1643 /* make sure the vnode is a regular file */
1644 if (vp
->v_type
!= VREG
) {
1645 SHARED_REGION_TRACE_ERROR(
1646 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1647 "not a file (type=%d)\n",
1648 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1649 p
->p_pid
, p
->p_comm
,
1650 (void *)VM_KERNEL_ADDRPERM(vp
),
1651 vp
->v_name
, vp
->v_type
));
1657 /* pass in 0 for the offset argument because AMFI does not need the offset
1658 of the shared cache */
1659 error
= mac_file_check_mmap(vfs_context_ucred(vfs_context_current()),
1660 fp
->f_fglob
, VM_PROT_ALL
, MAP_FILE
, 0, &maxprot
);
1666 /* make sure vnode is on the process's root volume */
1667 root_vp
= p
->p_fd
->fd_rdir
;
1668 if (root_vp
== NULL
) {
1669 root_vp
= rootvnode
;
1672 * Chroot-ed processes can't use the shared_region.
1678 if (vp
->v_mount
!= root_vp
->v_mount
) {
1679 SHARED_REGION_TRACE_ERROR(
1680 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1681 "not on process's root volume\n",
1682 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1683 p
->p_pid
, p
->p_comm
,
1684 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
));
1689 /* make sure vnode is owned by "root" */
1691 VATTR_WANTED(&va
, va_uid
);
1692 error
= vnode_getattr(vp
, &va
, vfs_context_current());
1694 SHARED_REGION_TRACE_ERROR(
1695 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1696 "vnode_getattr(%p) failed (error=%d)\n",
1697 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1698 p
->p_pid
, p
->p_comm
,
1699 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1700 (void *)VM_KERNEL_ADDRPERM(vp
), error
));
1703 if (va
.va_uid
!= 0) {
1704 SHARED_REGION_TRACE_ERROR(
1705 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1706 "owned by uid=%d instead of 0\n",
1707 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1708 p
->p_pid
, p
->p_comm
,
1709 (void *)VM_KERNEL_ADDRPERM(vp
),
1710 vp
->v_name
, va
.va_uid
));
1715 if (scdir_enforce
) {
1716 /* get vnode for scdir_path */
1717 error
= vnode_lookup(scdir_path
, 0, &scdir_vp
, vfs_context_current());
1719 SHARED_REGION_TRACE_ERROR(
1720 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1721 "vnode_lookup(%s) failed (error=%d)\n",
1722 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1723 p
->p_pid
, p
->p_comm
,
1724 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1725 scdir_path
, error
));
1729 /* ensure parent is scdir_vp */
1730 if (vnode_parent(vp
) != scdir_vp
) {
1731 SHARED_REGION_TRACE_ERROR(
1732 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1733 "shared cache file not in %s\n",
1734 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1735 p
->p_pid
, p
->p_comm
,
1736 (void *)VM_KERNEL_ADDRPERM(vp
),
1737 vp
->v_name
, scdir_path
));
1743 /* get vnode size */
1744 error
= vnode_size(vp
, &fs
, vfs_context_current());
1746 SHARED_REGION_TRACE_ERROR(
1747 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1748 "vnode_size(%p) failed (error=%d)\n",
1749 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1750 p
->p_pid
, p
->p_comm
,
1751 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1752 (void *)VM_KERNEL_ADDRPERM(vp
), error
));
1757 /* get the file's memory object handle */
1758 file_control
= ubc_getobject(vp
, UBC_HOLDOBJECT
);
1759 if (file_control
== MEMORY_OBJECT_CONTROL_NULL
) {
1760 SHARED_REGION_TRACE_ERROR(
1761 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1762 "no memory object\n",
1763 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1764 p
->p_pid
, p
->p_comm
,
1765 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
));
1770 /* check that the mappings are properly covered by code signatures */
1771 if (!cs_system_enforcement()) {
1772 /* code signing is not enforced: no need to check */
1773 } else for (i
= 0; i
< mappings_count
; i
++) {
1774 if (mappings
[i
].sfm_init_prot
& VM_PROT_ZF
) {
1775 /* zero-filled mapping: not backed by the file */
1778 if (ubc_cs_is_range_codesigned(vp
,
1779 mappings
[i
].sfm_file_offset
,
1780 mappings
[i
].sfm_size
)) {
1781 /* this mapping is fully covered by code signatures */
1784 SHARED_REGION_TRACE_ERROR(
1785 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1786 "mapping #%d/%d [0x%llx:0x%llx:0x%llx:0x%x:0x%x] "
1787 "is not code-signed\n",
1788 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1789 p
->p_pid
, p
->p_comm
,
1790 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1792 mappings
[i
].sfm_address
,
1793 mappings
[i
].sfm_size
,
1794 mappings
[i
].sfm_file_offset
,
1795 mappings
[i
].sfm_max_prot
,
1796 mappings
[i
].sfm_init_prot
));
1801 /* get the process's shared region (setup in vm_map_exec()) */
1802 shared_region
= vm_shared_region_trim_and_get(current_task());
1803 if (shared_region
== NULL
) {
1804 SHARED_REGION_TRACE_ERROR(
1805 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1806 "no shared region\n",
1807 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1808 p
->p_pid
, p
->p_comm
,
1809 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
));
1814 /* map the file into that shared region's submap */
1815 kr
= vm_shared_region_map_file(shared_region
,
1820 (void *) p
->p_fd
->fd_rdir
,
1824 if (kr
!= KERN_SUCCESS
) {
1825 SHARED_REGION_TRACE_ERROR(
1826 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1827 "vm_shared_region_map_file() failed kr=0x%x\n",
1828 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1829 p
->p_pid
, p
->p_comm
,
1830 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
, kr
));
1832 case KERN_INVALID_ADDRESS
:
1835 case KERN_PROTECTION_FAILURE
:
1842 case KERN_INVALID_ARGUMENT
:
1852 vnode_lock_spin(vp
);
1854 vp
->v_flag
|= VSHARED_DYLD
;
1858 /* update the vnode's access time */
1859 if (! (vnode_vfsvisflags(vp
) & MNT_NOATIME
)) {
1861 nanotime(&va
.va_access_time
);
1862 VATTR_SET_ACTIVE(&va
, va_access_time
);
1863 vnode_setattr(vp
, &va
, vfs_context_current());
1866 if (p
->p_flag
& P_NOSHLIB
) {
1867 /* signal that this process is now using split libraries */
1868 OSBitAndAtomic(~((uint32_t)P_NOSHLIB
), &p
->p_flag
);
1874 * release the vnode...
1875 * ubc_map() still holds it for us in the non-error case
1877 (void) vnode_put(vp
);
1881 /* release the file descriptor */
1882 fp_drop(p
, fd
, fp
, 0);
1885 if (scdir_vp
!= NULL
) {
1886 (void)vnode_put(scdir_vp
);
1890 if (shared_region
!= NULL
) {
1891 vm_shared_region_deallocate(shared_region
);
1894 SHARED_REGION_TRACE_DEBUG(
1895 ("shared_region: %p [%d(%s)] <- map\n",
1896 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1897 p
->p_pid
, p
->p_comm
));
1903 shared_region_map_and_slide_np(
1905 struct shared_region_map_and_slide_np_args
*uap
,
1906 __unused
int *retvalp
)
1908 struct shared_file_mapping_np
*mappings
;
1909 unsigned int mappings_count
= uap
->count
;
1910 kern_return_t kr
= KERN_SUCCESS
;
1911 uint32_t slide
= uap
->slide
;
1913 #define SFM_MAX_STACK 8
1914 struct shared_file_mapping_np stack_mappings
[SFM_MAX_STACK
];
1916 /* Is the process chrooted?? */
1917 if (p
->p_fd
->fd_rdir
!= NULL
) {
1922 if ((kr
= vm_shared_region_sliding_valid(slide
)) != KERN_SUCCESS
) {
1923 if (kr
== KERN_INVALID_ARGUMENT
) {
1925 * This will happen if we request sliding again
1926 * with the same slide value that was used earlier
1927 * for the very first sliding.
1934 if (mappings_count
== 0) {
1935 SHARED_REGION_TRACE_INFO(
1936 ("shared_region: %p [%d(%s)] map(): "
1938 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1939 p
->p_pid
, p
->p_comm
));
1940 kr
= 0; /* no mappings: we're done ! */
1942 } else if (mappings_count
<= SFM_MAX_STACK
) {
1943 mappings
= &stack_mappings
[0];
1945 SHARED_REGION_TRACE_ERROR(
1946 ("shared_region: %p [%d(%s)] map(): "
1947 "too many mappings (%d)\n",
1948 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1949 p
->p_pid
, p
->p_comm
,
1955 if ( (kr
= shared_region_copyin_mappings(p
, uap
->mappings
, uap
->count
, mappings
))) {
1960 kr
= _shared_region_map_and_slide(p
, uap
->fd
, mappings_count
, mappings
,
1962 uap
->slide_start
, uap
->slide_size
);
1963 if (kr
!= KERN_SUCCESS
) {
1971 /* sysctl overflow room */
1973 SYSCTL_INT (_vm
, OID_AUTO
, pagesize
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1974 (int *) &page_size
, 0, "vm page size");
1976 /* vm_page_free_target is provided as a makeshift solution for applications that want to
1977 allocate buffer space, possibly purgeable memory, but not cause inactive pages to be
1978 reclaimed. It allows the app to calculate how much memory is free outside the free target. */
1979 extern unsigned int vm_page_free_target
;
1980 SYSCTL_INT(_vm
, OID_AUTO
, vm_page_free_target
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1981 &vm_page_free_target
, 0, "Pageout daemon free target");
1983 SYSCTL_INT(_vm
, OID_AUTO
, memory_pressure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1984 &vm_pageout_state
.vm_memory_pressure
, 0, "Memory pressure indicator");
1987 vm_ctl_page_free_wanted SYSCTL_HANDLER_ARGS
1989 #pragma unused(oidp, arg1, arg2)
1990 unsigned int page_free_wanted
;
1992 page_free_wanted
= mach_vm_ctl_page_free_wanted();
1993 return SYSCTL_OUT(req
, &page_free_wanted
, sizeof (page_free_wanted
));
1995 SYSCTL_PROC(_vm
, OID_AUTO
, page_free_wanted
,
1996 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
1997 0, 0, vm_ctl_page_free_wanted
, "I", "");
1999 extern unsigned int vm_page_purgeable_count
;
2000 SYSCTL_INT(_vm
, OID_AUTO
, page_purgeable_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2001 &vm_page_purgeable_count
, 0, "Purgeable page count");
2003 extern unsigned int vm_page_purgeable_wired_count
;
2004 SYSCTL_INT(_vm
, OID_AUTO
, page_purgeable_wired_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2005 &vm_page_purgeable_wired_count
, 0, "Wired purgeable page count");
2007 #if DEVELOPMENT || DEBUG
2008 extern uint64_t get_pages_grabbed_count(void);
2011 pages_grabbed SYSCTL_HANDLER_ARGS
2013 #pragma unused(arg1, arg2, oidp)
2014 uint64_t value
= get_pages_grabbed_count();
2015 return SYSCTL_OUT(req
, &value
, sizeof(value
));
2018 SYSCTL_PROC(_vm
, OID_AUTO
, pages_grabbed
, CTLTYPE_QUAD
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
2019 0, 0, &pages_grabbed
, "QU", "Total pages grabbed");
2020 SYSCTL_ULONG(_vm
, OID_AUTO
, pages_freed
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2021 &vm_pageout_vminfo
.vm_page_pages_freed
, "Total pages freed");
2023 SYSCTL_INT(_vm
, OID_AUTO
, pageout_purged_objects
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2024 &vm_pageout_debug
.vm_pageout_purged_objects
, 0, "System purged object count");
2025 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_busy
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2026 &vm_pageout_debug
.vm_pageout_cleaned_busy
, 0, "Cleaned pages busy (deactivated)");
2027 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_nolock
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2028 &vm_pageout_debug
.vm_pageout_cleaned_nolock
, 0, "Cleaned pages no-lock (deactivated)");
2030 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_volatile_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2031 &vm_pageout_debug
.vm_pageout_cleaned_volatile_reactivated
, 0, "Cleaned pages volatile reactivated");
2032 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_fault_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2033 &vm_pageout_debug
.vm_pageout_cleaned_fault_reactivated
, 0, "Cleaned pages fault reactivated");
2034 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2035 &vm_pageout_debug
.vm_pageout_cleaned_reactivated
, 0, "Cleaned pages reactivated"); /* sum of all reactivated AND busy and nolock (even though those actually get reDEactivated */
2036 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_cleaned
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2037 &vm_pageout_vminfo
.vm_pageout_freed_cleaned
, "Cleaned pages freed");
2038 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_reference_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2039 &vm_pageout_debug
.vm_pageout_cleaned_reference_reactivated
, 0, "Cleaned pages reference reactivated");
2040 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_enqueued_cleaned
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2041 &vm_pageout_debug
.vm_pageout_enqueued_cleaned
, 0, ""); /* sum of next two */
2044 extern int madvise_free_debug
;
2045 SYSCTL_INT(_vm
, OID_AUTO
, madvise_free_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
2046 &madvise_free_debug
, 0, "zero-fill on madvise(MADV_FREE*)");
2048 SYSCTL_INT(_vm
, OID_AUTO
, page_reusable_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2049 &vm_page_stats_reusable
.reusable_count
, 0, "Reusable page count");
2050 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2051 &vm_page_stats_reusable
.reusable_pages_success
, "");
2052 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2053 &vm_page_stats_reusable
.reusable_pages_failure
, "");
2054 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_pages_shared
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2055 &vm_page_stats_reusable
.reusable_pages_shared
, "");
2056 SYSCTL_QUAD(_vm
, OID_AUTO
, all_reusable_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2057 &vm_page_stats_reusable
.all_reusable_calls
, "");
2058 SYSCTL_QUAD(_vm
, OID_AUTO
, partial_reusable_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2059 &vm_page_stats_reusable
.partial_reusable_calls
, "");
2060 SYSCTL_QUAD(_vm
, OID_AUTO
, reuse_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2061 &vm_page_stats_reusable
.reuse_pages_success
, "");
2062 SYSCTL_QUAD(_vm
, OID_AUTO
, reuse_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2063 &vm_page_stats_reusable
.reuse_pages_failure
, "");
2064 SYSCTL_QUAD(_vm
, OID_AUTO
, all_reuse_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2065 &vm_page_stats_reusable
.all_reuse_calls
, "");
2066 SYSCTL_QUAD(_vm
, OID_AUTO
, partial_reuse_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2067 &vm_page_stats_reusable
.partial_reuse_calls
, "");
2068 SYSCTL_QUAD(_vm
, OID_AUTO
, can_reuse_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2069 &vm_page_stats_reusable
.can_reuse_success
, "");
2070 SYSCTL_QUAD(_vm
, OID_AUTO
, can_reuse_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2071 &vm_page_stats_reusable
.can_reuse_failure
, "");
2072 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_reclaimed
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2073 &vm_page_stats_reusable
.reusable_reclaimed
, "");
2074 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_nonwritable
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2075 &vm_page_stats_reusable
.reusable_nonwritable
, "");
2076 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_shared
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2077 &vm_page_stats_reusable
.reusable_shared
, "");
2078 SYSCTL_QUAD(_vm
, OID_AUTO
, free_shared
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2079 &vm_page_stats_reusable
.free_shared
, "");
2082 extern unsigned int vm_page_free_count
, vm_page_speculative_count
;
2083 SYSCTL_UINT(_vm
, OID_AUTO
, page_free_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_free_count
, 0, "");
2084 SYSCTL_UINT(_vm
, OID_AUTO
, page_speculative_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_speculative_count
, 0, "");
2086 extern unsigned int vm_page_cleaned_count
;
2087 SYSCTL_UINT(_vm
, OID_AUTO
, page_cleaned_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_cleaned_count
, 0, "Cleaned queue size");
2089 extern unsigned int vm_page_pageable_internal_count
, vm_page_pageable_external_count
;
2090 SYSCTL_UINT(_vm
, OID_AUTO
, page_pageable_internal_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_pageable_internal_count
, 0, "");
2091 SYSCTL_UINT(_vm
, OID_AUTO
, page_pageable_external_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_pageable_external_count
, 0, "");
2093 /* pageout counts */
2094 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_inactive_clean
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_state
.vm_pageout_inactive_clean
, 0, "");
2095 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_inactive_used
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_state
.vm_pageout_inactive_used
, 0, "");
2097 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_inactive_dirty_internal
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_vminfo
.vm_pageout_inactive_dirty_internal
, "");
2098 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_inactive_dirty_external
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_vminfo
.vm_pageout_inactive_dirty_external
, "");
2099 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_speculative_clean
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_vminfo
.vm_pageout_freed_speculative
, "");
2100 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_freed_external
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_vminfo
.vm_pageout_freed_external
, "");
2101 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_freed_speculative
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_vminfo
.vm_pageout_freed_speculative
, "");
2102 SYSCTL_ULONG(_vm
, OID_AUTO
, pageout_freed_cleaned
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_vminfo
.vm_pageout_freed_cleaned
, "");
2105 /* counts of pages prefaulted when entering a memory object */
2106 extern int64_t vm_prefault_nb_pages
, vm_prefault_nb_bailout
;
2107 SYSCTL_QUAD(_vm
, OID_AUTO
, prefault_nb_pages
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_prefault_nb_pages
, "");
2108 SYSCTL_QUAD(_vm
, OID_AUTO
, prefault_nb_bailout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_prefault_nb_bailout
, "");
2110 #if defined (__x86_64__)
2111 extern unsigned int vm_clump_promote_threshold
;
2112 SYSCTL_UINT(_vm
, OID_AUTO
, vm_clump_promote_threshold
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_clump_promote_threshold
, 0, "clump size threshold for promotes");
2113 #if DEVELOPMENT || DEBUG
2114 extern unsigned long vm_clump_stats
[];
2115 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats1
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[1], "free page allocations from clump of 1 page");
2116 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats2
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[2], "free page allocations from clump of 2 pages");
2117 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats3
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[3], "free page allocations from clump of 3 pages");
2118 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats4
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[4], "free page allocations from clump of 4 pages");
2119 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats5
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[5], "free page allocations from clump of 5 pages");
2120 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats6
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[6], "free page allocations from clump of 6 pages");
2121 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats7
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[7], "free page allocations from clump of 7 pages");
2122 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats8
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[8], "free page allocations from clump of 8 pages");
2123 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats9
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[9], "free page allocations from clump of 9 pages");
2124 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats10
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[10], "free page allocations from clump of 10 pages");
2125 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats11
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[11], "free page allocations from clump of 11 pages");
2126 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats12
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[12], "free page allocations from clump of 12 pages");
2127 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats13
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[13], "free page allocations from clump of 13 pages");
2128 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats14
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[14], "free page allocations from clump of 14 pages");
2129 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats15
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[15], "free page allocations from clump of 15 pages");
2130 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats16
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[16], "free page allocations from clump of 16 pages");
2131 extern unsigned long vm_clump_allocs
, vm_clump_inserts
, vm_clump_inrange
, vm_clump_promotes
;
2132 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_alloc
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_allocs
, "free page allocations");
2133 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_inserts
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_inserts
, "free page insertions");
2134 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_inrange
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_inrange
, "free page insertions that are part of vm_pages");
2135 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_promotes
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_promotes
, "pages promoted to head");
2136 #endif /* if DEVELOPMENT || DEBUG */
2137 #endif /* #if defined (__x86_64__) */
2139 #if CONFIG_SECLUDED_MEMORY
2141 SYSCTL_UINT(_vm
, OID_AUTO
, num_tasks_can_use_secluded_mem
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &num_tasks_can_use_secluded_mem
, 0, "");
2142 extern unsigned int vm_page_secluded_target
;
2143 extern unsigned int vm_page_secluded_count
;
2144 extern unsigned int vm_page_secluded_count_free
;
2145 extern unsigned int vm_page_secluded_count_inuse
;
2146 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_target
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_target
, 0, "");
2147 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_count
, 0, "");
2148 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_count_free
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_count_free
, 0, "");
2149 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_count_inuse
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_count_inuse
, 0, "");
2151 extern struct vm_page_secluded_data vm_page_secluded
;
2152 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_eligible
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.eligible_for_secluded
, 0, "");
2153 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_success_free
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_success_free
, 0, "");
2154 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_success_other
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_success_other
, 0, "");
2155 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_failure_locked
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_failure_locked
, 0, "");
2156 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_failure_state
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_failure_state
, 0, "");
2157 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_failure_dirty
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_failure_dirty
, 0, "");
2158 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_for_iokit
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_for_iokit
, 0, "");
2159 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_for_iokit_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_for_iokit_success
, 0, "");
2161 #endif /* CONFIG_SECLUDED_MEMORY */
2163 #include <kern/thread.h>
2164 #include <sys/user.h>
2166 void vm_pageout_io_throttle(void);
2168 void vm_pageout_io_throttle(void) {
2169 struct uthread
*uthread
= get_bsdthread_info(current_thread());
2172 * thread is marked as a low priority I/O type
2173 * and the I/O we issued while in this cleaning operation
2174 * collided with normal I/O operations... we'll
2175 * delay in order to mitigate the impact of this
2176 * task on the normal operation of the system
2179 if (uthread
->uu_lowpri_window
) {
2180 throttle_lowpri_io(1);
2186 vm_pressure_monitor(
2187 __unused
struct proc
*p
,
2188 struct vm_pressure_monitor_args
*uap
,
2192 uint32_t pages_reclaimed
;
2193 uint32_t pages_wanted
;
2195 kr
= mach_vm_pressure_monitor(
2196 (boolean_t
) uap
->wait_for_pressure
,
2197 uap
->nsecs_monitored
,
2198 (uap
->pages_reclaimed
) ? &pages_reclaimed
: NULL
,
2210 if (uap
->pages_reclaimed
) {
2211 if (copyout((void *)&pages_reclaimed
,
2212 uap
->pages_reclaimed
,
2213 sizeof (pages_reclaimed
)) != 0) {
2218 *retval
= (int) pages_wanted
;
2223 kas_info(struct proc
*p
,
2224 struct kas_info_args
*uap
,
2225 int *retval __unused
)
2227 #ifdef SECURE_KERNEL
2231 #else /* !SECURE_KERNEL */
2232 int selector
= uap
->selector
;
2233 user_addr_t valuep
= uap
->value
;
2234 user_addr_t sizep
= uap
->size
;
2238 if (!kauth_cred_issuser(kauth_cred_get())) {
2243 error
= mac_system_check_kas_info(kauth_cred_get(), selector
);
2249 if (IS_64BIT_PROCESS(p
)) {
2250 user64_size_t size64
;
2251 error
= copyin(sizep
, &size64
, sizeof(size64
));
2252 size
= (user_size_t
)size64
;
2254 user32_size_t size32
;
2255 error
= copyin(sizep
, &size32
, sizeof(size32
));
2256 size
= (user_size_t
)size32
;
2263 case KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR
:
2265 uint64_t slide
= vm_kernel_slide
;
2267 if (sizeof(slide
) != size
) {
2271 if (IS_64BIT_PROCESS(p
)) {
2272 user64_size_t size64
= (user64_size_t
)size
;
2273 error
= copyout(&size64
, sizep
, sizeof(size64
));
2275 user32_size_t size32
= (user32_size_t
)size
;
2276 error
= copyout(&size32
, sizep
, sizeof(size32
));
2282 error
= copyout(&slide
, valuep
, sizeof(slide
));
2293 #endif /* !SECURE_KERNEL */
2297 #pragma clang diagnostic push
2298 #pragma clang diagnostic ignored "-Wcast-qual"
2299 #pragma clang diagnostic ignored "-Wunused-function"
2301 static void asserts() {
2302 static_assert(sizeof(vm_min_kernel_address
) == sizeof(unsigned long));
2303 static_assert(sizeof(vm_max_kernel_address
) == sizeof(unsigned long));
2306 SYSCTL_ULONG(_vm
, OID_AUTO
, vm_min_kernel_address
, CTLFLAG_RD
, (unsigned long *) &vm_min_kernel_address
, "");
2307 SYSCTL_ULONG(_vm
, OID_AUTO
, vm_max_kernel_address
, CTLFLAG_RD
, (unsigned long *) &vm_max_kernel_address
, "");
2308 #pragma clang diagnostic pop
2310 extern uint32_t vm_page_pages
;
2311 SYSCTL_UINT(_vm
, OID_AUTO
, pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_pages
, 0, "");
2313 extern uint32_t vm_page_busy_absent_skipped
;
2314 SYSCTL_UINT(_vm
, OID_AUTO
, page_busy_absent_skipped
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_busy_absent_skipped
, 0, "");
2316 #if (__arm__ || __arm64__) && (DEVELOPMENT || DEBUG)
2317 extern int vm_footprint_suspend_allowed
;
2318 SYSCTL_INT(_vm
, OID_AUTO
, footprint_suspend_allowed
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_footprint_suspend_allowed
, 0, "");
2320 extern void pmap_footprint_suspend(vm_map_t map
, boolean_t suspend
);
2322 sysctl_vm_footprint_suspend SYSCTL_HANDLER_ARGS
2324 #pragma unused(oidp, arg1, arg2)
2328 if (req
->newptr
== USER_ADDR_NULL
) {
2331 error
= SYSCTL_IN(req
, &new_value
, sizeof(int));
2335 if (!vm_footprint_suspend_allowed
) {
2336 if (new_value
!= 0) {
2337 /* suspends are not allowed... */
2340 /* ... but let resumes proceed */
2342 DTRACE_VM2(footprint_suspend
,
2343 vm_map_t
, current_map(),
2346 pmap_footprint_suspend(current_map(), new_value
);
2350 SYSCTL_PROC(_vm
, OID_AUTO
, footprint_suspend
,
2351 CTLTYPE_INT
|CTLFLAG_WR
|CTLFLAG_ANYBODY
|CTLFLAG_LOCKED
|CTLFLAG_MASKED
,
2352 0, 0, &sysctl_vm_footprint_suspend
, "I", "");
2353 #endif /* (__arm__ || __arm64__) && (DEVELOPMENT || DEBUG) */
2355 extern uint64_t vm_map_corpse_footprint_count
;
2356 extern uint64_t vm_map_corpse_footprint_size_avg
;
2357 extern uint64_t vm_map_corpse_footprint_size_max
;
2358 extern uint64_t vm_map_corpse_footprint_full
;
2359 extern uint64_t vm_map_corpse_footprint_no_buf
;
2360 SYSCTL_QUAD(_vm
, OID_AUTO
, corpse_footprint_count
,
2361 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_map_corpse_footprint_count
, "");
2362 SYSCTL_QUAD(_vm
, OID_AUTO
, corpse_footprint_size_avg
,
2363 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_map_corpse_footprint_size_avg
, "");
2364 SYSCTL_QUAD(_vm
, OID_AUTO
, corpse_footprint_size_max
,
2365 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_map_corpse_footprint_size_max
, "");
2366 SYSCTL_QUAD(_vm
, OID_AUTO
, corpse_footprint_full
,
2367 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_map_corpse_footprint_full
, "");
2368 SYSCTL_QUAD(_vm
, OID_AUTO
, corpse_footprint_no_buf
,
2369 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_map_corpse_footprint_no_buf
, "");
2372 extern uint64_t vm_cs_defer_to_pmap_cs
;
2373 extern uint64_t vm_cs_defer_to_pmap_cs_not
;
2374 SYSCTL_QUAD(_vm
, OID_AUTO
, cs_defer_to_pmap_cs
,
2375 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_cs_defer_to_pmap_cs
, "");
2376 SYSCTL_QUAD(_vm
, OID_AUTO
, cs_defer_to_pmap_cs_not
,
2377 CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_cs_defer_to_pmap_cs_not
, "");
2378 #endif /* PMAP_CS */
2380 extern uint64_t shared_region_pager_copied
;
2381 extern uint64_t shared_region_pager_slid
;
2382 extern uint64_t shared_region_pager_slid_error
;
2383 extern uint64_t shared_region_pager_reclaimed
;
2384 SYSCTL_QUAD(_vm
, OID_AUTO
, shared_region_pager_copied
,
2385 CTLFLAG_RD
| CTLFLAG_LOCKED
, &shared_region_pager_copied
, "");
2386 SYSCTL_QUAD(_vm
, OID_AUTO
, shared_region_pager_slid
,
2387 CTLFLAG_RD
| CTLFLAG_LOCKED
, &shared_region_pager_slid
, "");
2388 SYSCTL_QUAD(_vm
, OID_AUTO
, shared_region_pager_slid_error
,
2389 CTLFLAG_RD
| CTLFLAG_LOCKED
, &shared_region_pager_slid_error
, "");
2390 SYSCTL_QUAD(_vm
, OID_AUTO
, shared_region_pager_reclaimed
,
2391 CTLFLAG_RD
| CTLFLAG_LOCKED
, &shared_region_pager_reclaimed
, "");
2394 extern int pmap_ledgers_panic_leeway
;
2395 SYSCTL_INT(_vm
, OID_AUTO
, pmap_ledgers_panic_leeway
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &pmap_ledgers_panic_leeway
, 0, "");
2396 #endif /* MACH_ASSERT */