/* * Copyright (c) 2022 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef _KERN_EXT_PANICLOG_H_ #define _KERN_EXT_PANICLOG_H_ #include #include #include #define EXT_PANICLOG_ENABLE 1 #define EXT_PANICLOG_VERSION 2 #define MAX_DATA_ID_SIZE 32 #define MAX_EXT_PANICLOG_SIZE 32 * 1024 #define MAX_EXT_PANICLOG_LOGS 100 /* * From the panic log metrics, we estimate that the paniclog takes up * ~15K bytes and other log takes ~1K bytes. This 64K bytes ensures that * we have enough space for other log and nested panics */ #define OTHER_LOG_REQUIRED_SIZE (64 * 1024) #define PANIC_WITH_DATA_UUID "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" #define PANIC_WITH_DATA_MAX_LEN 2048 #define PANIC_WITH_DATA_DATA_ID "Panic with Data Buffer" #define EXTPANICLOG_ENTITLEMENT "com.apple.private.allow-ext_paniclog" /* * These flags are set internally and are passed along with each handle in * the extensible paniclog to be processed by DumpPanic. */ OS_CLOSED_OPTIONS(ext_paniclog_flags, uint32_t, EXT_PANICLOG_FLAGS_NONE = 0x0, EXT_PANICLOG_FLAGS_ADD_SEPARATE_KEY = 0x1); OS_CLOSED_OPTIONS(ext_paniclog_create_options, uint32_t, EXT_PANICLOG_OPTIONS_NONE = 0x0, EXT_PANICLOG_OPTIONS_WITH_BUFFER = 0x1, /* Adds the 'data ID' as a key and handle data as its value directly * in the paniclog instead of within the 'ExtensiblePaniclog' field */ EXT_PANICLOG_OPTIONS_ADD_SEPARATE_KEY = 0x2); #if KERNEL_PRIVATE enum ext_paniclog_test_options { EXT_PANICLOG_TEST_HANDLE_CREATE = 1, EXT_PANICLOG_TEST_SET_ACTIVE_INACTIVE, EXT_PANICLOG_TEST_INSERT_DATA, EXT_PANICLOG_TEST_WRITE_PANIC_DATA, EXT_PANICLOG_TEST_MULTIPLE_HANDLES, EXT_PANICLOG_TEST_MULTIPLE_HANDLES_PANIC, EXT_PANICLOG_TEST_INSERT_DUMMY_HANDLES, EXT_PANICLOG_TEST_INSERT_STRUCT_HANDLES, EXT_PANICLOG_TEST_INSERT_DUMMY_HANDLES_AS_SEPARATE_FIELDS, EXT_PANICLOG_TEST_END, }; typedef struct ext_paniclog_handle { LIST_ENTRY(ext_paniclog_handle) handles; uuid_t uuid; char data_id[MAX_DATA_ID_SIZE]; void * XNU_PTRAUTH_SIGNED_PTR("ext_paniclog_handle.buf_addr") buf_addr; uint32_t max_len; uint32_t used_len; ext_paniclog_create_options_t options; ext_paniclog_flags_t flags; uint8_t active; } ext_paniclog_handle_t; typedef struct ext_paniclog_header { uint32_t len; uuid_t uuid; ext_paniclog_flags_t flags; } ext_paniclog_header_t; void ext_paniclog_init(void); int ext_paniclog_handle_set_active(ext_paniclog_handle_t *handle); int ext_paniclog_handle_set_inactive(ext_paniclog_handle_t *handle); ext_paniclog_handle_t *ext_paniclog_handle_alloc_with_uuid(uuid_t uuid, const char *data_id, uint32_t max_len, ext_paniclog_create_options_t options); ext_paniclog_handle_t *ext_paniclog_handle_alloc_with_buffer(uuid_t uuid, const char *data_id, uint32_t max_len, void * buff, ext_paniclog_create_options_t options); void ext_paniclog_handle_free(ext_paniclog_handle_t *handle); int ext_paniclog_insert_data(ext_paniclog_handle_t *handle, void *addr, uint32_t len); int ext_paniclog_append_data(ext_paniclog_handle_t *handle, void *addr, uint32_t len); void *ext_paniclog_get_buffer(ext_paniclog_handle_t *handle); uint32_t ext_paniclog_write_panicdata(void); void *ext_paniclog_claim_buffer(ext_paniclog_handle_t *handle); int ext_paniclog_yield_buffer(ext_paniclog_handle_t *handle, uint32_t used_len); int ext_paniclog_set_used_len(ext_paniclog_handle_t *handle, uint32_t used_len); bool is_debug_ptr_in_ext_paniclog(void); /* * This function is used to panic and add a buffer data to the extensible paniclog. * uuid here is used to decode the data. */ __abortlike __printflike(5, 6) void panic_with_data(uuid_t uuid, void *addr, uint32_t len, uint64_t debugger_options_mask, const char *format, ...); int ext_paniclog_test_hook(uint32_t option); void ext_paniclog_panic_with_data(uuid_t uuid, void *addr, uint32_t len); #endif // KERNEL_PRIVATE #endif // _KERN_EXT_PANICLOG_H_