#include <mach-o/loader.h>
#include <libkern/kernel_mach_header.h>
#include <libkern/prelink.h>
+#include <libkern/OSKextLibPrivate.h>
#include <san/kasan.h>
#define KASLR_IOREG_DEBUG 0
kern_return_t
kext_receipt(void **addrp, size_t *sizep)
{
+ kern_return_t ret = KERN_FAILURE;
if (addrp == NULL || sizep == NULL) {
- return KERN_FAILURE;
+ goto finish;
}
kernel_mach_header_t *kc = PE_get_kc_header(KCKindAuxiliary);
if (kc == NULL) {
- return KERN_FAILURE;
+ ret = KERN_MISSING_KC;
+ goto finish;
+ }
+
+ /*
+ * This will be set in early boot once we've successfully checked that
+ * the AuxKC is properly linked against the BootKC. If this isn't set,
+ * and we have a valid AuxKC mach header, then the booter gave us a
+ * bad KC.
+ */
+ if (auxkc_uuid_valid == FALSE) {
+ ret = KERN_INVALID_KC;
+ goto finish;
}
size_t size;
void *addr = getsectdatafromheader(kc,
kReceiptInfoSegment, kAuxKCReceiptSection, &size);
if (addr == NULL) {
- return KERN_FAILURE;
+ ret = KERN_INVALID_KC;
+ goto finish;
}
*addrp = addr;
*sizep = size;
- return KERN_SUCCESS;
+ ret = KERN_SUCCESS;
+
+finish:
+ /*
+ * If we do return success, we'll want to wait for the other side to
+ * call kext_receipt_set_queried themselves, so we can confirm that
+ * it made the roundtrip before allowing third party kexts to load.
+ */
+ if (ret != KERN_SUCCESS) {
+ kext_receipt_set_queried();
+ }
+ return ret;
+}
+
+/*
+ * Returns KERN_FAILURE if the variable was already set.
+ */
+kern_return_t
+kext_receipt_set_queried()
+{
+ return OSKextSetReceiptQueried();
}