MacOS and iOS Internals, Volume II : Kernel Modechapter 1Welcome to the Machine: Hardware
DevicesMac Models Numbers and code names
12sysctl hw.modelioreg -l -f | grep IOPlatformExpertDevice
Processors“Rosetta”Processor Code Names“A”-series chips“n+n” “p-cores” “e-cores”
PortsSerial portsFirewire -> IEEE1394 fwkdp(1)ThunderBolt -> Intel’s ThunderBolt standard-> MiniDisplay Port and PCIeUSB usbkdp(1)
12ioreg -p IOUSBsystem_profiler SPUSBDataType
USB Restricted Mode
iDevice Connectors30-pinLightning
NVRAMMacOS: GUID Namespaces*OS: the nvrm namespaceMacOS: THe System Management BIOS-> Intel architectures*OS: SysCfg
The Device TreeDedicated ProcessorsCommon Code: RTKitThe *OS Side: RTBuddyAOP/AGX
chapter 2Use the source, Luke: The XNU Codebase
The XNU SourceKernel Address SANitizer (KASAN)
Compiling the kernelAvailabilityVersionsDTracelibplatformlibdispatch (firehose)Early during startup, this structure is saved by the Platform Expert, and PE* APIs -specifically, PE_parse_boot_argn or PE_parse_boot_arg_str - can be used to query thestring and retrieve numeric or string arguments.
Kernel DebuggingKernel Debug Protocol (kdp)
12345/* * Well-known UDP port, debugger side. * FIXME: This is what the 68K guys use, but beats me how they chose it... */#define KDP_REMOTE_PORT 41139 /* pick one and register it */
Don’t panicPESavePanicInfo
The Panic report/Library/Logs/DiagnosticReports[/Retired]/Kernel_YYYY-MM-DD-HHMMSS_Hostname.panic
Kernel Core Dumpskern_dump() kdumpd(8)
Coredump helperskern_register_coredump_helper
chapter 3EXTEND: Kernel ExtensionsXNU is no different in this regard: What in Windows are drivers and in Linux kernel modules are in Darwin kernel extensions. But similarities end very quickly, as thearchitectureal support and design of the extensions is quite different.kextload/kextutil/kext_logging/kextd/kextlibs
1kextstat | grep com.apple.kpi
The Kernel Programming InterfaceMACFramework
The kernelcache/System/Library/PrelinkedKernelsKernelcache structure__PRELINK_INFO.__info
Kext Loading: The user mode perspectiveKext Security Requirements/System/Library/Extensions/Library/ExtensionsKext code signing
12sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy -header "select * from settings"sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy -header "select * from kext_policy"
Kextd HOST_KEXTD_PORTMacOS 13: logkextloadedMacOS 14: BridgeOS kext_auditThe OSKext* APIskext_requestMultikexts
Kext Loading: The kernel perspectivevm_map_copyoutOSKext::loadDarwin 13 -> mac_kext_check_loadkxld Kernel extension loader-> kxld_link_file()Unloading a kext
kext metadata managementMacOS 15: System Extensions and DriverKitDarwin 19, however, provides an alternative - allowing developers to create,what are in effect, user-mode extensions and drivers, through two new frameworks
SystemExtensions and DriverKit.The idea is not unlike that of Windows’ User Mode Driver Framewrok(UMDF), in whichkernel code calls out to some user process, in order to perform some operations.NECP(Network Exetnsions model)NKE(Network Kernel Extensions)Darwin’s port of FUSE(Filesystem in USEr mode)Apple classifies Driver Extensions as those extensions which seek to replace(now legacy)IOKit drivers, and System Extensions for all other traditions in-kernel functionlity,such as Network Extensions (for packet filtering, tunneling, etc), and Endpoint Security Extensions.System Extensions -> sysextdDriver ExtensionsAs with IOKit, developers can use C++, but unlike it, this is a full C++17 compatible runtime, rather than IOKit’s restricted C++.
chapter 4Some Assembly Required: Kernel Primitives & Paradigms
Data StructuresQueues (Mach)* osfmk/kern/queue.hstruct queue_entryLinked Lists & Queues (BSD) bsd/sys/queue.hTree data structuressplay trees(slef-adjusting binary search)Red-Black trees
Concurrent resource accessAtomic operationshwlocksSpinlocks -> busy waitRead-Write LocksMutex locksLock GroupsLock Debugging/Tracing -> /dev/lockstat (legacy) or lockstat provider
Per-CPU dataosfmk/machine/cpu_data.h
Processor execution modesIntel Ring0/Ring3ARM64 Exception LevelsEL0 is user mode, EL1 is kernel mode, EL2 is reserved for the hypervisor (if any),and EL3 for secure monitor (if any).
Mode TraversalVoluntary TraversalsInvoluntary traversalsIntel: SYSENTER(Vol)Intel: IDT(Invol)ARM: Exception Vectors
Returning to user modethread_exception_return()
Context Switchingmachine_switch_context()osfmk/arch/cswitch.skernel_bootstrap_threadosfmk/kern/startup.c
Accessing user mode memoryUnlike kernel memory, which is normally wired(resident), user-space memorymay be swappwd. If that is the case, access will trigger a page fault. [bcopy]copyin* and copyoutvm_fault()
Memory Access ProtectionsIntel architectures define Secure Mode Access Prevention (SMAP), and ARM(v8.1 and later)architectures similary have Privileged Access Never (PAN).
Interrupt Handlingx86_64 uses the Advanced Programmer Interrupt Controller (APIC), which (as of Nehalem) is known as x2APIC.ARM recignizes two types of interrupts - the regular interrupt requests (IRQ) and “fastinterrupts requests” (FIQ).
Enabling/disabling interrupts -> Asynchronous Software Traps
Machine Level handling of interruptsx86_64 hndl_allintrs -> osfmk/x86_64/idt64.sarm exception vectors -> [fleh/sleh]_[irq/fiq]1sudo powermetrics --samplers interrupts
XNU’s Handling of InterruptsIntel -> interrupt() osfmk/i386/trap.cARM -> fleh_[irq/fiq] osfmk/arm[64]/locore.s -> sleh_[irq/fiq] osfmk/arm64/sleh.c
System call personalities
The BSD PersonalityAuditing/KDebug/Arguments/Noreturn
The Mach Personality
Machine Sepcific Syscallsplatform_syscall
Hypervisor support (MacOS)
chapter 5Alone in the Dark: The Boot Process
MacOS: EFIBasic ConceptsUnlike BIOS, EFI is in some respects a mini operating system.
The Boot Services
The Runtime Services1nm /System/Library/Extensions/AppleEFIRuntime.kext/Contents/MacOS/AppleEFIRuntime -UCgj
EFI Protocols-> Clover bootloaderThe EFI System PartitionSoftware capsulesEFI BinariesAs Microsoft owned the dominat platform at the time, it made sense to chooseWindows Portable Executable (PE) as the binary format.MacOS’s boot.efiMacOS’s boot.efi is rare biard - a PE32+ binary among all the other Mach-Os.1file /usr/standalone/i386/boot.efi
Blessed Art Thou1sudo bless --info --verbose # only Intel Arch, not for M1
*OS: iBootMacBook Pro (2018) and later: iBoot + EFISecure Boot
Kernel Boot Processx86_64: _start -> _vstartARM64: _start -> start_first_cpui386_init() and arm_init()kernel_early_bootstrap() -> osfmk/kern/startup.cmachine_startup/kernel_bootstrapkernel_bootstrap_log
12345678// osfmk/arm/start.sLOAD_ADDR(lr, arm_init)// osfmk/arm/arm_init.c__startup_funcvoid arm_init(boot_args *args)// osfmk/kern/startup.c__startup_funcvoid kernel_startup_bootstrap(void)
kernel_bootstrap_thread()-> idle_thread_create -> kernel_thread_create-> idle_thread -> processor_idle -> thread_run-> thread_invoke -> thread_dispatch(self, thread)/call_continuation
123int thread_run(thread_t self, thread_continue_t continuation, void *parameter, thread_t new_thread);thread_run(processor->idle_thread, idle_thread, NULL, new_thread);
123456// LOAD_ADDR(lr, arm_init_cpu)slave_main(NULL);// -> processor_start_thread thread_block(idle_thread);-> processor_start
SMP Considerationsman hostinfoprocessor_start -> cpu_start -> slave_mainx86_64 i386_init_slave_fastARM64 arm_init_cpu()
Kernel Threadskernel_task -> pid 0
Kernel Shutdownreboot/halt/shutdown mac_system_check_rebootreboot_kernel -> host_reboot -> halt_all_cpus/PEHaltRestart
chapter 6BS’’D: The BSD Layer
A Tour of BSDNeXT wanted to conform to it as well, which required adding another layer,on top of Mach, for the POSIX compatible APIs. Rather than implement somethingfrom scratch, the choice was made to adopt FreeBSD implementation.FreeBSD 6.0bsd_init()/bsd_init_kprintf()throttle/kmeminit/dev_kmen_initkauth_init/procinit/tty_init/mac_policy_initbsdulock_initializeaudit_initaio_init/pipeinit/sys v ipc lockspthread_init/select_waitq_initMemorystatussysctl_mib_initbsd_autoconfdtrace_postinitnetwork initsroot filesystem mountedsiginit
Launching launchd(8)bsd_utaskbootstrapcloneproc()bsdinit_task()
ProcessesMach defines tasks, but the BSD layer provides the highter level constructsthat are processes.
The struct procProcess Control Block(PCB)
The kernproc
Process lists12extern struct proclist allproc; /* List of all processes. */extern struct proclist zombproc; /* List of zombie processes. */
Process data in user modesysctl kern.procproc_info
(U)ThreadsThe struct uthread [bsd/sys/user.h]
Syscall information
Exception information
Continuation support select/kevent/wait
The wait channel
Pointers
Flags UT_* flags
Signal handling information
VFS context
Audit record123#if CONFIG_AUDIT struct kaudit_record *uu_ar; /* audit record */#endif
Throttling info
DTrace information
Document tombstone information
Exit reason
Thread name
Thread list connectorsNote that BSD level threads have no identifier which can be globally visible in user mode.There is the underlying Mach thread’s ID, but there is no BSD style API to retrieve it.
Pthread shims and callbacks (Darwin 13)pthread_kext_register pthread.kext
Work Queue threads (the kernel-side portion of GCD)in-kernel thread-poolworkq_open()/workq_kernreturn() bsd/pthread/pthread_workqueue.c
1struct workqueue
Parked thread block on workq_unpark_continue(), a continuation which allows quick resumption.workq_reqthreads -> workq_pop_idle_threadworkq_add_new_idle_thread -> workq_create_threadstack/thread_create_workq_waiting
BSD *sleep nad wakeup*1234extern int msleep(void *chan, lck_mtx_t *mtx, int pri, const char *wmesg, struct timespec * ts );extern int msleep0(void *chan, lck_mtx_t *mtx, int pri, const char *wmesg, int timo, int (*continuation)(int));extern void wakeup(void *chan);extern void wakeup_one(caddr_t chan);
All the sleep variants require a kernel address, referred to as a wait channel,which is used as a token to wake up the sleepers.The chan and wmesg arguments are stored on the uuthread’s uu_wchan and uu_wmesg.
Process Lifecyclefork/vfork/posix_spawn[__mac_]execve/posix_spawn
Image Activation: exec_activate_image()
Mach-O Image Activator: exec_mach_imgact
Loading Mach-O: load_machfile()pmap_create/vm_map_create
Parsing Mach-O: parse_machfile()
Post Load: exec_mach_imgact()
Process TerminationExit reasons -> exit_with_reason (Darwin 16)os_reason bsd/sys/reason.h
Core dumpskern.coredump
Crash ReportsEXC_CRASH Mach exceptiontask_exception_notify [osfmk/kern/exception.c]-> exception_triage -> exception_triage_thread-> exception_deliver
Corpses
File Descriptors
The struct filedesc [bsd/sys/filedecs.h]
The struct fileproc12345678__options_decl(fileproc_flags_t, uint16_t, { FP_NONE = 0, FP_CLOEXEC = 0x01, FP_CLOFORK = 0x02, FP_INSELECT = 0x04, FP_AIOISSUED = 0x08, FP_SELCONFLICT = 0x10, /* select conflict on an individual fp */});
The struct fileglob
File Types
POSIX Shared Memoryshm_open/mmap
KQueuesXNU supports dynamic kqueues, which are maintained at the filedec level in the fd_kqhash table.struct knote [bsd/sys/event.h]
Pipesstruct pipe [bsd/sys/pipe.h]/[bsd/kern/sys_pipe.c]A pipe dies when its read end is closed, in which case the writer gets a SIGPIPE when attempting a write (unless suppressed).
File I/Oopen/openat[_nocancel] -> openat_internal [bsd/vfs/vfs_syscalls.c]
123456intopenat(proc_t p, struct openat_args *uap, int32_t *retval){ __pthread_testcancel(1); return openat_nocancel(p, (struct openat_nocancel_args *)uap, retval);}
read[_nocancel] -> bsd/kern/sys_generic.cThe struct uioUser mode I/O requests are standardized into struct uio, which represents the metadatadetailing an I/O request.uio_create/uio_createwithbufferHandling uiosreadv/writev -> iovec
Asynchronous I/OPOSIX aio* interfaces -> bsd/kern/kern_aio.caio_read/write / aio_fsync-> aio_queue_async_requestaio_max_requests_per_process
BSD Memory ZonesBSD provides the notion of memory zones: Zones are preallocated arrays of objects of anidentical size.kmzones [bsd/kern/kern_malloc.c]vm_allocation_site Darwin15
sysctlsysctl_register_oid
123456sysctl netsysctl net.inet.tcpsysctl net.inet.tcp.pcbcountsysctl -X net.inet.tcp.pcblistsysctl -X net.inet.tcp.pcblist_nsysctl -X | wc -l
kern/vm/net/debug/hw/machdep/usersysctlbyname -> name2oid__DATA.__sysctl_set
DTracedtrace_init <- bsd_autoconfdtrace_cpu_state_changedProviders -> dtrace_registerdtrace/profile/syscall/mach_trap/lockstat/sdt/fbtProbes -> dtrace_probe_createCase Study: The fbt providerfbt_provide_probeThe function inspects the instruction stream at the address, trying to find the familiarPUSH RBP in Intel, and an STP FP, LR, .. (the frame pointeer and link register) in ARM.
chapter 7Fee, Fi-fo, File - the Virtual Filesystem Switch
VFS Concepts
Filesystemsnfs/devfs/nullfs/mockfs/routefs [bsd/vfs/vfs_conf.c]1man lsvfs
Mounts /System/Library/FileSystemsThe system maintains all its mounts in the mountlist.1extern TAILQ_HEAD(mntlist, mount) mountlist;
f_mntonname (name of mount point) and f_mntfromname (mounted filesystem)
vnodesA vnode is a representation of a file or special object, independent of the underlyingthe system. HFS+ and APFS use the number as a B-Tree node identifier.
The ubc_info (V_REG vnodes)The Unifide Buffer Cache (UBC) is a concept first introduced into NetBSD.1struct ubc_info
Buffersstruct buf [bsd/sys/buf_internal.j]
File System Attributes[bsd/vfs/vfs_attrlist.c]
Apple Extensions
Resource Forkscom.apple.ResourceFork
File compressioncom.apple.decmpfsdecmpfs_file_is_compressed
Restricted (MacOS)com.apple.rootless
Data Vault (Darwin 17)com.apple.rootless.datavault.controller
Data Protectioncom.apple.system.cprotect
FSEvents
Document IDs
Object IDs
Disk Conditioning (Darwin 17)
Triggers (MacOS)
EVFILT_VNODE kevent(2) notifications
/dev/vn## (conditional)
File Providersnspace_resolver_init <- vfsinit1man fileproviderctl
VFS KPIsKPI -> Kernel Programming Interfacebsd/vfs/vfs_vnops.c
The vfs_context_t
Manipulating file in kernel modenamei [bsd/vfs/vfs_lookup.c]vnode_open [bsd/vfs/vfs_subr.c]
Direct File I/Okern_open_file_for_direct_io()
Vnode lifecycleFile I/O, however, is very frequent. So sooner or later any limit will be hit,but vnodes never get freed - instead, they are recycled.
VFS SPIsSPI -> Service Provider Interface
Registering Filesystemsvfs_fsadd [bsd/vfs/kpi_vfs.c]
VFS operationsstruct vfsops [bsd/sys/mount.h]
Vnode operations
Case StudiesThe flow of fo_read
/dev (devfs)
The [b|c]devsw entriesBlock/Char Device
specfs nodesv_type of VBLK or VCHR
The fdesc quasi-filesystem/dev/fd /dev/[stdin/stdout/stderr][bsd/miscfs/devfs/devfs_fdesc_support.c]
NFS (MacOS)/sbin/nfsd/usr/libexec/automountd/sbin/nfsiod
NFS server operationsnfssvc/getfh/fhopen
NFS client operations1man nfsstat
Filesystems in USEr mode (FUSE)Because FUSE does require a kernel component, it is not applicable in the *OS variants,wherein Apple uses DMG mounts (by registering loop block devices) instead.
chapter 8Space Oddity: APFS
A Bird’s Eye View of APFSThe APFS partition type is identified by a well-known GUID.B-Tree [The RootFS Tree/The Extent Tree]
Filesystem Features
Full 64-bit filesystem
Volume Management
EncryptionMacOS was one of the first operationg systems to provide full disk encryption, when Appleintroducde FileVault in MacOS 10.7.apfs_meta_crypto
Fast Directory Sizingdu -> dir sizeAPFS provides a significant speed up, by storing the directory usage statistics asadditional metadata (an APFS_TYPE_DIR_STATS record) for the directory object.
Sparse File support
Atomic safe-saverename[at]x_np
File/Directory Cloningclonefileat (#462)
Copy-on-WriteThis also makes APFS a “flash friendly” filesystem.Suprisingly, however, APPLE chose not to provide an undelete tool, instead offeringa different model, of snapshots.
Snapshotsfs_snapshot (#518)1man fs_snapshot_create # macOS 10.13
DefragmentationDarwin 18
Volume Groups and Firm Links (Darwin 19+)
Purgeable Files (Darwin 19+)
File System InternalsUnallocated/Used by a file object/Used by APFS itself
APFS Objects
APFS object structure
B-TreesThe B-tree used by APFS are actually B+ trees - a refinement on classic B-trees, byrestricting values to leaf nodes only. Thus, non-leaf nodes (the root and deeper levels) hold only keys and identifiers of child nodes.APFS nodes further have no sibling pointers, which further compacts space needed, but impacts sequential reading of values: When the end of the node is reached, the next value in its sibling record must be located by starting the search at the root
The B-Tree Node FormatBTNODE_ROOT (0x1) BTNODE_LEAF (0x2)
Containers & Volumes
VolumesEach volume maintains three trees - filesystem, snapshot metadata and extent.
Filesystem Trees
The Space Manager
Chunk Info Blocks (CIBs)
CIB Address Blocks (CABs)
Reaping Objects
APFS.kextcom.apple.filesystem.apfs/System/Library/Extensions/apfs.kextclosed source
fsctl(2) codes
UserClient Methods
chapter 9Tempus Fugit: Mach Scheduling
The High Level ViewMach Tasksstruct task [osfmk/kern/task.h]
The task lock
Statistics
Priority, maxmimum priority and importance
The vm_map
Linkage
Threads
Task port space
Task special ports
Task registered ports
Task exception ports
The Machine task
Security and audit tokens
Counts
Resource usage
The corresponding struct proc
Corpse information
I/O statistics
Flags
Purgeable VM objects
Coalitions
Associated hypervisor Virtual Machine (MacOS)
Seclude memory
External Modification statistics
Effective and requested scheduling policies
IOUserClients
Task watching (*OS) task_watchers
The kernel_taskMach ThreadsFor all their size, Mach tasks (like UNIX processes) are merely resource containers.It is their threads which are the scheduleable entities.struct thread [osfmk/kern/thread.h]
12345678910111213141516171819202122232425struct thread_ro { struct thread *tro_owner;#if MACH_BSD struct ucred *tro_cred; struct proc *tro_proc; struct proc_ro *tro_proc_ro;#endif struct task *tro_task; thread_ro_flags_t tro_flags; struct ipc_port *tro_self_port; struct ipc_port *tro_settable_self_port; /* send right */ struct ipc_port *tro_ports[THREAD_SELF_PORT_COUNT]; /* no right */ struct exception_action *tro_exc_actions;};struct thread{ // ...... /* Task membership */#if __x86_64__ || __arm__ struct task *t_task;#endif struct thread_ro *t_tro; // ......};
Execution State
Linkage
Wait data
Ports
Priority
Scheudling information
Continuation
Affinity values
Page fault recovery handler
Thread call state
Guard execption codes
Turnstile
The BSD uuthread object
DTrace data
Per-thread statistics
Ledger details
Associated voucher
Tag
The machine dependent thread object
Thread creationthread_create[_running]Threads are normally created suspended, but using the running variant allows the caller to set the initial register state of the process and immdeidately schedule it for execution.thread_create && thread_startkernel_thread_create/kernel_thread_start[_priority]machine_thread_create [osfmk/arm64/pcb.c]
Thread terminationthread_terminate [osfmk/kern/thread_act.c]It then puts the thread into a block, to continue on thread_terminate_continue.The continuation, however, will never be reached (if it were to be reached, the kernelwould panic).
Processor Managementprocessor_set_default
Mach Scheduling EnhancementsFor IPC to be efficient, the scheduler must be highly effective - as Mach strives to be.
HandoffMach supports handoff in addition to the standard yield.注:switch direct, not yield??thread_handoff_[internal/parameter]thread_switch (user mode)
ContinuationsA continuation is a function, along with an optional parameter, which is provided asan argument to kernel_thread_create(), or to thread_block[_reason].struct thread_snapshot -> uint64_t continuation;12#define ith_continuation saved.receive.continuation#define sth_continuation saved.sema.continuation
struct uthread -> uu_continuation (BSD layer)
Asynchronous Software Traps (AST)
Handling ASTs
AST reasons [osfmk/kern/ast.h]12#define AST_SCHEDULING (AST_PREEMPTION | AST_YIELD | AST_HANDOFF)// processor_idle/thread_block_reason call ast_off(AST_SCHEDULING);
Mach Schedulers[osfmk/kern/sched.h]Darwin version before Darwin 17 use multiq, but Darwin 18 shifts to qualq.*OS 13 variant use a new scheduler called AMP, which takes into account the core type(Performance or efficiency) as well.The kern.sched sysctl(8) MIB will show the currentlyactive scheduler.Not note in this bookamp -> clutch()
12345#if CONFIG_SCHED_EDGE#include
sched_clutch.cclutch/edage
1sysctl kern.sched
macOS 12.6Mac mini (Late 2014)kern.sched: dualqMac mini (M1, 2020)kern.sched: edge
[osfmk/arm/proc_reg.h]123456789101112131415#if CONFIG_CLUTCH#if __ARM_AMP__/* Enable the Edge scheduler for all J129 platforms */#if XNU_TARGET_OS_OSX#define CONFIG_SCHED_CLUTCH 1#define CONFIG_SCHED_EDGE 1#endif /* XNU_TARGET_OS_OSX */#else /* __ARM_AMP__ */#define CONFIG_SCHED_CLUTCH 1#endif /* __ARM_AMP__ */#endif /* CONFIG_CLUTCH */
All Mach schedulers “plug in” to the scheduler primitives defined in osfmk/kern/sched_prim.c.
The Run Queue1struct run_queue;
PrioritiesThreads are queued in one of the NRQS queues, in FIFO ordering.BASEPRI_DEFAULT -> nice(1)
Load Average/Mach Factor, and Priority ShiftsA key metric in any UNIX system is its load average, which is reported by commands suchas w(1) and uptime (1).1sysctl vm.loadavg
The Mach factor can be retrieved using hostinfo(1).XNU also calculates a more fine grained scheduler load, which it uses to implement priortiy shifts.update_priority/sched_usage
Scheduling buckets and the EWMAsched_bucket_tXNU’s averages was further tweaked in Darwin 18 to an Exponentially Weighted Moving Averagealgorithm(EWMA).[osfmk/kern/sched_average.c]
Scheduler dispatch[osfmk/kern/sched_prim.c]1struct sched_dispatch_table;
thread_select
thread_invoke
thread_dispatch
qunatum_expire
update_priority (osfmk/kern/priority.c)
sched_maintenance_thread
Multicore considerationsThe calls for rebalancing, by moving queued threads from busy processor(s) to the less busyones(s), based on the respective run queue lengths.123sysctl kern | grep kern.schedsysctl kern.sched_enable_smtsysctl kern.sched_allow_NO_SMT_threads
Darwin 17 additions
Real time threading support
Multi processor support
Thread yield checks
Darwin 19 additions
Run counts
Thread buckets
Multiple processor set support
Effectuating policy changes
Deferred Calls[osfmk/kern/call_entry.h]
Timer calls[osfmk/kern/timer_call.h]1typedef struct timer_call;
Timer coalescingOne of Darwin 13’s most important “under the hood” changes was the introduction ofTimer Coalescing. When timers start up too frequently, the CPU can enjoy less idle periods
and waking up the CPU can actually take more power than just leaving it on for a slightlylonger period.timer_call_enter_with_leewayNote: Windows 8 and later have a similar mechanism in the EX_TIMERS and EX*Timer routines,with “No-wake timers”. Linux 2.6.22 and later timer_lists offer TIMER_DEFERRABLE).Ref: https://learn.microsoft.com/zh-cn/windows-hardware/drivers/ddi/wdm/ns-wdm-_ext_set_parameters_v0 (LONGLONG NoWakeTolerance;)
Scheduling timers
Thread calls
Servicing thread calls
Scheduler assisted synchronization
Wait QueuesMach follows this pattern as well, with the waitq and waitq_set structures.The waitqs can befound embedded in Mach ports, semaphores and (as of Darwin 18) turnstiles, and they alsosupport BSD’s select(2) and AIO implementaiotns. The waitq_sets back select(2) as well,along with kqueues and Mach ipc_mqueues.struct waitq [osfmk/kern/waitq.h]
selection callbackswaitq_select_12345#pragma mark global wait queuesstatic __startup_data struct waitq g_boot_waitq;static SECURITY_READ_ONLY_LATE(struct waitq *) global_waitqs = &g_boot_waitq;static SECURITY_READ_ONLY_LATE(uint32_t) g_num_waitqs = 1;
Ulocks (Darwin 16+)__ulock_wait/__ulock_wakeAs the double underscores imply, user mode is not intened to use these system callsdirectly, instead working with libplatform.dylib’s higher level os_unfair_lock_t.[bsd/kern/sys_ulock.c]sys_ulock_wait (#515) -> ulock_waitsys_ulock_wake (#516) -> ulock_wake
Turnstiles (Darwin 18+)The concept first appeared in Solaris, and was then adopted by FreeBSD, and well explainedin the BSD bible.Theoryoptimize short term locks and the scheduling of waiters wehn the locks become available.Darwin implmentation of Turnstiles.turnstiles_init()[osfmk/kern/turnstile.h]Ref:https://book.douban.com/subject/3666232/https://greenteapress.com/wp/semaphores/https://blog.csdn.net/booksyhay/article/details/82692362[信号量小书 第三章 基本同步模式]https://www.likecs.com/show-204583284.html#3.7.6%20%E9%A2%84%E8%A3%85%E6%97%8B%E8%BD%AC%E6%A0%85%E9%97%A8%EF%BC%88Preloaded%20turnstile%EF%BC%89123456789101112typedef enum __attribute__((packed)) turnstile_type { TURNSTILE_NONE = 0, TURNSTILE_KERNEL_MUTEX = 1, TURNSTILE_ULOCK = 2, TURNSTILE_PTHREAD_MUTEX = 3, TURNSTILE_SYNC_IPC = 4, TURNSTILE_WORKLOOPS = 5, TURNSTILE_WORKQS = 6, TURNSTILE_KNOTE = 7, TURNSTILE_SLEEP_INHERITOR = 8, TURNSTILE_TOTAL_TYPES = 9,} turnstile_type_t;
Benefits of Turnstiles“thundering herd” problempriority inversion
KDebug codesDBG_TURNSTILE
Gates (Darwin 19)
Ledgers
ledger (#373)
Initialization
Maintenance
Selective Forced Idle (SFI)Darwin 13The main user-mode client of the SFI facility is the thermald.
chapter 10Mixed Messages: Mach IPC
The High Level ViewMach is, first and foremost, a kernel optimized for message passing.ipc_space_t
Task ipc_space_tstruct ipc_space [osfmk/ipc/ipc_space.h]ipc_space_create
The ipc_port[osfmk/ipc/ipc_port.h]ipc_port_make_send
Case Study: resolving a port name to the underlying object address[osfmk/ipc/ipc_object.c]
Port lifecycle
Port allocation [osfmk/ipc/mach_port.c]
Rights and Names
Reference countingmach_msg -> mach_msg_trap-> mach_msg_trap-> ipc_kmsg_send/ipc_mqueue_receive
Port deallocation
Handling messages[osfmk/ipc/ipc_mqueue.h]
mach_msg revisited
Sending Mach messagesipc_kmsg_send
ipc_mqueue_send()
Receiving Mach messagesipc_mqueue_receive
Destriying messages[osfmk/ipc/ipc_kmsg.c]
Message Descriptors
Port right descriptors ipc_kmsg_copyin_port_descriptor
Port set (OOL ports) descriptors
OOL memory descriptors
Descriptors as a vehicle for malicious attacks
VouchersDarwin 14 [osfmk/ipc/ipc_voucher.h]
User-mode APIhost_create_mach_voucher_trapmach_voucher_extract_attr_recipe_trap
ImplementationIKOT_VOUCHER
Multinode
Multinode requirementsmach_host_other()
FLIPCFast Local InterProcess Communication (FLIPC)Mach Node [osfmk/kern/mach_node.c] mach_node_registerFLIPC [osfmk/ipc/flipc.c]
chapter 11Mapped out: Mach Memory Management
A Bird’s Eye ViewMach’s Virtual Memory subsystemvm_map -> virtual memorypmap -> physical memory
The vm_map Layer
The struct _vm_map[osfmk/vm/vm_map.h]vm_map_create[_options]
vm_objects[osfmk/vm/vm_object.h]
vm_pages[osfmk/vm/vm_page.h]pmap_startup/pmap_free_pagespmap_steal_memoryvm_page_lookup()
User mode interfacehost_virtual_physical_table_infovm_mapped_pages_infomach_vm_page_infovm_page_info_basic
vm_map_enter and friends[mach_]vm_allocate()
Allocating memory (highlighs)VM_PROT_EXECUTEcom.apple.security.cs.allow-jitkernel_memory_allocate
The vm_map_copy object1struct vm_map_copy;
Copying memory[mach_]vm_copy()
PagersPager types supported in Darwin 18Vnode/Device/Apple Protect/swapfileCompressor/4K(4K emulation on 16K)/shared
The Pager objectstruct memory_object
Pager Lifecycle callbacks
The vnode pager
The swapfile pager
The compressor pager[osfmk/vm/WKdm_new.h]Wilson & Kaplanvm_compressor_algorithms.h
Lifecycle
The Device Pager[osfmk/vm/device_vm.c]
The 4K Pager (*OS)
The sahred region pager (Darwin 18)
The Apple Protect pagermemory encryption[osfmk/vm/vm_apple_protect.c]
MacOS: Dont Steal Mac OS X.kextdsmos_page_transform_hook[osfmk/kern/page_decypt.c]
*OS: Fairplay encryption
Page Lists (UPLs)struct upl [osfmk/vm/vm_pageout.h]
Creating UPLs ubc_create_upl()
Handling UPLs [osfmk/mach/upl.defs]
The pmap Layer[osfmk/vm/pmap.h]pmap_create
Page TablesIn Intel, the special CR3 register holds the base of the page tables for a giver process.In ARM architecures, the Translation Table Base Registers (TTBRs) are used instead. ARM64providers a differnt TTBR for every execption level, so TTBR_EL0 is employde by user mode,and TTBR_EL1 by the kernel.Page Table Entrye(PTE)pmap_pte(pmap, va)
WIMGWrite-through, Cache-Inhibition, Memory Coherence and Guarde writes
I/O Mappingsml_io_map()
Intel PTEs
The ARM PTEs
chapre 12Ceci n’est pas une “heap”: Kernel Memory ManagementWe detail how the kernel manages its own vm_map - the kernel_map - through kmem_alloc*and kalloc*.
Kernel Memory Allocation
The kernel_map[osfmk/vm/vm_kern.c]VM_MIN_KERNEL_AND_KEXT_ADDRESSVM_MAX_KERNEL_AND_KEXT_ADDRESS
kmem_alloc() and friends
kernel_memory_allocate vm_map_find_space
kmem_suballoc
kmem_realloc
kalloc
kalloc.###zones zalloc_canblock_tag/vm_allocation_site
The Kalloc DLUTDirect LookUp Table (DLUT)[osfmk/kern/kalloc.c]
The slow path
OSMalloc*[libkern/libkern/OSMalloc.h]The main advantage of using OSMalloc is its support of memory tags.
The Zone Allocatorlike Linux’s Slabszalloc() [osfmk/kern/zalloc.c]
1man zprint
Zone Management
The zone_metadata_region
The zone metadata
Element Free Lists
Garbage Collectionconsider_zone_gc()/zone_gc()vm_pageout_garbage_collect
GC and UAFmach_zone_force_gc
Battling zone corruption
The Guard Mode Zone Allocator (MacOS)like libgmalloc(3) (Guard Malloc) in user mode
The Zone Cache (Darwin 18+)
Memorystauts (MacOS) anad Jetsam (*OS)
Purgeable memorytask_purgable_info[mach_]vm_purgable_controlmemory_entry_purgable_control
Kernel Memory Layout
The kernel_map regions
The Kernel SlideKernel Address Space Layout Randomization (KALSR) [Darwin 12]1sysctl kern.slide
vm_kernel_slidervm_kernel_addrhash_salt
chapter 13All in the Family: IOKitIORegistry IOCatalogue
A High level view of IOKit
The IOKit.frameworkIO Master Portdevice_service_create [osfmk/device/device_init.c]
IOKit error codes[iokit/IOKit/IOReturn.h]IOService::stringFromReturn
The IORegistryIORegistryPlanes
1ioreg -l -w 0 -f | grep IORegistryPlanes
IORegistryExplorer.app -> XCode’s Additional Tools
User Mode APIs
IteratorsIOIterator
The IOCatalog (ue)
Matching Dictionaries
NotifiationskIO…NotificationIONotificationPortCreate()
Interlude: Libkern Base Classes
OSObject
OSMetaClass(Base)
APIs
DefaultStrutors
Members, methods and the Fragile Base Class proble
Object types
OSStrings and OSSymbols
OSCollections
Serializaition
XML Serialization
Binary Serialization
The Class Menagerie
IOKIt Built-in classes
IORegistryEntry
IOService
IO*MemoryDescriptor
IO*MemoryCursor
IOWorkLoop
IO*EventSource and IOCommand
IOCommandQueue
IOKit Families
Driver Life Cycle
Driver MatchingIOKitPersonalities
Case Study: VMWare Fusion VMIOPlug
Driver activity and the IOWorkLoop
Messaging
Matching Notifications
Interrupt Handling
IOUserClients
IOUserClient lifecycle
Driver Properties
NotificationsIOConnectSetNotificationPort
Mapped Memory
External Traps
Extenal Methods
IOCFPlugInTypes
Darwin 19: DriverKit
IOUserServer
IORPC
chapter 14Stacking Up: Kernel Networking
The High Level ViewLayer V: Sockets
The struct socket
Socket Creationsocreate_internal() [bsd/kern/uipc_socket.c]
sockbufs
mbufsstruct mbuf;[bsd/sys/mbuf.h]XNU also supports an “mbuf watchdog”, toggled through kern.ipc.mb_watchdog.
Sockets in kernel mode[bsd/kern/kpi_socket.h]sock_connectwaitsock_socket -> socreate
Layer IV: Domains & Protocols
Domains
Protocols
Case Study: PF_SYSTEM sockets
SYSPROTO_EVENT
SYSPROTO_CONTROL
Layer III: Network Protocols
Incoming packets
Layer II: Interfaces - The Data Link Interface Layer
The struct ifnet
Interface lifecycle
Case Study: The UTUN interface
Network Data Processing
Sending Data
IPv4/IPv6 packet output
DLIL output
Receiving data
DLIL frame reception
IPv4/IPv6 packaet input
Firewalling & Filtering mechanisms
Socket Filters
Content Filters (Darwin 14+)
IP filters
PFBSD PFpfctl(8)
Interface Filters
BPF
Network Extension Control Policies
NECP file descriptorsnecp_open() [bsd/net/necp_client.c]
NECP Session FDsnecp_session_opne()
Policy evaluation
