深入解析MacOS和iOS 卷二 笔记

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 #endif /* CONFIG_SCHED_EDGE */.sched_name = "clutch",.sched_name = "edge",

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