/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ #include #include #include #define CLOSURE(s) #s, #define CRITICAL(s) #s, #if KASAN #define KASAN_ONLY(s) #s, #else #define KASAN_ONLY(s) #endif /* KASAN */ #if CONFIG_UBSAN_MINIMAL #define UBSAN_MINIMAL_ONLY(s) #s, #else #define UBSAN_MINIMAL_ONLY(s) #endif #if defined(__arm64__) #define ARM_ONLY(s) #s, #else #define ARM_ONLY(s) #endif /* defined(__arm64__) */ #if defined(__x86_64__) #define X86_ONLY(s) #s, #else #define X86_ONLY(s) #endif /* defined(__x86_64__) */ /* * Routine prefixes that must not be probed, either because they are used in * the exception path, by dtrace code in probe context, or are general * critical routines that must never be probed. * * All routines whose name start with one of these will be ignored. * * This must be kept in asciibetical order for purposes of bsearch(). */ const char * fbt_blacklist[] = { CRITICAL(Call_DebuggerC) CLOSURE(ClearIdlePop) CLOSURE(Debugger) CRITICAL(IOCPURunPlatformPanicActions) CLOSURE(IS_64BIT_PROCESS) CRITICAL(OSAdd) CRITICAL(OSBit) CLOSURE(OSCompareAndSwap) CRITICAL(OSDecrement) CRITICAL(OSIncrement) CRITICAL(PEARMDebugPanicHook) CRITICAL(PEHaltRestart) CRITICAL(PE_) CRITICAL(SavePanicInfo) CLOSURE(SetIdlePop) CRITICAL(SysChoked) CRITICAL(_ZN15OSMetaClassBase12safeMetaCastEPKS_PK11OSMetaClass) /* OSMetaClassBase::safeMetaCast */ CRITICAL(_ZN16IOPlatformExpert11haltRestartEj) /* IOPlatformExpert::haltRestart */ CRITICAL(_ZN18IODTPlatformExpert11haltRestartEj) /* IODTPlatformExpert::haltRestart */ ARM_ONLY(_ZN8ASPNVRAM4syncEv) /* ASPNVRAM::sync */ CRITICAL(_ZN9IODTNVRAM13savePanicInfoEPhy) /* IODTNVRAM::savePanicInfo */ CRITICAL(_ZN9IOService14newTemperatureElPS_) /* IOService::newTemperature */ CRITICAL(_ZN9IOService26temperatureCriticalForZoneEPS_) /* IOService::temperatureCriticalForZone */ CRITICAL(_ZNK11OSMetaClass13checkMetaCastEPK15OSMetaClassBase) /* OSMetaClass::checkMetaCast */ CRITICAL(_ZNK15OSMetaClassBase8metaCastEPK11OSMetaClass) /* OSMetaClassBase::metaCast */ CRITICAL(_ZNK6OSData14getBytesNoCopyEv) /* Data::getBytesNoCopy, IOHibernateSystemWake path */ KASAN_ONLY(__asan) ARM_ONLY(__div) CLOSURE(__dtrace_probe) KASAN_ONLY(__kasan) ARM_ONLY(__ml) ARM_ONLY(__mod) CRITICAL(__strlcpy_chk) CLOSURE(__thread_ro_circularity_panic) UBSAN_MINIMAL_ONLY(__ubsan) ARM_ONLY(__udiv) ARM_ONLY(__umod) CLOSURE(_copyin) CLOSURE(_copyout) CRITICAL(_disable_preemption) CRITICAL(_enable_preemption) #if SCHED_HYGIENE_DEBUG CLOSURE(abandon_preemption_disable_measurement) #endif CLOSURE(absolutetime_to_microtime) X86_ONLY(acpi_) X86_ONLY(act_machine) CLOSURE(act_set_astbsd) ARM_ONLY(add_saved_state_pc) ARM_ONLY(alternate_debugger_enter) ARM_ONLY(arm_init_idle_cpu) CLOSURE(ast_dtrace_on) CLOSURE(ast_pending) CRITICAL(backtrace_) CRITICAL(bcopy) CLOSURE(clean_dcache) CLOSURE(clean_mmu_dcache) CRITICAL(clock_) X86_ONLY(commpage_) CLOSURE(copyin) CLOSURE(copyout) CRITICAL(cpu_) CLOSURE(current_act) CLOSURE(current_percpu_base) CLOSURE(current_proc) CLOSURE(current_processor) CLOSURE(current_task) CLOSURE(current_task_early) CLOSURE(current_thread) CLOSURE(current_thread_ro) CLOSURE(current_thread_ro_unchecked) CLOSURE(current_uthread) CLOSURE(debug_) X86_ONLY(dsmos_) CLOSURE(dtrace_) CRITICAL(enter_lohandler) CRITICAL(fasttrap_) CRITICAL(fbt_invop) CRITICAL(fbt_perfCallback) CLOSURE(find_user_regs) ARM_ONLY(fleh_) CLOSURE(flush_dcache) ARM_ONLY(flush_mmu_tlb_) CLOSURE(flush_tlb64) CRITICAL(fuword) X86_ONLY(get_active_thread) CLOSURE(get_bsdtask_info) CLOSURE(get_bsdthread_info) CLOSURE(get_machthread) CRITICAL(get_preemption_level) ARM_ONLY(get_saved_state_lr) ARM_ONLY(get_saved_state_reg) ARM_ONLY(get_saved_state_sp) CRITICAL(get_thread_ro) CRITICAL(get_thread_ro_unchecked) CRITICAL(get_threadtask) CRITICAL(get_threadtask_early) ARM_ONLY(get_vfp_enabled) CRITICAL(getminor) CRITICAL(handle_pending_TLB_flushes) CRITICAL(hibernate_) X86_ONLY(hndl_) CRITICAL(hw_) X86_ONLY(idt64) CRITICAL(interrupt) CRITICAL(invalidate_mmu_icache) CRITICAL(is_saved_state32) KASAN_ONLY(kasan) CLOSURE(kauth_cred_get) CLOSURE(kauth_getgid) CLOSURE(kauth_getuid) CRITICAL(kdb_) CRITICAL(kdp_) CRITICAL(kernel_preempt_check) CRITICAL(kernel_trap) CRITICAL(kprintf) CRITICAL(ks_) CLOSURE(kvtophys) X86_ONLY(lapic_) CRITICAL(lo_alltraps) CRITICAL(lock_debugger) CLOSURE(mach_absolute_time) CRITICAL(machine_) X86_ONLY(mapping_) CRITICAL(mca_cpu_alloc) CRITICAL(mca_cpu_init) CLOSURE(memcpy) CLOSURE(memmove) CRITICAL(ml_) CLOSURE(mt_core_snap) CLOSURE(mt_cur_cpu) CLOSURE(mt_fixed_counts) CLOSURE(mt_fixed_counts_internal) CLOSURE(mt_mtc_update_count) CLOSURE(mt_mtc_update_fixed_counts) CRITICAL(nanoseconds_to_absolutetime) CRITICAL(nanotime_to_absolutetime) CRITICAL(no_asts) CLOSURE(other_percpu_base) CRITICAL(ovbcopy) CRITICAL(packA) X86_ONLY(pal_) CLOSURE(panic) CRITICAL(phystokv) CRITICAL(platform_) X86_ONLY(pltrace) X86_ONLY(pmCPU) X86_ONLY(pmKextRegister) X86_ONLY(pmMarkAllCPUsOff) X86_ONLY(pmSafeMode) X86_ONLY(pmTimerRestore) X86_ONLY(pmTimerSave) X86_ONLY(pmUnRegister) X86_ONLY(pmap64_pdpt) CLOSURE(pmap_find_pa) CLOSURE(pmap_find_phys) ARM_ONLY(pmap_get_cpu_data) CLOSURE(pmap_get_mapwindow) CLOSURE(pmap_pde) CLOSURE(pmap_pde_internal0) CLOSURE(pmap_pde_internal1) CLOSURE(pmap_pte) CLOSURE(pmap_pte_internal) CLOSURE(pmap_put_mapwindow) CLOSURE(pmap_valid_page) CLOSURE(pmap_vtophys) X86_ONLY(pms) CRITICAL(power_management_init) CRITICAL(preemption_underflow_panic) CLOSURE(prf) CLOSURE(proc_best_name) CLOSURE(proc_get_task_raw) CLOSURE(proc_is64bit) CLOSURE(proc_require) CLOSURE(proc_task) CRITICAL(rbtrace_bt) CLOSURE(recount_) CRITICAL(register_cpu_setup_func) CRITICAL(ret64_iret) CRITICAL(ret_to_user) CRITICAL(return_to_kernel) CRITICAL(return_to_user) CRITICAL(rtc_) CRITICAL(rtclock_) CRITICAL(saved_state64) CLOSURE(sdt_getargdesc) CRITICAL(sdt_invop) CLOSURE(setPop) ARM_ONLY(set_saved_state_pc) ARM_ONLY(sleh_) CRITICAL(sprlock) CRITICAL(sprunlock) CLOSURE(strlcpy) CRITICAL(strlen) CRITICAL(strncmp) CRITICAL(suword) X86_ONLY(sync_iss_to_iks_unconditionally) CLOSURE(systrace_stub) CRITICAL(t_invop) CLOSURE(task_get_proc_raw) CLOSURE(thread_tid) CLOSURE(timer_grab) ARM_ONLY(timer_state_event) CRITICAL(tmrCvt) CRITICAL(trap_from_kernel) CRITICAL(traptrace_) CRITICAL(tsc_) CRITICAL(uart_putc) CRITICAL(unlock_debugger) CRITICAL(unpackA) CRITICAL(unregister_cpu_setup_func) CRITICAL(uread) CLOSURE(uthread_is64bit) CRITICAL(uwrite) CRITICAL(vstart) CLOSURE(zone_has_index) CLOSURE(zone_id_require) CLOSURE(zone_id_require_panic) CLOSURE(zone_range_contains) CLOSURE(zone_require_panic) CLOSURE(zone_require_ro) CLOSURE(zpercpu_count) }; #define BLACKLIST_COUNT (sizeof(fbt_blacklist)/sizeof(fbt_blacklist[0])) /* * Modules that should not be probed. * * This must be kept in asciibetical order for purposes of bsearch(). */ static const char* fbt_module_blacklist[] = { X86_ONLY(com.apple.driver.AppleACPIEC) X86_ONLY(com.apple.driver.AppleACPIPlatform) ARM_ONLY(com.apple.driver.AppleARMPlatform) X86_ONLY(com.apple.driver.AppleEFI) X86_ONLY(com.apple.driver.AppleIntelCPUPowerManagement) ARM_ONLY(com.apple.driver.AppleInterruptController) X86_ONLY(com.apple.driver.AppleRTC) X86_ONLY(com.apple.iokit.IOACPIFamily) }; #define MODULE_BLACKLIST_COUNT (sizeof(fbt_module_blacklist)/sizeof(fbt_module_blacklist[0])) int ignore_fbt_blacklist = 0; extern int dtrace_kernel_symbol_mode; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcast-qual" static int _cmp(const void *a, const void *b) { const char *v = *(const char **)b; return strncmp((const char *)a, v, strlen(v)); } #pragma clang diagnostic pop /* * Module validation */ bool fbt_module_excluded(struct modctl* ctl) { const char *excluded; ASSERT(!MOD_FBT_DONE(ctl)); if (ctl->mod_address == 0 || ctl->mod_size == 0 || !ctl->mod_loaded) { return true; } if (ignore_fbt_blacklist) { return false; } excluded = bsearch(ctl->mod_modname, fbt_module_blacklist, MODULE_BLACKLIST_COUNT, sizeof(fbt_module_blacklist[0]), _cmp); return excluded; } /* * FBT probe name validation */ bool fbt_excluded(const char* name) { const char *excluded; if (ignore_fbt_blacklist) { return false; } excluded = bsearch(name, fbt_blacklist, BLACKLIST_COUNT, sizeof(name), _cmp ); return excluded; } SYSCTL_DECL(_kern_dtrace); static int sysctl_dtrace_ignore_fbt_blacklist SYSCTL_HANDLER_ARGS { #pragma unused(oidp, arg2) int err; int value = *(int*)arg1; err = sysctl_io_number(req, value, sizeof(value), &value, NULL); if (err) { return err; } if (req->newptr) { if (!(value == 0 || value == 1)) { return ERANGE; } /* * We do not allow setting the blacklist back to on, as we have no way * of knowing if those unsafe probes are still used. * * If we are using kernel symbols, we also do not allow any change, * since the symbols are jettison'd after the first pass. * * We do not need to take any locks here because those symbol modes * are permanent and do not change after boot. */ if (value != 1 || dtrace_kernel_symbol_mode == DTRACE_KERNEL_SYMBOLS_NEVER || dtrace_kernel_symbol_mode == DTRACE_KERNEL_SYMBOLS_ALWAYS_FROM_KERNEL) { return EPERM; } ignore_fbt_blacklist = 1; } return 0; } SYSCTL_PROC(_kern_dtrace, OID_AUTO, ignore_fbt_blacklist, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &ignore_fbt_blacklist, 0, sysctl_dtrace_ignore_fbt_blacklist, "I", "fbt provider ignore blacklist"); void fbt_blacklist_init(void) { PE_parse_boot_argn("IgnoreFBTBlacklist", &ignore_fbt_blacklist, sizeof(ignore_fbt_blacklist)); #if DEBUG || DEVELOPMENT for (size_t i = 1; i < BLACKLIST_COUNT; i++) { if (strcmp(fbt_blacklist[i - 1], fbt_blacklist[i]) > 0) { panic("unordered fbt blacklist %s > %s", fbt_blacklist[i - 1], fbt_blacklist[i]); } } #endif /* DEBUG || DEVELOPMENT */ }