google / syzkaller

syzkaller is an unsupervised coverage-guided kernel fuzzer
Apache License 2.0
5.3k stars 1.21k forks source link

MacOS XNU kernel can't be parsed by debug/elf #3469

Open phyonism opened 1 year ago

phyonism commented 1 year ago

HOST : osx 12.6 TARGET : macOS 11.5

run >> ~/115/bin/syz-manager -config=/root/115/syzkaller.cfg result >> SYZFATAL: failed to open ELF file /Users/user/115/obj/kernel.kasan: bad magic number '[207 250 237 254]' in record at byte 0x0

What's Happen? Help Me

dvyukov commented 1 year ago

Please re-send to the mailing list with full repro instructions.

retX0 commented 1 year ago

I checked the source code, it seem like it use method ctorBSD for ctorDarwin, and the ctorBSD method will make the kernel.kasan as elf file, so it crashed with message [FATAL] failed to open ELF file /Users/qaz/xnu_132/obj/kernel.kasan: bad magic number '[207 250 237 254]' in record at byte 0x0, How should I make it work with macos ?

a-nogikh commented 1 year ago

Cc @HerrSpace

retX0 commented 1 year ago

the config file

{
    "target": "darwin/amd64",
    "http": "127.0.0.1:56741",
    "sshkey": "/Users/qaz/.ssh/id_rsa.pub",
    "workdir": "/Users/qaz/xnu_132",
    "kernel_obj": "/Users/qaz/xnu_132/obj/",
    "kernel_src": "/Users/qaz/xnu_132/src/",
    "syzkaller": "/Users/qaz/syzkaller",
    "procs": 2,
    "type": "qemu",
    "cover": true,
    "image": "/Users/qaz/Developer/fuzz-xnu/mac_hdd.qcow",
    "vm": {
        "count": 1,
        "cpu": 1,
        "mem": 4096,
        "efi_code_device": "/usr/local/share/OVMF/OVMF_CODE.fd",
        "efi_vars_device": "/usr/local/share/OVMF/OVMF_VARS.fd",
        "apple_smc_osk": "ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc"
    }
}
HerrSpace commented 1 year ago

I reproduced this issue on head and narrowed the cause down to this commit, where we switched from symbolising reports via nm to golangs debug/elf. As the xnu kernel is a macho binary, this of course doesn't work.

Use d236a457274375e5273ac4e958722659929c469f and older for macos for now.

Previous report

retX0 commented 1 year ago

Now it works, and the xnu updated the ksancov.h path and struct ksancov_trace members with commit e6231be The path changed from san/ksancov.h to san/tools/ksancov.h before this commit


struct ksancov_trace {
    /* userspace R/O fields */
    union {
        struct ksancov_header hdr;
        struct {
            uint32_t magic;
            _Atomic uint32_t enabled;
        };
    };

    uintptr_t offset; /* pc entries relative to this */
    uint32_t maxpcs;
    _Atomic uint32_t head;
    uint32_t pcs[];
};

after the commit

typedef struct ksancov_trace {
    ksancov_header_t kt_hdr;         /* header (must be always first) */
    uintptr_t        kt_offset;      /* All recorded PCs are relateive to this offset. */
    uint32_t         kt_maxent;      /* Maximum entries in this shared buffer. */
    _Atomic uint32_t kt_head;        /* Pointer to the first unused element. */
    uint64_t         kt_entries[];   /* Trace entries in this buffer. */
} ksancov_trace_t;

Maybe the source code need to change to adjust for this commit, I just copy the san/tools/ksancov.h to the san/ksancov.h and change the executor/executor_darwin.h. like this

diff --git a/executor/executor_darwin.h b/executor/executor_darwin.h
index c16691663..6e5c990e8 100644
--- a/executor/executor_darwin.h
+++ b/executor/executor_darwin.h
@@ -113,8 +113,8 @@ static void cover_collect(cover_t* cov)
 {
    struct ksancov_trace* trace = (struct ksancov_trace*)cov->data;
    cov->size = ksancov_trace_head(trace);
-   cov->data_offset = ((int64_t) & (trace->pcs)) - ((int64_t)(cov->data));
-   cov->pc_offset = trace->offset;
+   cov->data_offset = ((int64_t) & (trace->kt_entries)) - ((int64_t)(cov->data));
+   cov->pc_offset = trace->kt_offset;
 }

 static bool use_cover_edges(uint64 pc)