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>
106 int _shared_region_map_and_slide(struct proc
*, int, unsigned int, struct shared_file_mapping_np
*, uint32_t, user_addr_t
, user_addr_t
);
107 int shared_region_copyin_mappings(struct proc
*, user_addr_t
, unsigned int, struct shared_file_mapping_np
*);
109 #if VM_MAP_DEBUG_APPLE_PROTECT
110 SYSCTL_INT(_vm
, OID_AUTO
, map_debug_apple_protect
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_map_debug_apple_protect
, 0, "");
111 #endif /* VM_MAP_DEBUG_APPLE_PROTECT */
113 #if VM_MAP_DEBUG_FOURK
114 SYSCTL_INT(_vm
, OID_AUTO
, map_debug_fourk
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_map_debug_fourk
, 0, "");
115 #endif /* VM_MAP_DEBUG_FOURK */
117 #if DEVELOPMENT || DEBUG
120 sysctl_kmem_alloc_contig SYSCTL_HANDLER_ARGS
122 #pragma unused(arg1, arg2)
128 error
= sysctl_handle_int(oidp
, &size
, 0, req
);
129 if (error
|| !req
->newptr
)
132 kr
= kmem_alloc_contig(kernel_map
, &kaddr
, (vm_size_t
)size
, 0, 0, 0, 0, VM_KERN_MEMORY_IOKIT
);
134 if (kr
== KERN_SUCCESS
)
135 kmem_free(kernel_map
, kaddr
, size
);
140 SYSCTL_PROC(_vm
, OID_AUTO
, kmem_alloc_contig
, CTLTYPE_INT
|CTLFLAG_WR
|CTLFLAG_LOCKED
|CTLFLAG_MASKED
,
141 0, 0, &sysctl_kmem_alloc_contig
, "I", "");
143 extern int vm_region_footprint
;
144 SYSCTL_INT(_vm
, OID_AUTO
, region_footprint
, CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
, &vm_region_footprint
, 0, "");
146 sysctl_vm_self_region_footprint SYSCTL_HANDLER_ARGS
148 #pragma unused(arg1, arg2, oidp)
152 value
= task_self_region_footprint();
153 error
= SYSCTL_OUT(req
, &value
, sizeof (int));
162 error
= SYSCTL_IN(req
, &value
, sizeof (int));
166 task_self_region_footprint_set(value
);
169 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", "");
171 #endif /* DEVELOPMENT || DEBUG */
176 #if DEVELOPMENT || DEBUG
177 extern int panic_on_unsigned_execute
;
178 SYSCTL_INT(_vm
, OID_AUTO
, panic_on_unsigned_execute
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &panic_on_unsigned_execute
, 0, "");
179 #endif /* DEVELOPMENT || DEBUG */
181 extern int log_executable_mem_entry
;
182 extern int cs_executable_create_upl
;
183 extern int cs_executable_mem_entry
;
184 extern int cs_executable_wire
;
185 SYSCTL_INT(_vm
, OID_AUTO
, log_executable_mem_entry
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &log_executable_mem_entry
, 0, "");
186 SYSCTL_INT(_vm
, OID_AUTO
, cs_executable_create_upl
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_executable_create_upl
, 0, "");
187 SYSCTL_INT(_vm
, OID_AUTO
, cs_executable_mem_entry
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_executable_mem_entry
, 0, "");
188 SYSCTL_INT(_vm
, OID_AUTO
, cs_executable_wire
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &cs_executable_wire
, 0, "");
189 #endif /* CONFIG_EMBEDDED */
191 #if DEVELOPMENT || DEBUG
192 extern int radar_20146450
;
193 SYSCTL_INT(_vm
, OID_AUTO
, radar_20146450
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &radar_20146450
, 0, "");
195 extern int macho_printf
;
196 SYSCTL_INT(_vm
, OID_AUTO
, macho_printf
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &macho_printf
, 0, "");
198 extern int apple_protect_pager_data_request_debug
;
199 SYSCTL_INT(_vm
, OID_AUTO
, apple_protect_pager_data_request_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &apple_protect_pager_data_request_debug
, 0, "");
201 #if __arm__ || __arm64__
202 /* These are meant to support the page table accounting unit test. */
203 extern unsigned int arm_hardware_page_size
;
204 extern unsigned int arm_pt_desc_size
;
205 extern unsigned int arm_pt_root_size
;
206 extern unsigned int free_page_size_tt_count
;
207 extern unsigned int free_two_page_size_tt_count
;
208 extern unsigned int free_tt_count
;
209 extern unsigned int inuse_user_tteroot_count
;
210 extern unsigned int inuse_kernel_tteroot_count
;
211 extern unsigned int inuse_user_ttepages_count
;
212 extern unsigned int inuse_kernel_ttepages_count
;
213 extern unsigned int inuse_user_ptepages_count
;
214 extern unsigned int inuse_kernel_ptepages_count
;
215 SYSCTL_UINT(_vm
, OID_AUTO
, native_hw_pagesize
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &arm_hardware_page_size
, 0, "");
216 SYSCTL_UINT(_vm
, OID_AUTO
, arm_pt_desc_size
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &arm_pt_desc_size
, 0, "");
217 SYSCTL_UINT(_vm
, OID_AUTO
, arm_pt_root_size
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &arm_pt_root_size
, 0, "");
218 SYSCTL_UINT(_vm
, OID_AUTO
, free_1page_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &free_page_size_tt_count
, 0, "");
219 SYSCTL_UINT(_vm
, OID_AUTO
, free_2page_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &free_two_page_size_tt_count
, 0, "");
220 SYSCTL_UINT(_vm
, OID_AUTO
, free_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &free_tt_count
, 0, "");
221 SYSCTL_UINT(_vm
, OID_AUTO
, user_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_user_tteroot_count
, 0, "");
222 SYSCTL_UINT(_vm
, OID_AUTO
, kernel_tte_root
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_kernel_tteroot_count
, 0, "");
223 SYSCTL_UINT(_vm
, OID_AUTO
, user_tte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_user_ttepages_count
, 0, "");
224 SYSCTL_UINT(_vm
, OID_AUTO
, kernel_tte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_kernel_ttepages_count
, 0, "");
225 SYSCTL_UINT(_vm
, OID_AUTO
, user_pte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_user_ptepages_count
, 0, "");
226 SYSCTL_UINT(_vm
, OID_AUTO
, kernel_pte_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &inuse_kernel_ptepages_count
, 0, "");
227 #endif /* __arm__ || __arm64__ */
230 extern int fourk_pager_data_request_debug
;
231 SYSCTL_INT(_vm
, OID_AUTO
, fourk_pager_data_request_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &fourk_pager_data_request_debug
, 0, "");
232 #endif /* __arm64__ */
233 #endif /* DEVELOPMENT || DEBUG */
235 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_compressor
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_compressor
, 0, "");
236 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_compressor_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_compressor_pages
, 0, "");
237 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_terminate
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_terminate
, 0, "");
238 SYSCTL_INT(_vm
, OID_AUTO
, vm_do_collapse_terminate_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.do_collapse_terminate_failure
, 0, "");
239 SYSCTL_INT(_vm
, OID_AUTO
, vm_should_cow_but_wired
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.should_cow_but_wired
, 0, "");
240 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_extra_cow
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_extra_cow
, 0, "");
241 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_extra_cow_pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_extra_cow_pages
, 0, "");
242 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_lookup_failure_write
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_lookup_failure_write
, 0, "");
243 SYSCTL_INT(_vm
, OID_AUTO
, vm_create_upl_lookup_failure_copy
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_counters
.create_upl_lookup_failure_copy
, 0, "");
244 #if VM_SCAN_FOR_SHADOW_CHAIN
245 static int vm_shadow_max_enabled
= 0; /* Disabled by default */
246 extern int proc_shadow_max(void);
248 vm_shadow_max SYSCTL_HANDLER_ARGS
250 #pragma unused(arg1, arg2, oidp)
253 if (vm_shadow_max_enabled
)
254 value
= proc_shadow_max();
256 return SYSCTL_OUT(req
, &value
, sizeof(value
));
258 SYSCTL_PROC(_vm
, OID_AUTO
, vm_shadow_max
, CTLTYPE_INT
|CTLFLAG_RD
|CTLFLAG_LOCKED
,
259 0, 0, &vm_shadow_max
, "I", "");
261 SYSCTL_INT(_vm
, OID_AUTO
, vm_shadow_max_enabled
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_shadow_max_enabled
, 0, "");
263 #endif /* VM_SCAN_FOR_SHADOW_CHAIN */
265 SYSCTL_INT(_vm
, OID_AUTO
, vm_debug_events
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_debug_events
, 0, "");
267 __attribute__((noinline
)) int __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(
268 mach_port_t task_access_port
, int32_t calling_pid
, uint32_t calling_gid
, int32_t target_pid
);
270 * Sysctl's related to data/stack execution. See osfmk/vm/vm_map.c
273 #if DEVELOPMENT || DEBUG
274 extern int allow_stack_exec
, allow_data_exec
;
276 SYSCTL_INT(_vm
, OID_AUTO
, allow_stack_exec
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &allow_stack_exec
, 0, "");
277 SYSCTL_INT(_vm
, OID_AUTO
, allow_data_exec
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &allow_data_exec
, 0, "");
280 extern int fourk_binary_compatibility_unsafe
;
281 extern int fourk_binary_compatibility_allow_wx
;
282 SYSCTL_INT(_vm
, OID_AUTO
, fourk_binary_compatibility_unsafe
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &fourk_binary_compatibility_unsafe
, 0, "");
283 SYSCTL_INT(_vm
, OID_AUTO
, fourk_binary_compatibility_allow_wx
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &fourk_binary_compatibility_allow_wx
, 0, "");
284 #endif /* __arm64__ */
285 #endif /* DEVELOPMENT || DEBUG */
287 static const char *prot_values
[] = {
299 log_stack_execution_failure(addr64_t vaddr
, vm_prot_t prot
)
301 printf("Data/Stack execution not permitted: %s[pid %d] at virtual address 0x%qx, protections were %s\n",
302 current_proc()->p_comm
, current_proc()->p_pid
, vaddr
, prot_values
[prot
& VM_PROT_ALL
]);
306 * shared_region_unnest_logging: level of logging of unnesting events
308 * 1 - throttled logging of unexpected unnesting events (default)
309 * 2 - unthrottled logging of unexpected unnesting events
310 * 3+ - unthrottled logging of all unnesting events
312 int shared_region_unnest_logging
= 1;
314 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_unnest_logging
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
315 &shared_region_unnest_logging
, 0, "");
317 int vm_shared_region_unnest_log_interval
= 10;
318 int shared_region_unnest_log_count_threshold
= 5;
321 * Shared cache path enforcement.
324 #ifndef CONFIG_EMBEDDED
325 static int scdir_enforce
= 1;
326 static char scdir_path
[] = "/var/db/dyld/";
328 static int scdir_enforce
= 0;
329 static char scdir_path
[] = "/System/Library/Caches/com.apple.dyld/";
332 #ifndef SECURE_KERNEL
333 SYSCTL_INT(_vm
, OID_AUTO
, enforce_shared_cache_dir
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &scdir_enforce
, 0, "");
336 /* These log rate throttling state variables aren't thread safe, but
337 * are sufficient unto the task.
339 static int64_t last_unnest_log_time
= 0;
340 static int shared_region_unnest_log_count
= 0;
347 boolean_t is_nested_map
,
348 vm_map_offset_t lowest_unnestable_addr
)
352 if (shared_region_unnest_logging
== 0)
355 if (shared_region_unnest_logging
<= 2 &&
357 s
>= lowest_unnestable_addr
) {
359 * Unnesting of writable map entries is fine.
364 if (shared_region_unnest_logging
<= 1) {
366 if ((tv
.tv_sec
- last_unnest_log_time
) <
367 vm_shared_region_unnest_log_interval
) {
368 if (shared_region_unnest_log_count
++ >
369 shared_region_unnest_log_count_threshold
)
372 last_unnest_log_time
= tv
.tv_sec
;
373 shared_region_unnest_log_count
= 0;
377 DTRACE_VM4(log_unnest_badness
,
381 vm_map_offset_t
, lowest_unnestable_addr
);
382 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
));
394 return (vm_map_check_protection(
396 vm_map_trunc_page(addr
,
397 vm_map_page_mask(map
)),
398 vm_map_round_page(addr
+len
,
399 vm_map_page_mask(map
)),
400 prot
== B_READ
? VM_PROT_READ
: VM_PROT_WRITE
));
412 kret
= vm_map_wire_kernel(map
,
413 vm_map_trunc_page(addr
,
414 vm_map_page_mask(map
)),
415 vm_map_round_page(addr
+len
,
416 vm_map_page_mask(map
)),
417 VM_PROT_READ
| VM_PROT_WRITE
, VM_KERN_MEMORY_BSD
,
423 case KERN_INVALID_ADDRESS
:
426 case KERN_PROTECTION_FAILURE
:
437 __unused
int dirtied
)
442 vm_map_offset_t vaddr
;
452 pmap
= get_task_pmap(current_task());
453 for (vaddr
= vm_map_trunc_page(addr
, PAGE_MASK
);
454 vaddr
< vm_map_round_page(addr
+len
, PAGE_MASK
);
455 vaddr
+= PAGE_SIZE
) {
456 paddr
= pmap_extract(pmap
, vaddr
);
457 pg
= PHYS_TO_VM_PAGE(paddr
);
458 vm_page_set_modified(pg
);
465 kret
= vm_map_unwire(map
,
466 vm_map_trunc_page(addr
,
467 vm_map_page_mask(map
)),
468 vm_map_round_page(addr
+len
,
469 vm_map_page_mask(map
)),
474 case KERN_INVALID_ADDRESS
:
477 case KERN_PROTECTION_FAILURE
:
491 character
= (char)byte
;
492 return (copyout((void *)&(character
), addr
, sizeof(char)) == 0 ? 0 : -1);
502 character
= (char)byte
;
503 return (copyout((void *)&(character
), addr
, sizeof(char)) == 0 ? 0 : -1);
506 int fubyte(user_addr_t addr
)
510 if (copyin(addr
, (void *) &byte
, sizeof(char)))
515 int fuibyte(user_addr_t addr
)
519 if (copyin(addr
, (void *) &(byte
), sizeof(char)))
529 return (copyout((void *) &word
, addr
, sizeof(int)) == 0 ? 0 : -1);
532 long fuword(user_addr_t addr
)
536 if (copyin(addr
, (void *) &word
, sizeof(int)))
541 /* suiword and fuiword are the same as suword and fuword, respectively */
548 return (copyout((void *) &word
, addr
, sizeof(int)) == 0 ? 0 : -1);
551 long fuiword(user_addr_t addr
)
555 if (copyin(addr
, (void *) &word
, sizeof(int)))
561 * With a 32-bit kernel and mixed 32/64-bit user tasks, this interface allows the
562 * fetching and setting of process-sized size_t and pointer values.
565 sulong(user_addr_t addr
, int64_t word
)
568 if (IS_64BIT_PROCESS(current_proc())) {
569 return(copyout((void *)&word
, addr
, sizeof(word
)) == 0 ? 0 : -1);
571 return(suiword(addr
, (long)word
));
576 fulong(user_addr_t addr
)
580 if (IS_64BIT_PROCESS(current_proc())) {
581 if (copyin(addr
, (void *)&longword
, sizeof(longword
)) != 0)
585 return((int64_t)fuiword(addr
));
590 suulong(user_addr_t addr
, uint64_t uword
)
593 if (IS_64BIT_PROCESS(current_proc())) {
594 return(copyout((void *)&uword
, addr
, sizeof(uword
)) == 0 ? 0 : -1);
596 return(suiword(addr
, (uint32_t)uword
));
601 fuulong(user_addr_t addr
)
605 if (IS_64BIT_PROCESS(current_proc())) {
606 if (copyin(addr
, (void *)&ulongword
, sizeof(ulongword
)) != 0)
610 return((uint64_t)fuiword(addr
));
615 swapon(__unused proc_t procp
, __unused
struct swapon_args
*uap
, __unused
int *retval
)
623 * Find the BSD process ID for the Mach task associated with the given Mach port
626 * Parameters: args User argument descriptor (see below)
628 * Indirect parameters: args->t Mach port name
629 * args->pid Process ID (returned value; see below)
631 * Returns: KERL_SUCCESS Success
632 * KERN_FAILURE Not success
634 * Implicit returns: args->pid Process ID
639 struct pid_for_task_args
*args
)
641 mach_port_name_t t
= args
->t
;
642 user_addr_t pid_addr
= args
->pid
;
646 kern_return_t err
= KERN_SUCCESS
;
648 AUDIT_MACH_SYSCALL_ENTER(AUE_PIDFORTASK
);
649 AUDIT_ARG(mach_port1
, t
);
651 t1
= port_name_to_task_inspect(t
);
653 if (t1
== TASK_NULL
) {
657 p
= get_bsdtask_info(t1
);
661 } else if (is_corpsetask(t1
)) {
671 (void) copyout((char *) &pid
, pid_addr
, sizeof(int));
672 AUDIT_MACH_SYSCALL_EXIT(err
);
678 * tfp_policy = KERN_TFP_POLICY_DENY; Deny Mode: None allowed except for self
679 * tfp_policy = KERN_TFP_POLICY_DEFAULT; default mode: all posix checks and upcall via task port for authentication
682 static int tfp_policy
= KERN_TFP_POLICY_DEFAULT
;
685 * Routine: task_for_pid_posix_check
687 * Verify that the current process should be allowed to
688 * get the target process's task port. This is only
690 * - The current process is root
691 * OR all of the following are true:
692 * - The target process's real, effective, and saved uids
693 * are the same as the current proc's euid,
694 * - The target process's group set is a subset of the
695 * calling process's group set, and
696 * - The target process hasn't switched credentials.
698 * Returns: TRUE: permitted
702 task_for_pid_posix_check(proc_t target
)
704 kauth_cred_t targetcred
, mycred
;
708 /* No task_for_pid on bad targets */
709 if (target
->p_stat
== SZOMB
) {
713 mycred
= kauth_cred_get();
714 myuid
= kauth_cred_getuid(mycred
);
716 /* If we're running as root, the check passes */
717 if (kauth_cred_issuser(mycred
))
720 /* We're allowed to get our own task port */
721 if (target
== current_proc())
725 * Under DENY, only root can get another proc's task port,
726 * so no more checks are needed.
728 if (tfp_policy
== KERN_TFP_POLICY_DENY
) {
732 targetcred
= kauth_cred_proc_ref(target
);
735 /* Do target's ruid, euid, and saved uid match my euid? */
736 if ((kauth_cred_getuid(targetcred
) != myuid
) ||
737 (kauth_cred_getruid(targetcred
) != myuid
) ||
738 (kauth_cred_getsvuid(targetcred
) != myuid
)) {
743 /* Are target's groups a subset of my groups? */
744 if (kauth_cred_gid_subset(targetcred
, mycred
, &allowed
) ||
750 /* Has target switched credentials? */
751 if (target
->p_flag
& P_SUGID
) {
757 kauth_cred_unref(&targetcred
);
762 * __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__
764 * Description: Waits for the user space daemon to respond to the request
765 * we made. Function declared non inline to be visible in
766 * stackshots and spindumps as well as debugging.
768 __attribute__((noinline
)) int __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(
769 mach_port_t task_access_port
, int32_t calling_pid
, uint32_t calling_gid
, int32_t target_pid
)
771 return check_task_access(task_access_port
, calling_pid
, calling_gid
, target_pid
);
775 * Routine: task_for_pid
777 * Get the task port for another "process", named by its
778 * process ID on the same host as "target_task".
780 * Only permitted to privileged processes, or processes
781 * with the same user ID.
783 * Note: if pid == 0, an error is return no matter who is calling.
785 * XXX This should be a BSD system call, not a Mach trap!!!
789 struct task_for_pid_args
*args
)
791 mach_port_name_t target_tport
= args
->target_tport
;
793 user_addr_t task_addr
= args
->t
;
794 proc_t p
= PROC_NULL
;
795 task_t t1
= TASK_NULL
;
796 task_t task
= TASK_NULL
;
797 mach_port_name_t tret
= MACH_PORT_NULL
;
798 ipc_port_t tfpport
= MACH_PORT_NULL
;
802 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID
);
804 AUDIT_ARG(mach_port1
, target_tport
);
806 /* Always check if pid == 0 */
808 (void ) copyout((char *)&t1
, task_addr
, sizeof(mach_port_name_t
));
809 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE
);
810 return(KERN_FAILURE
);
813 t1
= port_name_to_task(target_tport
);
814 if (t1
== TASK_NULL
) {
815 (void) copyout((char *)&t1
, task_addr
, sizeof(mach_port_name_t
));
816 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE
);
817 return(KERN_FAILURE
);
822 if (p
== PROC_NULL
) {
823 error
= KERN_FAILURE
;
828 AUDIT_ARG(process
, p
);
831 if (!(task_for_pid_posix_check(p
))) {
832 error
= KERN_FAILURE
;
836 if (p
->task
== TASK_NULL
) {
837 error
= KERN_SUCCESS
;
842 error
= mac_proc_check_get_task(kauth_cred_get(), p
);
844 error
= KERN_FAILURE
;
849 /* Grab a task reference since the proc ref might be dropped if an upcall to task access server is made */
851 task_reference(task
);
853 /* If we aren't root and target's task access port is set... */
854 if (!kauth_cred_issuser(kauth_cred_get()) &&
855 p
!= current_proc() &&
856 (task_get_task_access_port(task
, &tfpport
) == 0) &&
857 (tfpport
!= IPC_PORT_NULL
)) {
859 if (tfpport
== IPC_PORT_DEAD
) {
860 error
= KERN_PROTECTION_FAILURE
;
865 * Drop the proc_find proc ref before making an upcall
866 * to taskgated, since holding a proc_find
867 * ref while making an upcall can cause deadlock.
872 /* Call up to the task access server */
873 error
= __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport
, proc_selfpid(), kauth_getgid(), pid
);
875 if (error
!= MACH_MSG_SUCCESS
) {
876 if (error
== MACH_RCV_INTERRUPTED
)
877 error
= KERN_ABORTED
;
879 error
= KERN_FAILURE
;
884 /* Grant task port access */
885 extmod_statistics_incr_task_for_pid(task
);
886 sright
= (void *) convert_task_to_port(task
);
888 /* Check if the task has been corpsified */
889 if (is_corpsetask(task
)) {
890 /* task ref consumed by convert_task_to_port */
892 ipc_port_release_send(sright
);
893 error
= KERN_FAILURE
;
897 /* task ref consumed by convert_task_to_port */
899 tret
= ipc_port_copyout_send(
901 get_task_ipcspace(current_task()));
903 error
= KERN_SUCCESS
;
907 AUDIT_ARG(mach_port2
, tret
);
908 (void) copyout((char *) &tret
, task_addr
, sizeof(mach_port_name_t
));
910 if (tfpport
!= IPC_PORT_NULL
) {
911 ipc_port_release_send(tfpport
);
913 if (task
!= TASK_NULL
) {
914 task_deallocate(task
);
918 AUDIT_MACH_SYSCALL_EXIT(error
);
923 * Routine: task_name_for_pid
925 * Get the task name port for another "process", named by its
926 * process ID on the same host as "target_task".
928 * Only permitted to privileged processes, or processes
929 * with the same user ID.
931 * XXX This should be a BSD system call, not a Mach trap!!!
936 struct task_name_for_pid_args
*args
)
938 mach_port_name_t target_tport
= args
->target_tport
;
940 user_addr_t task_addr
= args
->t
;
941 proc_t p
= PROC_NULL
;
943 mach_port_name_t tret
;
945 int error
= 0, refheld
= 0;
946 kauth_cred_t target_cred
;
948 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKNAMEFORPID
);
950 AUDIT_ARG(mach_port1
, target_tport
);
952 t1
= port_name_to_task(target_tport
);
953 if (t1
== TASK_NULL
) {
954 (void) copyout((char *)&t1
, task_addr
, sizeof(mach_port_name_t
));
955 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE
);
956 return(KERN_FAILURE
);
960 if (p
!= PROC_NULL
) {
961 AUDIT_ARG(process
, p
);
962 target_cred
= kauth_cred_proc_ref(p
);
965 if ((p
->p_stat
!= SZOMB
)
966 && ((current_proc() == p
)
967 || kauth_cred_issuser(kauth_cred_get())
968 || ((kauth_cred_getuid(target_cred
) == kauth_cred_getuid(kauth_cred_get())) &&
969 ((kauth_cred_getruid(target_cred
) == kauth_getruid()))))) {
971 if (p
->task
!= TASK_NULL
) {
972 task_reference(p
->task
);
974 error
= mac_proc_check_get_task_name(kauth_cred_get(), p
);
976 task_deallocate(p
->task
);
980 sright
= (void *)convert_task_name_to_port(p
->task
);
981 tret
= ipc_port_copyout_send(sright
,
982 get_task_ipcspace(current_task()));
984 tret
= MACH_PORT_NULL
;
986 AUDIT_ARG(mach_port2
, tret
);
987 (void) copyout((char *)&tret
, task_addr
, sizeof(mach_port_name_t
));
989 error
= KERN_SUCCESS
;
998 tret
= MACH_PORT_NULL
;
999 (void) copyout((char *) &tret
, task_addr
, sizeof(mach_port_name_t
));
1000 error
= KERN_FAILURE
;
1003 kauth_cred_unref(&target_cred
);
1006 AUDIT_MACH_SYSCALL_EXIT(error
);
1011 pid_suspend(struct proc
*p __unused
, struct pid_suspend_args
*args
, int *ret
)
1013 task_t target
= NULL
;
1014 proc_t targetproc
= PROC_NULL
;
1015 int pid
= args
->pid
;
1019 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_SUSPEND
);
1031 targetproc
= proc_find(pid
);
1032 if (targetproc
== PROC_NULL
) {
1037 if (!task_for_pid_posix_check(targetproc
)) {
1042 target
= targetproc
->task
;
1043 #ifndef CONFIG_EMBEDDED
1044 if (target
!= TASK_NULL
) {
1045 mach_port_t tfpport
;
1047 /* If we aren't root and target's task access port is set... */
1048 if (!kauth_cred_issuser(kauth_cred_get()) &&
1049 targetproc
!= current_proc() &&
1050 (task_get_task_access_port(target
, &tfpport
) == 0) &&
1051 (tfpport
!= IPC_PORT_NULL
)) {
1053 if (tfpport
== IPC_PORT_DEAD
) {
1058 /* Call up to the task access server */
1059 error
= __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport
, proc_selfpid(), kauth_getgid(), pid
);
1061 if (error
!= MACH_MSG_SUCCESS
) {
1062 if (error
== MACH_RCV_INTERRUPTED
)
1072 task_reference(target
);
1073 error
= task_pidsuspend(target
);
1075 if (error
== KERN_INVALID_ARGUMENT
) {
1081 #if CONFIG_MEMORYSTATUS
1083 memorystatus_on_suspend(targetproc
);
1087 task_deallocate(target
);
1090 if (targetproc
!= PROC_NULL
)
1091 proc_rele(targetproc
);
1097 pid_resume(struct proc
*p __unused
, struct pid_resume_args
*args
, int *ret
)
1099 task_t target
= NULL
;
1100 proc_t targetproc
= PROC_NULL
;
1101 int pid
= args
->pid
;
1105 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_RESUME
);
1117 targetproc
= proc_find(pid
);
1118 if (targetproc
== PROC_NULL
) {
1123 if (!task_for_pid_posix_check(targetproc
)) {
1128 target
= targetproc
->task
;
1129 #ifndef CONFIG_EMBEDDED
1130 if (target
!= TASK_NULL
) {
1131 mach_port_t tfpport
;
1133 /* If we aren't root and target's task access port is set... */
1134 if (!kauth_cred_issuser(kauth_cred_get()) &&
1135 targetproc
!= current_proc() &&
1136 (task_get_task_access_port(target
, &tfpport
) == 0) &&
1137 (tfpport
!= IPC_PORT_NULL
)) {
1139 if (tfpport
== IPC_PORT_DEAD
) {
1144 /* Call up to the task access server */
1145 error
= __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport
, proc_selfpid(), kauth_getgid(), pid
);
1147 if (error
!= MACH_MSG_SUCCESS
) {
1148 if (error
== MACH_RCV_INTERRUPTED
)
1160 resume_proc_sockets(targetproc
);
1161 #endif /* SOCKETS */
1162 #endif /* CONFIG_EMBEDDED */
1164 task_reference(target
);
1166 #if CONFIG_MEMORYSTATUS
1167 memorystatus_on_resume(targetproc
);
1170 error
= task_pidresume(target
);
1172 if (error
== KERN_INVALID_ARGUMENT
) {
1175 if (error
== KERN_MEMORY_ERROR
) {
1176 psignal(targetproc
, SIGKILL
);
1183 task_deallocate(target
);
1186 if (targetproc
!= PROC_NULL
)
1187 proc_rele(targetproc
);
1195 * Freeze the specified process (provided in args->pid), or find and freeze a PID.
1196 * When a process is specified, this call is blocking, otherwise we wake up the
1197 * freezer thread and do not block on a process being frozen.
1200 pid_hibernate(struct proc
*p __unused
, struct pid_hibernate_args
*args
, int *ret
)
1203 proc_t targetproc
= PROC_NULL
;
1204 int pid
= args
->pid
;
1206 #ifndef CONFIG_FREEZE
1211 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_HIBERNATE
);
1219 * If a pid has been provided, we obtain the process handle and call task_for_pid_posix_check().
1223 targetproc
= proc_find(pid
);
1225 if (targetproc
== PROC_NULL
) {
1230 if (!task_for_pid_posix_check(targetproc
)) {
1237 vm_pageout_anonymous_pages();
1238 } else if (pid
== -1) {
1239 memorystatus_on_inactivity(targetproc
);
1241 error
= memorystatus_freeze_process_sync(targetproc
);
1246 #endif /* CONFIG_FREEZE */
1248 if (targetproc
!= PROC_NULL
)
1249 proc_rele(targetproc
);
1253 #endif /* CONFIG_EMBEDDED */
1257 networking_memstatus_callout(proc_t p
, uint32_t status
)
1259 struct filedesc
*fdp
;
1263 * proc list lock NOT held
1264 * proc lock NOT held
1265 * a reference on the proc has been held / shall be dropped by the caller.
1267 LCK_MTX_ASSERT(proc_list_mlock
, LCK_MTX_ASSERT_NOTOWNED
);
1268 LCK_MTX_ASSERT(&p
->p_mlock
, LCK_MTX_ASSERT_NOTOWNED
);
1272 for (i
= 0; i
< fdp
->fd_nfiles
; i
++) {
1273 struct fileproc
*fp
;
1275 fp
= fdp
->fd_ofiles
[i
];
1276 if (fp
== NULL
|| (fdp
->fd_ofileflags
[i
] & UF_RESERVED
) != 0) {
1279 switch (FILEGLOB_DTYPE(fp
->f_fglob
)) {
1281 case DTYPE_NETPOLICY
:
1282 necp_fd_memstatus(p
, status
,
1283 (struct necp_fd_data
*)fp
->f_fglob
->fg_data
);
1297 networking_defunct_callout(proc_t p
, void *arg
)
1299 struct pid_shutdown_sockets_args
*args
= arg
;
1300 int pid
= args
->pid
;
1301 int level
= args
->level
;
1302 struct filedesc
*fdp
;
1307 for (i
= 0; i
< fdp
->fd_nfiles
; i
++) {
1308 struct fileproc
*fp
= fdp
->fd_ofiles
[i
];
1309 struct fileglob
*fg
;
1311 if (fp
== NULL
|| (fdp
->fd_ofileflags
[i
] & UF_RESERVED
) != 0) {
1316 switch (FILEGLOB_DTYPE(fg
)) {
1317 case DTYPE_SOCKET
: {
1318 struct socket
*so
= (struct socket
*)fg
->fg_data
;
1319 if (p
->p_pid
== pid
|| so
->last_pid
== pid
||
1320 ((so
->so_flags
& SOF_DELEGATED
) && so
->e_pid
== pid
)) {
1321 /* Call networking stack with socket and level */
1322 (void) socket_defunct(p
, so
, level
);
1327 case DTYPE_NETPOLICY
:
1328 /* first pass: defunct necp and get stats for ntstat */
1329 if (p
->p_pid
== pid
) {
1331 (struct necp_fd_data
*)fg
->fg_data
);
1342 return (PROC_RETURNED
);
1346 pid_shutdown_sockets(struct proc
*p __unused
, struct pid_shutdown_sockets_args
*args
, int *ret
)
1349 proc_t targetproc
= PROC_NULL
;
1350 int pid
= args
->pid
;
1351 int level
= args
->level
;
1353 if (level
!= SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC
&&
1354 level
!= SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL
) {
1360 error
= mac_proc_check_suspend_resume(p
, MAC_PROC_CHECK_SHUTDOWN_SOCKETS
);
1367 targetproc
= proc_find(pid
);
1368 if (targetproc
== PROC_NULL
) {
1373 if (!task_for_pid_posix_check(targetproc
)) {
1378 proc_iterate(PROC_ALLPROCLIST
| PROC_NOWAITTRANS
,
1379 networking_defunct_callout
, args
, NULL
, NULL
);
1382 if (targetproc
!= PROC_NULL
)
1383 proc_rele(targetproc
);
1388 #endif /* SOCKETS */
1391 sysctl_settfp_policy(__unused
struct sysctl_oid
*oidp
, void *arg1
,
1392 __unused
int arg2
, struct sysctl_req
*req
)
1397 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
1398 if (error
|| req
->newptr
== USER_ADDR_NULL
)
1401 if (!kauth_cred_issuser(kauth_cred_get()))
1404 if ((error
= SYSCTL_IN(req
, &new_value
, sizeof(int)))) {
1407 if ((new_value
== KERN_TFP_POLICY_DENY
)
1408 || (new_value
== KERN_TFP_POLICY_DEFAULT
))
1409 tfp_policy
= new_value
;
1417 #if defined(SECURE_KERNEL)
1418 static int kern_secure_kernel
= 1;
1420 static int kern_secure_kernel
= 0;
1423 SYSCTL_INT(_kern
, OID_AUTO
, secure_kernel
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &kern_secure_kernel
, 0, "");
1425 SYSCTL_NODE(_kern
, KERN_TFP
, tfp
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "tfp");
1426 SYSCTL_PROC(_kern_tfp
, KERN_TFP_POLICY
, policy
, CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
1427 &tfp_policy
, sizeof(uint32_t), &sysctl_settfp_policy
,"I","policy");
1429 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_trace_level
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
1430 &shared_region_trace_level
, 0, "");
1431 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_version
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1432 &shared_region_version
, 0, "");
1433 SYSCTL_INT(_vm
, OID_AUTO
, shared_region_persistence
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
1434 &shared_region_persistence
, 0, "");
1437 * shared_region_check_np:
1439 * This system call is intended for dyld.
1441 * dyld calls this when any process starts to see if the process's shared
1442 * region is already set up and ready to use.
1443 * This call returns the base address of the first mapping in the
1444 * process's shared region's first mapping.
1445 * dyld will then check what's mapped at that address.
1447 * If the shared region is empty, dyld will then attempt to map the shared
1448 * cache file in the shared region via the shared_region_map_np() system call.
1450 * If something's already mapped in the shared region, dyld will check if it
1451 * matches the shared cache it would like to use for that process.
1452 * If it matches, evrything's ready and the process can proceed and use the
1454 * If it doesn't match, dyld will unmap the shared region and map the shared
1455 * cache into the process's address space via mmap().
1458 * EINVAL no shared region
1459 * ENOMEM shared region is empty
1460 * EFAULT bad address for "start_address"
1463 shared_region_check_np(
1464 __unused
struct proc
*p
,
1465 struct shared_region_check_np_args
*uap
,
1466 __unused
int *retvalp
)
1468 vm_shared_region_t shared_region
;
1469 mach_vm_offset_t start_address
= 0;
1473 SHARED_REGION_TRACE_DEBUG(
1474 ("shared_region: %p [%d(%s)] -> check_np(0x%llx)\n",
1475 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1476 p
->p_pid
, p
->p_comm
,
1477 (uint64_t)uap
->start_address
));
1479 /* retrieve the current tasks's shared region */
1480 shared_region
= vm_shared_region_get(current_task());
1481 if (shared_region
!= NULL
) {
1482 /* retrieve address of its first mapping... */
1483 kr
= vm_shared_region_start_address(shared_region
,
1485 if (kr
!= KERN_SUCCESS
) {
1488 /* ... and give it to the caller */
1489 error
= copyout(&start_address
,
1490 (user_addr_t
) uap
->start_address
,
1491 sizeof (start_address
));
1493 SHARED_REGION_TRACE_ERROR(
1494 ("shared_region: %p [%d(%s)] "
1496 "copyout(0x%llx) error %d\n",
1497 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1498 p
->p_pid
, p
->p_comm
,
1499 (uint64_t)uap
->start_address
, (uint64_t)start_address
,
1503 vm_shared_region_deallocate(shared_region
);
1505 /* no shared region ! */
1509 SHARED_REGION_TRACE_DEBUG(
1510 ("shared_region: %p [%d(%s)] check_np(0x%llx) <- 0x%llx %d\n",
1511 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1512 p
->p_pid
, p
->p_comm
,
1513 (uint64_t)uap
->start_address
, (uint64_t)start_address
, error
));
1520 shared_region_copyin_mappings(
1522 user_addr_t user_mappings
,
1523 unsigned int mappings_count
,
1524 struct shared_file_mapping_np
*mappings
)
1527 vm_size_t mappings_size
= 0;
1529 /* get the list of mappings the caller wants us to establish */
1530 mappings_size
= (vm_size_t
) (mappings_count
* sizeof (mappings
[0]));
1531 error
= copyin(user_mappings
,
1535 SHARED_REGION_TRACE_ERROR(
1536 ("shared_region: %p [%d(%s)] map(): "
1537 "copyin(0x%llx, %d) failed (error=%d)\n",
1538 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1539 p
->p_pid
, p
->p_comm
,
1540 (uint64_t)user_mappings
, mappings_count
, error
));
1545 * shared_region_map_np()
1547 * This system call is intended for dyld.
1549 * dyld uses this to map a shared cache file into a shared region.
1550 * This is usually done only the first time a shared cache is needed.
1551 * Subsequent processes will just use the populated shared region without
1552 * requiring any further setup.
1555 _shared_region_map_and_slide(
1558 uint32_t mappings_count
,
1559 struct shared_file_mapping_np
*mappings
,
1561 user_addr_t slide_start
,
1562 user_addr_t slide_size
)
1566 struct fileproc
*fp
;
1567 struct vnode
*vp
, *root_vp
, *scdir_vp
;
1568 struct vnode_attr va
;
1570 memory_object_size_t file_size
;
1572 vm_prot_t maxprot
= VM_PROT_ALL
;
1574 memory_object_control_t file_control
;
1575 struct vm_shared_region
*shared_region
;
1578 SHARED_REGION_TRACE_DEBUG(
1579 ("shared_region: %p [%d(%s)] -> map\n",
1580 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1581 p
->p_pid
, p
->p_comm
));
1583 shared_region
= NULL
;
1588 /* get file structure from file descriptor */
1589 error
= fp_lookup(p
, fd
, &fp
, 0);
1591 SHARED_REGION_TRACE_ERROR(
1592 ("shared_region: %p [%d(%s)] map: "
1593 "fd=%d lookup failed (error=%d)\n",
1594 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1595 p
->p_pid
, p
->p_comm
, fd
, error
));
1599 /* make sure we're attempting to map a vnode */
1600 if (FILEGLOB_DTYPE(fp
->f_fglob
) != DTYPE_VNODE
) {
1601 SHARED_REGION_TRACE_ERROR(
1602 ("shared_region: %p [%d(%s)] map: "
1603 "fd=%d not a vnode (type=%d)\n",
1604 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1605 p
->p_pid
, p
->p_comm
,
1606 fd
, FILEGLOB_DTYPE(fp
->f_fglob
)));
1611 /* we need at least read permission on the file */
1612 if (! (fp
->f_fglob
->fg_flag
& FREAD
)) {
1613 SHARED_REGION_TRACE_ERROR(
1614 ("shared_region: %p [%d(%s)] map: "
1615 "fd=%d not readable\n",
1616 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1617 p
->p_pid
, p
->p_comm
, fd
));
1622 /* get vnode from file structure */
1623 error
= vnode_getwithref((vnode_t
) fp
->f_fglob
->fg_data
);
1625 SHARED_REGION_TRACE_ERROR(
1626 ("shared_region: %p [%d(%s)] map: "
1627 "fd=%d getwithref failed (error=%d)\n",
1628 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1629 p
->p_pid
, p
->p_comm
, fd
, error
));
1632 vp
= (struct vnode
*) fp
->f_fglob
->fg_data
;
1634 /* make sure the vnode is a regular file */
1635 if (vp
->v_type
!= VREG
) {
1636 SHARED_REGION_TRACE_ERROR(
1637 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1638 "not a file (type=%d)\n",
1639 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1640 p
->p_pid
, p
->p_comm
,
1641 (void *)VM_KERNEL_ADDRPERM(vp
),
1642 vp
->v_name
, vp
->v_type
));
1648 /* pass in 0 for the offset argument because AMFI does not need the offset
1649 of the shared cache */
1650 error
= mac_file_check_mmap(vfs_context_ucred(vfs_context_current()),
1651 fp
->f_fglob
, VM_PROT_ALL
, MAP_FILE
, 0, &maxprot
);
1657 /* make sure vnode is on the process's root volume */
1658 root_vp
= p
->p_fd
->fd_rdir
;
1659 if (root_vp
== NULL
) {
1660 root_vp
= rootvnode
;
1663 * Chroot-ed processes can't use the shared_region.
1669 if (vp
->v_mount
!= root_vp
->v_mount
) {
1670 SHARED_REGION_TRACE_ERROR(
1671 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1672 "not on process's root volume\n",
1673 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1674 p
->p_pid
, p
->p_comm
,
1675 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
));
1680 /* make sure vnode is owned by "root" */
1682 VATTR_WANTED(&va
, va_uid
);
1683 error
= vnode_getattr(vp
, &va
, vfs_context_current());
1685 SHARED_REGION_TRACE_ERROR(
1686 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1687 "vnode_getattr(%p) failed (error=%d)\n",
1688 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1689 p
->p_pid
, p
->p_comm
,
1690 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1691 (void *)VM_KERNEL_ADDRPERM(vp
), error
));
1694 if (va
.va_uid
!= 0) {
1695 SHARED_REGION_TRACE_ERROR(
1696 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1697 "owned by uid=%d instead of 0\n",
1698 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1699 p
->p_pid
, p
->p_comm
,
1700 (void *)VM_KERNEL_ADDRPERM(vp
),
1701 vp
->v_name
, va
.va_uid
));
1706 if (scdir_enforce
) {
1707 /* get vnode for scdir_path */
1708 error
= vnode_lookup(scdir_path
, 0, &scdir_vp
, vfs_context_current());
1710 SHARED_REGION_TRACE_ERROR(
1711 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1712 "vnode_lookup(%s) failed (error=%d)\n",
1713 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1714 p
->p_pid
, p
->p_comm
,
1715 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1716 scdir_path
, error
));
1720 /* ensure parent is scdir_vp */
1721 if (vnode_parent(vp
) != scdir_vp
) {
1722 SHARED_REGION_TRACE_ERROR(
1723 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1724 "shared cache file not in %s\n",
1725 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1726 p
->p_pid
, p
->p_comm
,
1727 (void *)VM_KERNEL_ADDRPERM(vp
),
1728 vp
->v_name
, scdir_path
));
1734 /* get vnode size */
1735 error
= vnode_size(vp
, &fs
, vfs_context_current());
1737 SHARED_REGION_TRACE_ERROR(
1738 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1739 "vnode_size(%p) failed (error=%d)\n",
1740 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1741 p
->p_pid
, p
->p_comm
,
1742 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1743 (void *)VM_KERNEL_ADDRPERM(vp
), error
));
1748 /* get the file's memory object handle */
1749 file_control
= ubc_getobject(vp
, UBC_HOLDOBJECT
);
1750 if (file_control
== MEMORY_OBJECT_CONTROL_NULL
) {
1751 SHARED_REGION_TRACE_ERROR(
1752 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1753 "no memory object\n",
1754 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1755 p
->p_pid
, p
->p_comm
,
1756 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
));
1761 /* check that the mappings are properly covered by code signatures */
1762 if (!cs_enforcement(NULL
)) {
1763 /* code signing is not enforced: no need to check */
1764 } else for (i
= 0; i
< mappings_count
; i
++) {
1765 if (mappings
[i
].sfm_init_prot
& VM_PROT_ZF
) {
1766 /* zero-filled mapping: not backed by the file */
1769 if (ubc_cs_is_range_codesigned(vp
,
1770 mappings
[i
].sfm_file_offset
,
1771 mappings
[i
].sfm_size
)) {
1772 /* this mapping is fully covered by code signatures */
1775 SHARED_REGION_TRACE_ERROR(
1776 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1777 "mapping #%d/%d [0x%llx:0x%llx:0x%llx:0x%x:0x%x] "
1778 "is not code-signed\n",
1779 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1780 p
->p_pid
, p
->p_comm
,
1781 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
,
1783 mappings
[i
].sfm_address
,
1784 mappings
[i
].sfm_size
,
1785 mappings
[i
].sfm_file_offset
,
1786 mappings
[i
].sfm_max_prot
,
1787 mappings
[i
].sfm_init_prot
));
1792 /* get the process's shared region (setup in vm_map_exec()) */
1793 shared_region
= vm_shared_region_get(current_task());
1794 if (shared_region
== NULL
) {
1795 SHARED_REGION_TRACE_ERROR(
1796 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1797 "no shared region\n",
1798 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1799 p
->p_pid
, p
->p_comm
,
1800 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
));
1804 /* map the file into that shared region's submap */
1805 kr
= vm_shared_region_map_file(shared_region
,
1810 (void *) p
->p_fd
->fd_rdir
,
1814 if (kr
!= KERN_SUCCESS
) {
1815 SHARED_REGION_TRACE_ERROR(
1816 ("shared_region: %p [%d(%s)] map(%p:'%s'): "
1817 "vm_shared_region_map_file() failed kr=0x%x\n",
1818 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1819 p
->p_pid
, p
->p_comm
,
1820 (void *)VM_KERNEL_ADDRPERM(vp
), vp
->v_name
, kr
));
1822 case KERN_INVALID_ADDRESS
:
1825 case KERN_PROTECTION_FAILURE
:
1832 case KERN_INVALID_ARGUMENT
:
1842 vnode_lock_spin(vp
);
1844 vp
->v_flag
|= VSHARED_DYLD
;
1848 /* update the vnode's access time */
1849 if (! (vnode_vfsvisflags(vp
) & MNT_NOATIME
)) {
1851 nanotime(&va
.va_access_time
);
1852 VATTR_SET_ACTIVE(&va
, va_access_time
);
1853 vnode_setattr(vp
, &va
, vfs_context_current());
1856 if (p
->p_flag
& P_NOSHLIB
) {
1857 /* signal that this process is now using split libraries */
1858 OSBitAndAtomic(~((uint32_t)P_NOSHLIB
), &p
->p_flag
);
1864 * release the vnode...
1865 * ubc_map() still holds it for us in the non-error case
1867 (void) vnode_put(vp
);
1871 /* release the file descriptor */
1872 fp_drop(p
, fd
, fp
, 0);
1875 if (scdir_vp
!= NULL
) {
1876 (void)vnode_put(scdir_vp
);
1880 if (shared_region
!= NULL
) {
1881 vm_shared_region_deallocate(shared_region
);
1884 SHARED_REGION_TRACE_DEBUG(
1885 ("shared_region: %p [%d(%s)] <- map\n",
1886 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1887 p
->p_pid
, p
->p_comm
));
1893 shared_region_map_and_slide_np(
1895 struct shared_region_map_and_slide_np_args
*uap
,
1896 __unused
int *retvalp
)
1898 struct shared_file_mapping_np
*mappings
;
1899 unsigned int mappings_count
= uap
->count
;
1900 kern_return_t kr
= KERN_SUCCESS
;
1901 uint32_t slide
= uap
->slide
;
1903 #define SFM_MAX_STACK 8
1904 struct shared_file_mapping_np stack_mappings
[SFM_MAX_STACK
];
1906 /* Is the process chrooted?? */
1907 if (p
->p_fd
->fd_rdir
!= NULL
) {
1912 if ((kr
= vm_shared_region_sliding_valid(slide
)) != KERN_SUCCESS
) {
1913 if (kr
== KERN_INVALID_ARGUMENT
) {
1915 * This will happen if we request sliding again
1916 * with the same slide value that was used earlier
1917 * for the very first sliding.
1924 if (mappings_count
== 0) {
1925 SHARED_REGION_TRACE_INFO(
1926 ("shared_region: %p [%d(%s)] map(): "
1928 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1929 p
->p_pid
, p
->p_comm
));
1930 kr
= 0; /* no mappings: we're done ! */
1932 } else if (mappings_count
<= SFM_MAX_STACK
) {
1933 mappings
= &stack_mappings
[0];
1935 SHARED_REGION_TRACE_ERROR(
1936 ("shared_region: %p [%d(%s)] map(): "
1937 "too many mappings (%d)\n",
1938 (void *)VM_KERNEL_ADDRPERM(current_thread()),
1939 p
->p_pid
, p
->p_comm
,
1945 if ( (kr
= shared_region_copyin_mappings(p
, uap
->mappings
, uap
->count
, mappings
))) {
1950 kr
= _shared_region_map_and_slide(p
, uap
->fd
, mappings_count
, mappings
,
1952 uap
->slide_start
, uap
->slide_size
);
1953 if (kr
!= KERN_SUCCESS
) {
1961 /* sysctl overflow room */
1963 SYSCTL_INT (_vm
, OID_AUTO
, pagesize
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1964 (int *) &page_size
, 0, "vm page size");
1966 /* vm_page_free_target is provided as a makeshift solution for applications that want to
1967 allocate buffer space, possibly purgeable memory, but not cause inactive pages to be
1968 reclaimed. It allows the app to calculate how much memory is free outside the free target. */
1969 extern unsigned int vm_page_free_target
;
1970 SYSCTL_INT(_vm
, OID_AUTO
, vm_page_free_target
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1971 &vm_page_free_target
, 0, "Pageout daemon free target");
1973 extern unsigned int vm_memory_pressure
;
1974 SYSCTL_INT(_vm
, OID_AUTO
, memory_pressure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1975 &vm_memory_pressure
, 0, "Memory pressure indicator");
1978 vm_ctl_page_free_wanted SYSCTL_HANDLER_ARGS
1980 #pragma unused(oidp, arg1, arg2)
1981 unsigned int page_free_wanted
;
1983 page_free_wanted
= mach_vm_ctl_page_free_wanted();
1984 return SYSCTL_OUT(req
, &page_free_wanted
, sizeof (page_free_wanted
));
1986 SYSCTL_PROC(_vm
, OID_AUTO
, page_free_wanted
,
1987 CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
1988 0, 0, vm_ctl_page_free_wanted
, "I", "");
1990 extern unsigned int vm_page_purgeable_count
;
1991 SYSCTL_INT(_vm
, OID_AUTO
, page_purgeable_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1992 &vm_page_purgeable_count
, 0, "Purgeable page count");
1994 extern unsigned int vm_page_purgeable_wired_count
;
1995 SYSCTL_INT(_vm
, OID_AUTO
, page_purgeable_wired_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
1996 &vm_page_purgeable_wired_count
, 0, "Wired purgeable page count");
1998 extern unsigned int vm_pageout_purged_objects
;
1999 SYSCTL_INT(_vm
, OID_AUTO
, pageout_purged_objects
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2000 &vm_pageout_purged_objects
, 0, "System purged object count");
2002 extern int madvise_free_debug
;
2003 SYSCTL_INT(_vm
, OID_AUTO
, madvise_free_debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
2004 &madvise_free_debug
, 0, "zero-fill on madvise(MADV_FREE*)");
2006 SYSCTL_INT(_vm
, OID_AUTO
, page_reusable_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2007 &vm_page_stats_reusable
.reusable_count
, 0, "Reusable page count");
2008 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2009 &vm_page_stats_reusable
.reusable_pages_success
, "");
2010 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2011 &vm_page_stats_reusable
.reusable_pages_failure
, "");
2012 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_pages_shared
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2013 &vm_page_stats_reusable
.reusable_pages_shared
, "");
2014 SYSCTL_QUAD(_vm
, OID_AUTO
, all_reusable_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2015 &vm_page_stats_reusable
.all_reusable_calls
, "");
2016 SYSCTL_QUAD(_vm
, OID_AUTO
, partial_reusable_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2017 &vm_page_stats_reusable
.partial_reusable_calls
, "");
2018 SYSCTL_QUAD(_vm
, OID_AUTO
, reuse_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2019 &vm_page_stats_reusable
.reuse_pages_success
, "");
2020 SYSCTL_QUAD(_vm
, OID_AUTO
, reuse_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2021 &vm_page_stats_reusable
.reuse_pages_failure
, "");
2022 SYSCTL_QUAD(_vm
, OID_AUTO
, all_reuse_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2023 &vm_page_stats_reusable
.all_reuse_calls
, "");
2024 SYSCTL_QUAD(_vm
, OID_AUTO
, partial_reuse_calls
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2025 &vm_page_stats_reusable
.partial_reuse_calls
, "");
2026 SYSCTL_QUAD(_vm
, OID_AUTO
, can_reuse_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2027 &vm_page_stats_reusable
.can_reuse_success
, "");
2028 SYSCTL_QUAD(_vm
, OID_AUTO
, can_reuse_failure
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2029 &vm_page_stats_reusable
.can_reuse_failure
, "");
2030 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_reclaimed
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2031 &vm_page_stats_reusable
.reusable_reclaimed
, "");
2032 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_nonwritable
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2033 &vm_page_stats_reusable
.reusable_nonwritable
, "");
2034 SYSCTL_QUAD(_vm
, OID_AUTO
, reusable_shared
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2035 &vm_page_stats_reusable
.reusable_shared
, "");
2036 SYSCTL_QUAD(_vm
, OID_AUTO
, free_shared
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
2037 &vm_page_stats_reusable
.free_shared
, "");
2040 extern unsigned int vm_page_free_count
, vm_page_speculative_count
;
2041 SYSCTL_UINT(_vm
, OID_AUTO
, page_free_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_free_count
, 0, "");
2042 SYSCTL_UINT(_vm
, OID_AUTO
, page_speculative_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_speculative_count
, 0, "");
2044 extern unsigned int vm_page_cleaned_count
;
2045 SYSCTL_UINT(_vm
, OID_AUTO
, page_cleaned_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_cleaned_count
, 0, "Cleaned queue size");
2047 extern unsigned int vm_page_pageable_internal_count
, vm_page_pageable_external_count
;
2048 SYSCTL_UINT(_vm
, OID_AUTO
, page_pageable_internal_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_pageable_internal_count
, 0, "");
2049 SYSCTL_UINT(_vm
, OID_AUTO
, page_pageable_external_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_pageable_external_count
, 0, "");
2051 /* pageout counts */
2052 extern unsigned int vm_pageout_inactive_dirty_internal
, vm_pageout_inactive_dirty_external
, vm_pageout_inactive_clean
, vm_pageout_speculative_clean
, vm_pageout_inactive_used
;
2053 extern unsigned int vm_pageout_freed_from_inactive_clean
, vm_pageout_freed_from_speculative
;
2054 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_inactive_dirty_internal
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_inactive_dirty_internal
, 0, "");
2055 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_inactive_dirty_external
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_inactive_dirty_external
, 0, "");
2056 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_inactive_clean
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_inactive_clean
, 0, "");
2057 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_speculative_clean
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_speculative_clean
, 0, "");
2058 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_inactive_used
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_inactive_used
, 0, "");
2059 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_freed_from_inactive_clean
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_freed_from_inactive_clean
, 0, "");
2060 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_freed_from_speculative
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_freed_from_speculative
, 0, "");
2062 extern unsigned int vm_pageout_freed_from_cleaned
;
2063 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_freed_from_cleaned
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_freed_from_cleaned
, 0, "");
2065 /* counts of pages entering the cleaned queue */
2066 extern unsigned int vm_pageout_enqueued_cleaned
, vm_pageout_enqueued_cleaned_from_inactive_dirty
;
2067 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_enqueued_cleaned
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_enqueued_cleaned
, 0, ""); /* sum of next two */
2068 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_enqueued_cleaned_from_inactive_dirty
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_enqueued_cleaned_from_inactive_dirty
, 0, "");
2070 /* counts of pages leaving the cleaned queue */
2071 extern unsigned int vm_pageout_cleaned_reclaimed
, vm_pageout_cleaned_reactivated
, vm_pageout_cleaned_reference_reactivated
, vm_pageout_cleaned_volatile_reactivated
, vm_pageout_cleaned_fault_reactivated
, vm_pageout_cleaned_commit_reactivated
, vm_pageout_cleaned_busy
, vm_pageout_cleaned_nolock
;
2072 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_reclaimed
, 0, "Cleaned pages reclaimed");
2073 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_reactivated
, 0, "Cleaned pages reactivated"); /* sum of all reactivated AND busy and nolock (even though those actually get reDEactivated */
2074 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_reference_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_reference_reactivated
, 0, "Cleaned pages reference reactivated");
2075 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_volatile_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_volatile_reactivated
, 0, "Cleaned pages volatile reactivated");
2076 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_fault_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_fault_reactivated
, 0, "Cleaned pages fault reactivated");
2077 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_commit_reactivated
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_commit_reactivated
, 0, "Cleaned pages commit reactivated");
2078 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_busy
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_busy
, 0, "Cleaned pages busy (deactivated)");
2079 SYSCTL_UINT(_vm
, OID_AUTO
, pageout_cleaned_nolock
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_cleaned_nolock
, 0, "Cleaned pages no-lock (deactivated)");
2081 /* counts of pages prefaulted when entering a memory object */
2082 extern int64_t vm_prefault_nb_pages
, vm_prefault_nb_bailout
;
2083 SYSCTL_QUAD(_vm
, OID_AUTO
, prefault_nb_pages
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_prefault_nb_pages
, "");
2084 SYSCTL_QUAD(_vm
, OID_AUTO
, prefault_nb_bailout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_prefault_nb_bailout
, "");
2086 #if defined (__x86_64__)
2087 extern unsigned int vm_clump_promote_threshold
;
2088 SYSCTL_UINT(_vm
, OID_AUTO
, vm_clump_promote_threshold
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &vm_clump_promote_threshold
, 0, "clump size threshold for promotes");
2089 #if DEVELOPMENT || DEBUG
2090 extern unsigned long vm_clump_stats
[];
2091 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats1
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[1], "free page allocations from clump of 1 page");
2092 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats2
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[2], "free page allocations from clump of 2 pages");
2093 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats3
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[3], "free page allocations from clump of 3 pages");
2094 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats4
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[4], "free page allocations from clump of 4 pages");
2095 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats5
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[5], "free page allocations from clump of 5 pages");
2096 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats6
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[6], "free page allocations from clump of 6 pages");
2097 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats7
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[7], "free page allocations from clump of 7 pages");
2098 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats8
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[8], "free page allocations from clump of 8 pages");
2099 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats9
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[9], "free page allocations from clump of 9 pages");
2100 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats10
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[10], "free page allocations from clump of 10 pages");
2101 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats11
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[11], "free page allocations from clump of 11 pages");
2102 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats12
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[12], "free page allocations from clump of 12 pages");
2103 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats13
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[13], "free page allocations from clump of 13 pages");
2104 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats14
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[14], "free page allocations from clump of 14 pages");
2105 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats15
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[15], "free page allocations from clump of 15 pages");
2106 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_stats16
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_stats
[16], "free page allocations from clump of 16 pages");
2107 extern unsigned long vm_clump_allocs
, vm_clump_inserts
, vm_clump_inrange
, vm_clump_promotes
;
2108 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_alloc
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_allocs
, "free page allocations");
2109 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_inserts
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_inserts
, "free page insertions");
2110 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_inrange
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_inrange
, "free page insertions that are part of vm_pages");
2111 SYSCTL_LONG(_vm
, OID_AUTO
, vm_clump_promotes
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_clump_promotes
, "pages promoted to head");
2112 #endif /* if DEVELOPMENT || DEBUG */
2113 #endif /* #if defined (__x86_64__) */
2115 #if CONFIG_SECLUDED_MEMORY
2117 SYSCTL_UINT(_vm
, OID_AUTO
, num_tasks_can_use_secluded_mem
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &num_tasks_can_use_secluded_mem
, 0, "");
2118 extern unsigned int vm_page_secluded_target
;
2119 extern unsigned int vm_page_secluded_count
;
2120 extern unsigned int vm_page_secluded_count_free
;
2121 extern unsigned int vm_page_secluded_count_inuse
;
2122 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_target
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_target
, 0, "");
2123 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_count
, 0, "");
2124 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_count_free
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_count_free
, 0, "");
2125 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_count_inuse
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded_count_inuse
, 0, "");
2127 extern struct vm_page_secluded_data vm_page_secluded
;
2128 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_eligible
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.eligible_for_secluded
, 0, "");
2129 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_success_free
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_success_free
, 0, "");
2130 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_success_other
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_success_other
, 0, "");
2131 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_failure_locked
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_failure_locked
, 0, "");
2132 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_failure_state
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_failure_state
, 0, "");
2133 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_failure_dirty
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_failure_dirty
, 0, "");
2134 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_for_iokit
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_for_iokit
, 0, "");
2135 SYSCTL_UINT(_vm
, OID_AUTO
, page_secluded_grab_for_iokit_success
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_secluded
.grab_for_iokit_success
, 0, "");
2137 extern uint64_t vm_pageout_secluded_burst_count
;
2138 SYSCTL_QUAD(_vm
, OID_AUTO
, pageout_secluded_burst_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_pageout_secluded_burst_count
, "");
2140 #endif /* CONFIG_SECLUDED_MEMORY */
2142 #include <kern/thread.h>
2143 #include <sys/user.h>
2145 void vm_pageout_io_throttle(void);
2147 void vm_pageout_io_throttle(void) {
2148 struct uthread
*uthread
= get_bsdthread_info(current_thread());
2151 * thread is marked as a low priority I/O type
2152 * and the I/O we issued while in this cleaning operation
2153 * collided with normal I/O operations... we'll
2154 * delay in order to mitigate the impact of this
2155 * task on the normal operation of the system
2158 if (uthread
->uu_lowpri_window
) {
2159 throttle_lowpri_io(1);
2165 vm_pressure_monitor(
2166 __unused
struct proc
*p
,
2167 struct vm_pressure_monitor_args
*uap
,
2171 uint32_t pages_reclaimed
;
2172 uint32_t pages_wanted
;
2174 kr
= mach_vm_pressure_monitor(
2175 (boolean_t
) uap
->wait_for_pressure
,
2176 uap
->nsecs_monitored
,
2177 (uap
->pages_reclaimed
) ? &pages_reclaimed
: NULL
,
2189 if (uap
->pages_reclaimed
) {
2190 if (copyout((void *)&pages_reclaimed
,
2191 uap
->pages_reclaimed
,
2192 sizeof (pages_reclaimed
)) != 0) {
2197 *retval
= (int) pages_wanted
;
2202 kas_info(struct proc
*p
,
2203 struct kas_info_args
*uap
,
2204 int *retval __unused
)
2206 #ifdef SECURE_KERNEL
2210 #else /* !SECURE_KERNEL */
2211 int selector
= uap
->selector
;
2212 user_addr_t valuep
= uap
->value
;
2213 user_addr_t sizep
= uap
->size
;
2217 if (!kauth_cred_issuser(kauth_cred_get())) {
2222 error
= mac_system_check_kas_info(kauth_cred_get(), selector
);
2228 if (IS_64BIT_PROCESS(p
)) {
2229 user64_size_t size64
;
2230 error
= copyin(sizep
, &size64
, sizeof(size64
));
2231 size
= (user_size_t
)size64
;
2233 user32_size_t size32
;
2234 error
= copyin(sizep
, &size32
, sizeof(size32
));
2235 size
= (user_size_t
)size32
;
2242 case KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR
:
2244 uint64_t slide
= vm_kernel_slide
;
2246 if (sizeof(slide
) != size
) {
2250 if (IS_64BIT_PROCESS(p
)) {
2251 user64_size_t size64
= (user64_size_t
)size
;
2252 error
= copyout(&size64
, sizep
, sizeof(size64
));
2254 user32_size_t size32
= (user32_size_t
)size
;
2255 error
= copyout(&size32
, sizep
, sizeof(size32
));
2261 error
= copyout(&slide
, valuep
, sizeof(slide
));
2272 #endif /* !SECURE_KERNEL */
2276 #pragma clang diagnostic push
2277 #pragma clang diagnostic ignored "-Wcast-qual"
2278 #pragma clang diagnostic ignored "-Wunused-function"
2280 static void asserts() {
2281 static_assert(sizeof(vm_min_kernel_address
) == sizeof(unsigned long));
2282 static_assert(sizeof(vm_max_kernel_address
) == sizeof(unsigned long));
2285 SYSCTL_ULONG(_vm
, OID_AUTO
, vm_min_kernel_address
, CTLFLAG_RD
, (unsigned long *) &vm_min_kernel_address
, "");
2286 SYSCTL_ULONG(_vm
, OID_AUTO
, vm_max_kernel_address
, CTLFLAG_RD
, (unsigned long *) &vm_max_kernel_address
, "");
2287 #pragma clang diagnostic pop
2289 extern uint32_t vm_page_pages
;
2290 SYSCTL_UINT(_vm
, OID_AUTO
, pages
, CTLFLAG_RD
| CTLFLAG_LOCKED
, &vm_page_pages
, 0, "");
2292 #if (__arm__ || __arm64__) && (DEVELOPMENT || DEBUG)
2293 extern int pacified_footprint_suspend
;
2294 int footprint_suspend_allowed
= 0;
2295 SYSCTL_INT(_vm
, OID_AUTO
, footprint_suspend_allowed
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &footprint_suspend_allowed
, 0, "");
2297 extern void pmap_footprint_suspend(vm_map_t map
, boolean_t suspend
);
2299 sysctl_vm_footprint_suspend SYSCTL_HANDLER_ARGS
2301 #pragma unused(oidp, arg1, arg2)
2305 if (req
->newptr
== USER_ADDR_NULL
) {
2308 error
= SYSCTL_IN(req
, &new_value
, sizeof(int));
2312 if (pacified_footprint_suspend
&&
2313 !footprint_suspend_allowed
) {
2314 if (new_value
!= 0) {
2315 /* suspends are not allowed... */
2318 /* ... but let resumes proceed */
2320 DTRACE_VM2(footprint_suspend
,
2321 vm_map_t
, current_map(),
2324 pmap_footprint_suspend(current_map(), new_value
);
2328 SYSCTL_PROC(_vm
, OID_AUTO
, footprint_suspend
,
2329 CTLTYPE_INT
|CTLFLAG_WR
|CTLFLAG_ANYBODY
|CTLFLAG_LOCKED
|CTLFLAG_MASKED
,
2330 0, 0, &sysctl_vm_footprint_suspend
, "I", "");
2331 #endif /* (__arm__ || __arm64__) && (DEVELOPMENT || DEBUG) */