diff --git a/.gitignore b/.gitignore index 0c8386b9..7e1031c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.scannerwork DerivedData Lilu.kext xcuserdata diff --git a/Changelog.md b/Changelog.md index 4801adc5..56a18d8a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Lilu Changelog #### v1.3.0 - Fixed a rare kernel panic on user patch failure +- Removed unimplemented `genPlatformKey` API #### v1.2.9 - Added `kern_atomic.hpp` header to support atomic types with old Clang diff --git a/Lilu/Headers/kern_crypto.hpp b/Lilu/Headers/kern_crypto.hpp index d8fc5943..b212d123 100644 --- a/Lilu/Headers/kern_crypto.hpp +++ b/Lilu/Headers/kern_crypto.hpp @@ -51,23 +51,7 @@ namespace Crypto { while (len--) *vptr++ = '\0'; } - - /** - * Generates a platform specific encryption key to be used for later encryption/decryption. - * Use very cautiously, this generates a key that should be reproducible on the same hardware. - * This means that the key is NOT meant protect the data from decryption on the same machine, - * but it only tries to circumvent cases when some blobs containing sensitive information - * (e.g. nvram dumps) were accidentally shared. - * - * This is currently UNIMPLEMENTED - * - * @param seed prefixed data blob used for key generation - * @param size seed size - * - * @return generated key of at least BlockSize bits long (must be freeded by Buffer::deleter) or nullptr - */ - EXPORT uint8_t *genPlatformKey(const uint8_t *seed=nullptr, uint32_t size=0); - + /** * Generates cryptographically secure encryption key (from /dev/random) * @@ -78,7 +62,7 @@ namespace Crypto { /** * Encrypts data of specified size and stores in Encrypted format * - * @param key encryption key returned by genUniqueKey, genPlatformKey (default if null) + * @param key encryption key returned by genUniqueKey * @param src source data * @param size data size, encrypted size is returned on success * @@ -89,7 +73,7 @@ namespace Crypto { /** * Decrypts data of specified size stored in Encrypted format * - * @param key encryption key returned by genUniqueKey, genPlatformKey (default if null) + * @param key encryption key returned by genUniqueKey * @param src source data * @param size data size, decrypted size is returned on success * diff --git a/Lilu/Headers/kern_iokit.hpp b/Lilu/Headers/kern_iokit.hpp index ea7d79b3..72091781 100644 --- a/Lilu/Headers/kern_iokit.hpp +++ b/Lilu/Headers/kern_iokit.hpp @@ -18,7 +18,7 @@ namespace WIOKit { /** - * AppleHDAEngine::getLocation teaches us to use while(1) when talking to IOReg + * AppleHDAEngine::getLocation teaches us to use loop infinitely when talking to IOReg * This feels mad and insane, since it may prevent the system from booting. * Although this had never happened, we will use a far bigger fail-safe stop value. */ diff --git a/Lilu/Headers/kern_patcher.hpp b/Lilu/Headers/kern_patcher.hpp index 8a7c9fa3..9529584b 100644 --- a/Lilu/Headers/kern_patcher.hpp +++ b/Lilu/Headers/kern_patcher.hpp @@ -291,7 +291,7 @@ class KernelPatcher { * * @param patch patch to apply * @param startingAddress start with this address (or kext/kernel lowest address) - * @param maxSize maximum size to look for (or kext/kernel max size) + * @param maxSize maximum size to lookup (or kext/kernel max size) */ EXPORT void applyLookupPatch(const LookupPatch *patch, uint8_t *startingAddress, size_t maxSize); #endif /* LILU_KEXTPATCH_SUPPORT */ diff --git a/Lilu/Headers/kern_user.hpp b/Lilu/Headers/kern_user.hpp index ae824ce7..00be5a30 100644 --- a/Lilu/Headers/kern_user.hpp +++ b/Lilu/Headers/kern_user.hpp @@ -483,12 +483,10 @@ class UserPatcher { * @param action passed action, we only need KAUTH_FILEOP_EXEC * @param arg0 pointer to vnode (vnode *) for executable * @param arg1 pointer to path (char *) to executable - * @param arg2 unused - * @param arg3 unsed * * @return 0 to allow further execution */ - static int execListener(kauth_cred_t credential, void *idata, kauth_action_t action, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3); + static int execListener(kauth_cred_t /* credential */, void *idata, kauth_action_t action, uintptr_t /* arg0 */, uintptr_t arg1, uintptr_t, uintptr_t); /** * Unrestricted vm_protect, that takes care of Mojave codesign limitations for everyone's good. diff --git a/Lilu/Headers/kern_util.hpp b/Lilu/Headers/kern_util.hpp index 8ee05c20..6437d70b 100644 --- a/Lilu/Headers/kern_util.hpp +++ b/Lilu/Headers/kern_util.hpp @@ -672,7 +672,7 @@ class ThreadLocal { * Use this deleter when storing scalar types */ template -static void emptyDeleter(T) {} +static void emptyDeleter(T) { /* no dynamic alloc */ } template , void (*deleterY)(Y)=emptyDeleter> struct ppair { @@ -761,13 +761,13 @@ class evector { * * @return elements ptr or null */ - template + template T *reserve(size_t num) { if (rsvd < num) { - T *nPtr = static_cast(kern_os_realloc(ptr, Mul * num * sizeof(T))); + T *nPtr = static_cast(kern_os_realloc(ptr, MUL * num * sizeof(T))); if (nPtr) { ptr = nPtr; - rsvd = Mul * num; + rsvd = MUL * num; } else { return nullptr; } @@ -804,9 +804,9 @@ class evector { * * @return true on success */ - template + template bool push_back(T &element) { - if (reserve(cnt+1)) { + if (reserve(cnt+1)) { ptr[cnt] = element; cnt++; return true; @@ -823,9 +823,9 @@ class evector { * * @return true on success */ - template + template bool push_back(T &&element) { - if (reserve(cnt+1)) { + if (reserve(cnt+1)) { ptr[cnt] = element; cnt++; return true; @@ -891,9 +891,9 @@ inline constexpr char getBuildMonth() { return "11"[i]; case ' ceD': return "12"[i]; + default: + return '0'; } - - return '0'; } template diff --git a/Lilu/PrivateHeaders/kern_config.hpp b/Lilu/PrivateHeaders/kern_config.hpp index 525e336a..e069fda4 100644 --- a/Lilu/PrivateHeaders/kern_config.hpp +++ b/Lilu/PrivateHeaders/kern_config.hpp @@ -86,7 +86,7 @@ class Configuration { * * @return 0 on success */ - static int policyCredCheckLabelUpdateExecve(kauth_cred_t old, vnode_t vp, ...); + static int policyCredCheckLabelUpdateExecve(kauth_cred_t, vnode_t, ...); /** * TrustedBSD policy called before remounting @@ -95,7 +95,7 @@ class Configuration { * @param mp mount point * @param mlabel mount point label */ - static int policyCheckRemount(kauth_cred_t cred, mount *mp, label *mlabel); + static int policyCheckRemount(kauth_cred_t, mount *, label *); /** * TrustedBSD policy options diff --git a/Lilu/PrivateHeaders/kern_patcher.hpp b/Lilu/PrivateHeaders/kern_patcher.hpp index 67b996dc..15659790 100644 --- a/Lilu/PrivateHeaders/kern_patcher.hpp +++ b/Lilu/PrivateHeaders/kern_patcher.hpp @@ -42,8 +42,7 @@ namespace Patch { template static void writeType(mach_vm_address_t addr, T value) { - // Completely forbidden to IOLog with disabled interrupts as of High Sierra - // DBGLOG("private @ writing to %X value of %lu which is %X", static_cast(addr), sizeof(T), (unsigned int)value); + // It is completely forbidden to IOLog with disabled interrupts as of High Sierra, yet DBGLOG may bypass it if needed. *reinterpret_cast(addr) = value; } @@ -66,11 +65,11 @@ namespace Patch { }; union All { - All(P &&v) : u8(v) {} - All(P &&v) : u16(v) {} - All(P &&v) : u32(v) {} - All(P &&v) : u64(v) {} - All(P &&v) : u128(v) {} + explicit All(P &&v) : u8(v) {} + explicit All(P &&v) : u16(v) {} + explicit All(P &&v) : u32(v) {} + explicit All(P &&v) : u64(v) {} + explicit All(P &&v) : u128(v) {} P u8; P u16; diff --git a/Lilu/Sources/kern_api.cpp b/Lilu/Sources/kern_api.cpp index 9d6f67bc..95f39b9e 100644 --- a/Lilu/Sources/kern_api.cpp +++ b/Lilu/Sources/kern_api.cpp @@ -119,7 +119,7 @@ LiluAPI::Error LiluAPI::onPatcherLoad(t_patcherLoaded callback, void *user) { if (!patcherLoadedCallbacks.push_back<2>(pcall)) { SYSLOG("api", "failed to store stored_pair"); - pcall->deleter(pcall); + stored_pair::deleter(pcall); return Error::MemoryError; } @@ -141,7 +141,7 @@ LiluAPI::Error LiluAPI::onKextLoad(KernelPatcher::KextInfo *infos, size_t num, t if (!kextLoadedCallbacks.push_back<4>(pcall)) { SYSLOG("api", "failed to store stored_pair"); - pcall->deleter(pcall); + stored_pair::deleter(pcall); return Error::MemoryError; } } @@ -160,7 +160,7 @@ LiluAPI::Error LiluAPI::onKextLoad(KernelPatcher::KextInfo *infos, size_t num, t if (!storedKexts.push_back<4>(pkext)) { SYSLOG("api", "failed to store stored_pair"); - pkext->deleter(pkext); + stored_pair::deleter(pkext); return Error::MemoryError; } } @@ -169,10 +169,7 @@ LiluAPI::Error LiluAPI::onKextLoad(KernelPatcher::KextInfo *infos, size_t num, t } LiluAPI::Error LiluAPI::onProcLoad(UserPatcher::ProcInfo *infos, size_t num, UserPatcher::t_BinaryLoaded callback, void *user, UserPatcher::BinaryModInfo *mods, size_t modnum) { - // It seems to partially work - // Offer no support for user patcher before 10.9 - //if (getKernelVersion() <= KernelVersion::MountainLion) - // return Error::IncompatibleOS; + // We do not officially support user patcher prior to 10.9, yet it seems to partially work // Store the callbacks if (callback) { @@ -188,7 +185,7 @@ LiluAPI::Error LiluAPI::onProcLoad(UserPatcher::ProcInfo *infos, size_t num, Use if (!binaryLoadedCallbacks.push_back<2>(pcall)) { SYSLOG("api", "failed to store stored_pair"); - pcall->deleter(pcall); + stored_pair::deleter(pcall); return Error::MemoryError; } } @@ -226,7 +223,7 @@ LiluAPI::Error LiluAPI::onEntitlementRequest(t_entitlementRequested callback, vo if (!entitlementRequestedCallbacks.push_back<2>(ecall)) { SYSLOG("api", "failed to store stored_pair"); - ecall->deleter(ecall); + stored_pair::deleter(ecall); return Error::MemoryError; } diff --git a/Lilu/Sources/kern_compression.cpp b/Lilu/Sources/kern_compression.cpp index 4c2526a2..a2cbe8c2 100644 --- a/Lilu/Sources/kern_compression.cpp +++ b/Lilu/Sources/kern_compression.cpp @@ -345,13 +345,10 @@ uint8_t *Compression::compress(uint32_t compression, uint32_t &dstlen, const uin auto compressedBuf = buffer ? buffer : Buffer::create(dstlen); if (compressedBuf) { uint8_t *endptr = nullptr; - switch (compression) { - case ModeLZSS: - endptr = compress_lzss(compressedBuf, dstlen, src, srclen); - break; - default: - SYSLOG("comp", "unsupported compression format %X", compression); - } + if (compression == ModeLZSS) + endptr = compress_lzss(compressedBuf, dstlen, src, srclen); + else + SYSLOG("comp", "unsupported compression format %X", compression); if (endptr) { dstlen = static_cast(endptr-compressedBuf); diff --git a/Lilu/Sources/kern_cpu.cpp b/Lilu/Sources/kern_cpu.cpp index 0a2a17a4..0bc5dacf 100644 --- a/Lilu/Sources/kern_cpu.cpp +++ b/Lilu/Sources/kern_cpu.cpp @@ -11,7 +11,7 @@ #include extern "C" { - #include +#include } static CPUInfo::CpuVendor currentVendor = CPUInfo::CpuVendor::Unknown; diff --git a/Lilu/Sources/kern_crypto.cpp b/Lilu/Sources/kern_crypto.cpp index 1aaf1dc8..bdae3421 100644 --- a/Lilu/Sources/kern_crypto.cpp +++ b/Lilu/Sources/kern_crypto.cpp @@ -15,12 +15,6 @@ static_assert(Crypto::BlockSize == AES_BLOCK_SIZE, "Invalid block size!"); static_assert(Crypto::BlockSize <= SHA256_BLOCK_SIZE || Crypto::MinDigestSize > SHA256_BLOCK_SIZE, "Hash function does not provide enough data"); -uint8_t *Crypto::genPlatformKey(const uint8_t *seed, uint32_t size) { - SYSLOG("crypto", "genPlatformKey is currently unimplemented"); - - return nullptr; -} - uint8_t *Crypto::genUniqueKey(uint32_t size) { if (size < BlockSize) { SYSLOG("crypto", "invalid key size %u", size); @@ -44,9 +38,8 @@ uint8_t *Crypto::encrypt(const uint8_t *key, const uint8_t *src, uint32_t &size) return nullptr; } - uint8_t *pkey = nullptr; - if (!key && !(pkey = genPlatformKey())) { - SYSLOG("crypto", "encrypt unable to obtain platform key"); + if (!key) { + SYSLOG("crypto", "encrypt unable to obtain encryption key"); return nullptr; } @@ -72,7 +65,7 @@ uint8_t *Crypto::encrypt(const uint8_t *key, const uint8_t *src, uint32_t &size) read_random(enc->iv, BlockSize); aes_encrypt_ctx ctx; - auto ret = aes_encrypt_key(key ? key : pkey, BlockSize, &ctx); + auto ret = aes_encrypt_key(key, BlockSize, &ctx); if (ret == aes_good) { ret = aes_encrypt_cbc(dataBuf, enc->iv, encSize / BlockSize, enc->buf, &ctx); if (ret == aes_good) @@ -98,12 +91,7 @@ uint8_t *Crypto::encrypt(const uint8_t *key, const uint8_t *src, uint32_t &size) } else { SYSLOG("crypto", "encrypt failed to allocate src buffer of %u bytes", encSize); } - - if (pkey) { - zeroMemory(BlockSize, pkey); - Buffer::deleter(pkey); - } - + return encBuf; } @@ -113,9 +101,8 @@ uint8_t *Crypto::decrypt(const uint8_t *key, const uint8_t *src, uint32_t &size) return nullptr; } - uint8_t *pkey = nullptr; - if (!key && !(pkey = genPlatformKey())) { - SYSLOG("crypto", "decrypt unable to obtain platform key"); + if (!key) { + SYSLOG("crypto", "decrypt unable to obtain decryption key"); return nullptr; } @@ -124,7 +111,7 @@ uint8_t *Crypto::decrypt(const uint8_t *key, const uint8_t *src, uint32_t &size) auto decBuf = Buffer::create(size); if (decBuf) { aes_decrypt_ctx ctx; - auto ret = aes_decrypt_key(key ? key : pkey, BlockSize, &ctx); + auto ret = aes_decrypt_key(key, BlockSize, &ctx); if (ret == aes_good) { auto enc = reinterpret_cast(src); ret = aes_decrypt_cbc(enc->buf, enc->iv, size / BlockSize, decBuf, &ctx); @@ -153,12 +140,7 @@ uint8_t *Crypto::decrypt(const uint8_t *key, const uint8_t *src, uint32_t &size) decBuf = nullptr; } } - - if (pkey) { - zeroMemory(BlockSize, pkey); - Buffer::deleter(pkey); - } - + return decBuf; } diff --git a/Lilu/Sources/kern_devinfo.cpp b/Lilu/Sources/kern_devinfo.cpp index c2d644f0..807162e9 100644 --- a/Lilu/Sources/kern_devinfo.cpp +++ b/Lilu/Sources/kern_devinfo.cpp @@ -272,10 +272,8 @@ void DeviceInfo::grabDevicesFromPciRoot(IORegistryEntry *pciRoot) { pciiterator->release(); - if (v.video) { - if (!videoExternal.push_back(v)) - SYSLOG("dev", "failed to push video gpu"); - } + if (v.video && !videoExternal.push_back(v)) + SYSLOG("dev", "failed to push video gpu"); } } } diff --git a/Lilu/Sources/kern_efi.cpp b/Lilu/Sources/kern_efi.cpp index 16324a7b..d0bc83ad 100644 --- a/Lilu/Sources/kern_efi.cpp +++ b/Lilu/Sources/kern_efi.cpp @@ -88,7 +88,7 @@ void EfiRuntimeServices::activate() { } EfiRuntimeServices *EfiRuntimeServices::get(bool lock) { - //FIXME: To be completely honest we should lock gAppleEFIRuntimeLock here, but it is not public :/ + //TODO: To be completely honest we should lock gAppleEFIRuntimeLock here, but it is not public :/ // The current approach is that EfiRuntimeServices are only allowed to be used before AppleEFIRuntime is loaded. if (instance && lock) IOLockLock(instance->accessLock); diff --git a/Lilu/Sources/kern_iokit.cpp b/Lilu/Sources/kern_iokit.cpp index 5df92cf3..e36a84a8 100644 --- a/Lilu/Sources/kern_iokit.cpp +++ b/Lilu/Sources/kern_iokit.cpp @@ -50,8 +50,7 @@ namespace WIOKit { return read8(service, space, reg); case 16: return read16(service, space, reg); - case 32: - default: + default: /* assume 32-bit otherwise */ return read32(service, space, reg); } } @@ -191,7 +190,6 @@ namespace WIOKit { while ((res = OSDynamicCast(IORegistryEntry, iterator->getNextObject())) != nullptr) { const char *resname = res->getName(); - //DBGLOG("iokit", "iterating over %s", resname); if (resname && !strncmp(prefix, resname, len)) { found = proc ? proc(user, res) : true; if (found) { @@ -268,11 +266,11 @@ namespace WIOKit { DBGLOG("iokit", "fixing compatible to have %s", name); lilu_os_memcpy(&compatibleBuf[0], compatibleStr, compatibleSz); lilu_os_memcpy(&compatibleBuf[compatibleSz], name, nameSize); - auto compatibleProp = OSData::withBytes(compatibleBuf, compatibleBufSz); + auto compatibleData = OSData::withBytes(compatibleBuf, compatibleBufSz); Buffer::deleter(compatibleBuf); - if (compatibleProp) { - entry->setProperty("compatible", compatibleProp); - compatibleProp->release(); + if (compatibleData) { + entry->setProperty("compatible", compatibleData); + compatibleData->release(); return true; } else { SYSLOG("iokit", "compatible property memory alloc failure %u for %s", compatibleBufSz, name); diff --git a/Lilu/Sources/kern_mach.cpp b/Lilu/Sources/kern_mach.cpp index aded4fef..15f9b08b 100644 --- a/Lilu/Sources/kern_mach.cpp +++ b/Lilu/Sources/kern_mach.cpp @@ -39,7 +39,7 @@ kern_return_t MachInfo::init(const char * const paths[], size_t num, MachInfo *p // Check if we have a proper credential, prevents a race-condition panic on 10.11.4 Beta // When calling kauth_cred_get() for the current_thread. - //FIXME: This needs a better solution... + //TODO: Try to find a better solution... if (!kernproc || !current_thread() || !vfs_context_current() || !vfs_context_ucred(vfs_context_current())) { SYSLOG("mach", "current context has no credential, it's too early"); return error; @@ -48,7 +48,7 @@ kern_return_t MachInfo::init(const char * const paths[], size_t num, MachInfo *p // Attempt to load directly from the filesystem (void)fsfallback; - //FIXME: There still is a chance of booting with outdated prelink cache, so we cannot optimise it currently. + //TODO: There still is a chance of booting with outdated prelink cache, so we cannot optimise it currently. // We are fine to detect prelinked usage (#27), but prelinked may not contain certain kexts and even more // it may contain different kexts (#30). In theory we should be able to compare _PrelinkInterfaceUUID with // LC_UUID like OSKext::registerIdentifier does, but this would overcomplicate the logic with no practical @@ -206,13 +206,14 @@ mach_vm_address_t MachInfo::findKernelBase() { auto segmentCommand = reinterpret_cast(tmp + sizeof(mach_header_64)); if (!strncmp(segmentCommand->segname, "__TEXT", sizeof(segmentCommand->segname))) { DBGLOG("mach", "found kernel mach-o header address at %llx", tmp); - return tmp; + break; } } tmp -= KASLRAlignment; } - return 0; + + return tmp; } bool MachInfo::setInterrupts(bool enable) { @@ -657,16 +658,12 @@ void MachInfo::updatePrelinkInfo() { } else { SYSLOG("mach", "unable to find prelink info section"); } - } else { - //DBGLOG("mach", "dict present %d kernel %d buf present %d", prelink_dict != nullptr, isKernel, file_buf != nullptr); } } uint8_t *MachInfo::findImage(const char *identifier, uint32_t &imageSize, mach_vm_address_t &slide, bool &missing) { updatePrelinkInfo(); - //DBGLOG("mach", "looking up %s kext in prelink", identifier); - if (prelink_dict) { static OSArray *imageArr = nullptr; static uint32_t imageNum = 0; @@ -700,8 +697,6 @@ uint8_t *MachInfo::findImage(const char *identifier, uint32_t &imageSize, mach_v SYSLOG("mach", "unable to obtain addr and size for %s at %u of %u prelink", identifier, i, imageNum); return nullptr; - } else { - //DBGLOG("mach", "prelink %u of %u contains %s id", i, imageNum, imageID ? imageID->getCStringNoCopy() : "(null)"); } } else { SYSLOG("mach", "prelink %u of %u is not a dictionary", i, imageNum); diff --git a/Lilu/Sources/kern_nvram.cpp b/Lilu/Sources/kern_nvram.cpp index fbd21c45..372f659a 100644 --- a/Lilu/Sources/kern_nvram.cpp +++ b/Lilu/Sources/kern_nvram.cpp @@ -66,13 +66,13 @@ uint8_t *NVStorage::read(const char *key, uint32_t &size, uint8_t opts, const ui payloadBuf += sizeof(Header); payloadSize -= sizeof(Header); - auto replacePayload = [&payloadBuf, &payloadAlloc, opts](const uint8_t *buf, uint32_t orgSize) { + auto replacePayload = [&payloadBuf, &payloadAlloc, opts](const uint8_t *newBuf, uint32_t orgSize) { if (payloadAlloc) { auto buf = const_cast(payloadBuf); if (opts & OptSensitive) Crypto::zeroMemory(orgSize, buf); Buffer::deleter(buf); } - payloadBuf = buf; + payloadBuf = newBuf; payloadAlloc = true; }; @@ -156,13 +156,13 @@ bool NVStorage::write(const char *key, const uint8_t *src, uint32_t size, uint8_ auto payloadBuf = src; auto payloadSize = size; - auto replacePayload = [&payloadBuf, &payloadAlloc, opts](const uint8_t *buf, uint32_t orgSize) { + auto replacePayload = [&payloadBuf, &payloadAlloc, opts](const uint8_t *newBuf, uint32_t orgSize) { if (payloadAlloc) { auto buf = const_cast(payloadBuf); if (opts & OptSensitive) Crypto::zeroMemory(orgSize, buf); Buffer::deleter(buf); } - payloadBuf = buf; + payloadBuf = newBuf; payloadAlloc = true; }; @@ -295,8 +295,7 @@ uint8_t *NVStorage::compress(const uint8_t *src, uint32_t &size, bool sensitive) *reinterpret_cast(buf) = size; DBGLOG("nvram", "compress saves dstSize = %u, srcSize = %u", dstSize, size); if (Compression::compress(Compression::ModeLZSS, dstSize, src, size, buf + sizeof(uint32_t))) { - // size was updated by compress - //Buffer::resize(buf, size + sizeof(uint32_t)); + // Buffer was already resized by compress size = dstSize + sizeof(uint32_t); DBGLOG("nvram", "compress result size = %u", size); Buffer::resize(buf, size); diff --git a/Lilu/Sources/kern_patcher.cpp b/Lilu/Sources/kern_patcher.cpp index c00a6b38..2a9fe9cb 100644 --- a/Lilu/Sources/kern_patcher.cpp +++ b/Lilu/Sources/kern_patcher.cpp @@ -13,6 +13,8 @@ #include +#include + #ifdef LILU_KEXTPATCH_SUPPORT static KernelPatcher *that {nullptr}; static SInt32 updateSummariesEntryCount; @@ -20,8 +22,6 @@ static SInt32 updateSummariesEntryCount; IOSimpleLock *KernelPatcher::kernelWriteLock {nullptr}; -#include - KernelPatcher::Error KernelPatcher::getError() { return code; } @@ -70,11 +70,11 @@ void KernelPatcher::init() { void KernelPatcher::deinit() { // Remove the patches if (kinfos.size() > 0) { - if (kinfos[KernelID]->setKernelWriting(true, kernelWriteLock) == KERN_SUCCESS) { + if (MachInfo::setKernelWriting(true, kernelWriteLock) == KERN_SUCCESS) { for (size_t i = 0, n = kpatches.size(); i < n; i++) { kpatches[i]->restore(); } - kinfos[KernelID]->setKernelWriting(false, kernelWriteLock); + MachInfo::setKernelWriting(false, kernelWriteLock); } else { SYSLOG("patcher", "failed to change kernel protection at patch removal"); } @@ -307,7 +307,7 @@ void KernelPatcher::applyLookupPatch(const LookupPatch *patch, uint8_t *starting size_t changes {0}; - if (kinfo->setKernelWriting(true, kernelWriteLock) != KERN_SUCCESS) { + if (MachInfo::setKernelWriting(true, kernelWriteLock) != KERN_SUCCESS) { SYSLOG("patcher", "lookup patching failed to write to kernel"); code = Error::MemoryProtection; return; @@ -324,7 +324,7 @@ void KernelPatcher::applyLookupPatch(const LookupPatch *patch, uint8_t *starting } } - if (kinfo->setKernelWriting(false, kernelWriteLock) != KERN_SUCCESS) { + if (MachInfo::setKernelWriting(false, kernelWriteLock) != KERN_SUCCESS) { SYSLOG("patcher", "lookup patching failed to disable kernel writing"); code = Error::MemoryProtection; return; @@ -388,7 +388,7 @@ mach_vm_address_t KernelPatcher::routeFunction(mach_vm_address_t from, mach_vm_a return EINVAL; } - if (kernelRoute && kinfos[KernelID]->setKernelWriting(true, kernelWriteLock) != KERN_SUCCESS) { + if (kernelRoute && MachInfo::setKernelWriting(true, kernelWriteLock) != KERN_SUCCESS) { SYSLOG("patcher", "cannot change kernel memory protection"); code = Error::MemoryProtection; Patch::deleter(opcode); Patch::deleter(argument); @@ -401,7 +401,7 @@ mach_vm_address_t KernelPatcher::routeFunction(mach_vm_address_t from, mach_vm_a if (disp) disp->patch(); if (kernelRoute) { - kinfos[KernelID]->setKernelWriting(false, kernelWriteLock); + MachInfo::setKernelWriting(false, kernelWriteLock); if (revertible) { auto oidx = kpatches.push_back<4>(opcode); @@ -426,10 +426,10 @@ mach_vm_address_t KernelPatcher::routeFunction(mach_vm_address_t from, mach_vm_a mach_vm_address_t KernelPatcher::routeBlock(mach_vm_address_t from, const uint8_t *opcodes, size_t opnum, bool buildWrapper, bool kernelRoute) { // Simply overwrite the function in the easiest case if (!buildWrapper) { - if (!kernelRoute || kinfos[KernelID]->setKernelWriting(true, kernelWriteLock) == KERN_SUCCESS) { + if (!kernelRoute || MachInfo::setKernelWriting(true, kernelWriteLock) == KERN_SUCCESS) { lilu_os_memcpy(reinterpret_cast(from), opcodes, opnum); if (kernelRoute) - kinfos[KernelID]->setKernelWriting(false, kernelWriteLock); + MachInfo::setKernelWriting(false, kernelWriteLock); } else { SYSLOG("patcher", "block overwrite failed to change protection"); code = Error::MemoryProtection; @@ -506,7 +506,7 @@ uint8_t KernelPatcher::tempExecutableMemory[TempExecutableMemorySize] __attribut mach_vm_address_t KernelPatcher::createTrampoline(mach_vm_address_t func, size_t min, const uint8_t *opcodes, size_t opnum) { // Doing it earlier to workaround stack corruption due to a possible 10.12 bug. // Otherwise in rare cases there will be random KPs with corrupted stack data. - if (kinfos[KernelID]->setKernelWriting(true, kernelWriteLock) != KERN_SUCCESS) { + if (MachInfo::setKernelWriting(true, kernelWriteLock) != KERN_SUCCESS) { SYSLOG("patcher", "failed to set executable permissions"); code = Error::MemoryProtection; return 0; @@ -516,7 +516,7 @@ mach_vm_address_t KernelPatcher::createTrampoline(mach_vm_address_t func, size_t size_t off = Disassembler::quickInstructionSize(func, min); if (!off || off > PAGE_SIZE - LongJump) { - kinfos[KernelID]->setKernelWriting(false, kernelWriteLock); + MachInfo::setKernelWriting(false, kernelWriteLock); SYSLOG("patcher", "unsupported destination offset %lu", off); code = Error::DisasmFailure; return 0; @@ -527,7 +527,7 @@ mach_vm_address_t KernelPatcher::createTrampoline(mach_vm_address_t func, size_t tempExecutableMemoryOff += off + LongJump + opnum; if (tempExecutableMemoryOff >= TempExecutableMemorySize) { - kinfos[KernelID]->setKernelWriting(false, kernelWriteLock); + MachInfo::setKernelWriting(false, kernelWriteLock); SYSLOG("patcher", "not enough executable memory requested %ld have %lu", tempExecutableMemoryOff+1, TempExecutableMemorySize); code = Error::DisasmFailure; } else { @@ -538,7 +538,7 @@ mach_vm_address_t KernelPatcher::createTrampoline(mach_vm_address_t func, size_t // Copy the prologue, assuming it is PIC lilu_os_memcpy(tempDataPtr + opnum, reinterpret_cast(func), off); - kinfos[KernelID]->setKernelWriting(false, kernelWriteLock); + MachInfo::setKernelWriting(false, kernelWriteLock); // Add a jump routeFunction(reinterpret_cast(tempDataPtr+opnum+off), func+off, false, true, false); @@ -562,9 +562,9 @@ void KernelPatcher::onKextSummariesUpdated() { // // For this reason on 10.12 and above the outer function is routed, and so far it // seems to cause fewer issues. Regarding syncing: - // - the only place modifying gLoadedKextSummaries is updateLoadedKextSummaries; - // - updateLoadedKextSummaries is called from load/unload separately; - // - sKextSummariesLock is not exported or visible. + // - the only place modifying gLoadedKextSummaries is updateLoadedKextSummaries + // - updateLoadedKextSummaries is called from load/unload separately + // - sKextSummariesLock is not exported or visible // As a result no syncing should be necessary but there are guards for future // changes and in case of any misunderstanding. @@ -625,21 +625,19 @@ void KernelPatcher::processAlreadyLoadedKexts(OSKextLoadedKextSummary *summaries auto curr = summaries[i]; for (size_t j = 0; j < khandlers.size(); j++) { auto handler = khandlers[j]; - if (handler->loaded) { - if (!strncmp(handler->id, curr.name, KMOD_MAX_NAME)) { - DBGLOG("patcher", "discovered the right kext %s at " PRIKADDR ", invoking handler", curr.name, CASTKADDR(curr.address)); - if (!kinfos[handler->index]->isCurrentBinary(curr.address)) { - SYSLOG("patcher", "uuid mismatch for %s at " PRIKADDR ", ignoring", curr.name, CASTKADDR(curr.address)); - continue; - } - handler->address = curr.address; - handler->size = curr.size; - handler->handler(handler); - // Remove the item - if (!that->khandlers[j]->reloadable) - that->khandlers.erase(j); - break; + if (handler->loaded && !strncmp(handler->id, curr.name, KMOD_MAX_NAME)) { + DBGLOG("patcher", "discovered the right kext %s at " PRIKADDR ", invoking handler", curr.name, CASTKADDR(curr.address)); + if (!kinfos[handler->index]->isCurrentBinary(curr.address)) { + SYSLOG("patcher", "uuid mismatch for %s at " PRIKADDR ", ignoring", curr.name, CASTKADDR(curr.address)); + continue; } + handler->address = curr.address; + handler->size = curr.size; + handler->handler(handler); + // Remove the item + if (!that->khandlers[j]->reloadable) + that->khandlers.erase(j); + break; } } } diff --git a/Lilu/Sources/kern_start.cpp b/Lilu/Sources/kern_start.cpp index 8bdd2984..ea4014e7 100644 --- a/Lilu/Sources/kern_start.cpp +++ b/Lilu/Sources/kern_start.cpp @@ -85,12 +85,12 @@ bool Configuration::performInit() { return true; } -int Configuration::policyCheckRemount(kauth_cred_t cred, mount *mp, label *mlabel) { +int Configuration::policyCheckRemount(kauth_cred_t, mount *, label *) { ADDPR(config).policyInit("mac_mount_check_remount"); return 0; } -int Configuration::policyCredCheckLabelUpdateExecve(kauth_cred_t auth, vnode_t vp, ...) { +int Configuration::policyCredCheckLabelUpdateExecve(kauth_cred_t, vnode_t, ...) { ADDPR(config).policyInit("mac_cred_check_label_update_execve"); return 0; } @@ -268,7 +268,7 @@ bool Configuration::registerPolicy() { return true; } -extern "C" kern_return_t kern_start(kmod_info_t * ki, void *d) { +extern "C" kern_return_t kern_start(kmod_info_t *, void *) { // Initialise config status atomic_init(&ADDPR(config).initialised, false); // We should be aware of the CPU we run on. @@ -285,6 +285,6 @@ extern "C" kern_return_t kern_start(kmod_info_t * ki, void *d) { return KERN_SUCCESS; } -extern "C" kern_return_t kern_stop(kmod_info_t *ki, void *d) { +extern "C" kern_return_t kern_stop(kmod_info_t *, void *) { return ADDPR(config).startSuccess ? KERN_FAILURE : KERN_SUCCESS; } diff --git a/Lilu/Sources/kern_user.cpp b/Lilu/Sources/kern_user.cpp index 23f2f764..bd7e85c6 100644 --- a/Lilu/Sources/kern_user.cpp +++ b/Lilu/Sources/kern_user.cpp @@ -42,12 +42,12 @@ kern_return_t UserPatcher::vmProtect(vm_map_t map, vm_offset_t start, vm_size_t DBGLOG("user", "found request for W^X switch-off %d", new_protection); // struct proc layout usually changes with time, so we will calculate the offset based on partial layout: - // struct pgrp *p_pgrp; /* Pointer to process group. (LL) */ - // uint32_t p_csflags; /* flags for codesign (PL) */ - // uint32_t p_pcaction; /* action for process control on starvation */ - // uint8_t p_uuid[16]; /* from LC_UUID load command */ - // cpu_type_t p_cputype; - // cpu_subtype_t p_cpusubtype; + // struct pgrp *p_pgrp Pointer to process group. (LL) + // uint32_t p_csflags flags for codesign (PL) + // uint32_t p_pcaction action for process control on starvation + // uint8_t p_uuid[16] from LC_UUID load command + // cpu_type_t p_cputype + // cpu_subtype_t p_cpusubtype if (csFlagsOffset == 0) { for (size_t off = 0x200; off < 0x400; off += sizeof (uint32_t)) { auto csOff = off - sizeof(uint8_t[16]) - sizeof(uint32_t)*2; @@ -86,17 +86,13 @@ kern_return_t UserPatcher::vmProtect(vm_map_t map, vm_offset_t start, vm_size_t return vm_protect(map, start, size, set_maximum, new_protection); } -int UserPatcher::execListener(kauth_cred_t credential, void *idata, kauth_action_t action, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) { +int UserPatcher::execListener(kauth_cred_t, void *idata, kauth_action_t action, uintptr_t, uintptr_t arg1, uintptr_t, uintptr_t) { // Make sure this is ours - if (that->activated) { - if (idata == &that->cookie && action == KAUTH_FILEOP_EXEC && arg1) { - const char *path = reinterpret_cast(arg1); - that->onPath(path, static_cast(strlen(path))); - } else { - //DBGLOG("user", "listener did not match our needs action %d cookie %d", action, idata == &that->cookie); - } + if (that->activated && idata == &that->cookie && action == KAUTH_FILEOP_EXEC && arg1) { + const char *path = reinterpret_cast(arg1); + that->onPath(path, static_cast(strlen(path))); } - + return 0; } @@ -263,8 +259,6 @@ boolean_t UserPatcher::codeSignValidateRangeWrapper(void *blobs, memory_object_t if (res) that->performPagePatch(data, data_size); - - /*DBGLOG("user", "cs_validate_range %llX %llX %llX %llX -> %llX %llX", (uint64_t)blobs, (uint64_t)pager, range_offset, (uint64_t)data, data_size, (uint64_t)tainted);*/ return res; } @@ -291,11 +285,11 @@ void UserPatcher::onPath(const char *path, uint32_t len) { delete *previous; } - auto p = new PendingUser; - if (p != nullptr) { - lilu_os_strlcpy(p->path, path, MAXPATHLEN); - p->pathLen = len; - PANIC_COND(!pending.set(p), "user", "failed to set user patch request"); + auto pend = new PendingUser; + if (pend != nullptr) { + lilu_os_strlcpy(pend->path, path, MAXPATHLEN); + pend->pathLen = len; + PANIC_COND(!pending.set(pend), "user", "failed to set user patch request"); } else { SYSLOG("user", "failed to allocate pending user callback"); } @@ -366,7 +360,7 @@ bool UserPatcher::injectRestrict(vm_map_t taskPort) { } } - //FIXME: check the space available + //TODO: Should implement a check whether the space is available to ensure that we do not break processes. // Note, that we don't restore memory protection if we fail somewhere (no need to push something non-critical) // Enable writing for the calculated regions @@ -468,7 +462,7 @@ bool UserPatcher::injectPayload(vm_map_t taskPort, uint8_t *payload, size_t size kern_return_t err = orgVmMapReadUser(taskPort, baseAddr, tmpBufferData, sizeof(tmpBufferData)); auto machHeader = reinterpret_cast(tmpBufferData); if (err == KERN_SUCCESS){ - if ((machHeader->magic == MH_MAGIC_64 || machHeader->magic == MH_MAGIC)) { + if (machHeader->magic == MH_MAGIC_64 || machHeader->magic == MH_MAGIC) { size_t hdrSize = machHeader->magic == MH_MAGIC ? sizeof(mach_header) : sizeof(mach_header_64); uintptr_t newEp = hdrSize + machHeader->sizeofcmds; if (newEp + PAGE_SIZE > sizeof(tmpBufferData)) { @@ -671,10 +665,10 @@ void UserPatcher::patchSharedCache(vm_map_t taskPort, uint32_t slide, cpu_type_t SYSLOG("user", "failed to obtain write permissions for patching %d", r); } } else if (ADDPR(debugEnabled)) { - for (size_t i = 0; i < patch.size; i++) { - auto v = (applyChanges? patch.find : patch.replace)[i]; - if (tmp[i] != v) { - DBGLOG("user", "miss at %lu: %02X vs %02X", i, tmp[i], v); + for (size_t l = 0; l < patch.size; l++) { + auto v = (applyChanges? patch.find : patch.replace)[l]; + if (tmp[l] != v) { + DBGLOG("user", "miss at %lu: %02X vs %02X", l, tmp[l], v); break; } } @@ -750,9 +744,9 @@ bool UserPatcher::loadDyldSharedCacheMapping() { uint8_t *buffer {nullptr}; size_t bufferSize {0}; uint32_t ebx = 0; - if (CPUInfo::getCpuid(7, 0, nullptr, &ebx)) { - if ((ebx & CPUInfo::bit_AVX2) && getKernelVersion() >= KernelVersion::Yosemite) - buffer = FileIO::readFileToBuffer(SharedCacheMapHaswell, bufferSize); + if (CPUInfo::getCpuid(7, 0, nullptr, &ebx) && (ebx & CPUInfo::bit_AVX2) && + getKernelVersion() >= KernelVersion::Yosemite) { + buffer = FileIO::readFileToBuffer(SharedCacheMapHaswell, bufferSize); } if (!buffer) diff --git a/Lilu/Sources/kern_util.cpp b/Lilu/Sources/kern_util.cpp index 1f558aef..6bfcca3f 100644 --- a/Lilu/Sources/kern_util.cpp +++ b/Lilu/Sources/kern_util.cpp @@ -49,9 +49,11 @@ void lilu_os_log(const char *format, ...) { } const char *strstr(const char *stack, const char *needle, size_t len) { - if (!len && !(len = strlen(needle))) - return stack; - + if (len == 0) { + len = strlen(needle); + if (len == 0) return stack; + } + const char *i = needle; while (*stack) { diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 00000000..6bac87a4 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,116 @@ +# +# sonar-project.properties +# Lilu +# +# Copyright © 2018 vit9696. All rights reserved. +# + +# Reference: https://docs.sonarqube.org/latest/analysis/analysis-parameters/ + +sonar.projectKey=acidanthera_Lilu +sonar.projectName=Lilu +sonar.projectVersion=1.0 + +sonar.links.homepage=https://github.com/acidanthera/Lilu +sonar.links.ci=https://github.com/acidanthera/Lilu +sonar.links.scm=https://github.com/acidanthera/Lilu +sonar.links.issue=https://github.com/acidanthera/Lilu/issues + +sonar.sourceEncoding=UTF-8 +sonar.sources=Lilu + +# Source exclusions + +sonar.exclusions=Lilu/Library/bsd/**,Lilu/Library/corecrypto/**,Lilu/Library/libkern/**,\ + Lilu/Library/osfmk/**,Lilu/Library/security/**,Lilu/Library/LegacyIOService.h + +# Rule exclusions + +sonar.issue.ignore.multicriteria=e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12 + +# Allow undef in special cases as we use them carefully +sonar.issue.ignore.multicriteria.e1.ruleKey=cpp:PPUndefUsage +sonar.issue.ignore.multicriteria.e1.resourceKey=** + +# Allow union +sonar.issue.ignore.multicriteria.e2.ruleKey=cpp:Union +sonar.issue.ignore.multicriteria.e2.resourceKey=** + +# Allow structs with (public only) methods +sonar.issue.ignore.multicriteria.e3.ruleKey=cpp:S1771 +sonar.issue.ignore.multicriteria.e3.resourceKey=** + +# Remove structure complexity limits, fixing will be costly +sonar.issue.ignore.multicriteria.e4.ruleKey=cpp:S1820 +sonar.issue.ignore.multicriteria.e4.resourceKey=** + +# Remove argument complexity limits, fixing will be costly +sonar.issue.ignore.multicriteria.e5.ruleKey=cpp:S107 +sonar.issue.ignore.multicriteria.e5.resourceKey=** + +# Remove function complexity limits, fixing will be costly +sonar.issue.ignore.multicriteria.e6.ruleKey=cpp:S3776 +sonar.issue.ignore.multicriteria.e6.resourceKey=** + +# Remove break/continue complexity limits, fixing will be costly +sonar.issue.ignore.multicriteria.e7.ruleKey=cpp:SingleGotoOrBreakPerIteration +sonar.issue.ignore.multicriteria.e7.resourceKey=** + +# The use of ## is intentional +sonar.issue.ignore.multicriteria.e8.ruleKey=cpp:PPStringifyAndPastingUsage +sonar.issue.ignore.multicriteria.e8.resourceKey=** + +# The use of const_cast is intentional to hide the internals +sonar.issue.ignore.multicriteria.e9.ruleKey=cpp:S859 +sonar.issue.ignore.multicriteria.e9.resourceKey=** + +# Adding & prior to function name is not a bug and was removed from MISRA-C 2012 +sonar.issue.ignore.multicriteria.e10.ruleKey=cpp:S936 +sonar.issue.ignore.multicriteria.e10.resourceKey=** + +# We need variable argument functions +sonar.issue.ignore.multicriteria.e11.ruleKey=cpp:FunctionEllipsis +sonar.issue.ignore.multicriteria.e11.resourceKey=** + +# Allow multiple declarations on one line +sonar.issue.ignore.multicriteria.e12.ruleKey=cpp:SingleDeclarationPerStatement +sonar.issue.ignore.multicriteria.e12.resourceKey=** + +# sonar.language directive is deprecated and breaks multilanguage analysis. +# One has to manually disable every analyser to ensure no random files are analysed. +# Enabled languages are commented out. + +sonar.abap.file.suffixes=- +sonar.apex.file.suffixes=- +#sonar.c.file.suffixes=- +sonar.cobol.file.suffixes=- +#sonar.cpp.file.suffixes=- +sonar.cs.file.suffixes=- +sonar.css.file.suffixes=- +sonar.flex.file.suffixes=- +sonar.go.file.suffixes=- +sonar.groovy.file.suffixes +sonar.html.file.suffixes=- +sonar.java.file.suffixes=- +sonar.javascript.file.suffixes=- +sonar.kotlin.file.suffixes=- +#sonar.objc.file.suffixes=- +sonar.pli.file.suffixes=- +sonar.plsql.file.suffixes=- +sonar.php.file.suffixes=- +sonar.python.file.suffixes=- +sonar.ruby.file.suffixes=- +sonar.scala.file.suffixes=- +sonar.swift.file.suffixes=- +sonar.tsql.file.suffixes=- +sonar.typescript.file.suffixes=- +sonar.vb.file.suffixes=- +sonar.vbnet.file.suffixes=- +sonar.web.file.suffixes=- +sonar.xml.file.suffixes=- + +# Specified --out-dir for the build-wrapper +sonar.cfamily.build-wrapper-output=DerivedData/compilation-database + +# Disable coverage +sonar.coverage.exclusions=**