DF-5102 / df5102_nullfree.c
/* * DF-5102 mechanism PoC: apple_fw_probe() (sys/dev/apple/fw/apple_fw.c:107-113) * does: * * product = kgetenv("smbios.system.product"); * biosver = kgetenv("smbios.bios.version"); * ... * kfreeenv(product); * kfreeenv(biosver); * * kgetenv() returns NULL when the variable is absent and the kernel * environment is dynamic (kern_environment.c:228-251; kenv_isdynamic=1 is * the standard post-loader state, kern_environment.c:592). * kfreeenv() unconditionally calls kfree(env, M_KENV) when kenv is dynamic * (kern_environment.c:331-336), and DragonFly's _kfree() panics on NULL: * kern_slaballoc.c:1407-1408 "trying to free NULL pointer". * * This module reproduces the exact sink with a definitely-missing variable, * the same situation apple_fw_probe faces on APPLE-firmware hardware whose * smbios.* environment entries are absent. */ #include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/malloc.h> static int df5102_load(module_t mod, int what, void *arg) { char *product, *biosver; switch (what) { case MOD_LOAD: kprintf("DF5102: enter\n"); /* * Use names that are absent from the kernel environment. * On hardware meeting the finding's precondition (FADT * OemId "APPLE " but no SMBIOS-derived kenv entries), * kgetenv("smbios.system.product") returns NULL exactly * like these absent names do, and apple_fw.c:112-113 then * feeds that NULL to kfreeenv(). */ product = kgetenv("smbios.system.product.absent"); biosver = kgetenv("smbios.bios.version.absent"); kprintf("DF5102: product=%p biosver=%p (NULL == kenv entry absent)\n", product, biosver); if (product == NULL || biosver == NULL) kprintf("DF5102: precondition met, calling kfreeenv as " "apple_fw.c:112-113 does -- expect panic\n"); kfreeenv(product); kfreeenv(biosver); kprintf("DF5102: survived (kenv static or vars present?)\n"); return (0); case MOD_UNLOAD: return (0); default: return (EOPNOTSUPP); } } static moduledata_t df5102_mod = { "df5102b", df5102_load, NULL }; DECLARE_MODULE(df5102b, df5102_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); |