Skip to content

Commit 8159c8b

Browse files
committed
Added disk log dump in DEBUG builds via liludump=N boot-arg (requires plugin rebuild)
N is the amount of seconds to wait before saving the log to /var/log/Lilu_%ver_%kernver.txt
1 parent 088885d commit 8159c8b

File tree

7 files changed

+211
-33
lines changed

7 files changed

+211
-33
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Lilu Changelog
44
#### v1.2.7
55
- Added support for detecting optimus switch-off
66
- Added Sanitize target with ubsan support (thx to NetBSD)
7+
- Added disk log dump in DEBUG builds via `liludump=N` boot-arg (requires plugin rebuild)
78
- Fixed multiple Mach-O parsing issues
89
- Fixed support of PCI devices without compatible property
910

Lilu/Headers/kern_util.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,8 @@ extern proc_t kernproc;
7474
*/
7575
#define SYSLOG_COND(cond, module, str, ...) \
7676
do { \
77-
if (cond) { \
78-
IOLog( "%s%10s" str "\n", xStringify(PRODUCT_NAME) ": ", module " @ ", ## __VA_ARGS__); \
79-
if (ADDPR(debugPrintDelay) > 0) IOSleep(ADDPR(debugPrintDelay)); \
80-
} \
77+
if (cond) \
78+
LLLog( "%s%10s" str "\n", xStringify(PRODUCT_NAME) ": ", module " @ ", ## __VA_ARGS__); \
8179
} while (0)
8280

8381
/**
@@ -236,6 +234,14 @@ extern proc_t kernproc;
236234
*/
237235
#define PACKED __attribute__((packed))
238236

237+
/**
238+
* This function is supposed to workaround missing entries in the system log.
239+
* By providing its own buffer for logging data.
240+
*
241+
* @param format formatted string
242+
*/
243+
EXPORT void LLLog(const char *format, ...);
244+
239245
/**
240246
* Two-way substring search
241247
*

Lilu/PrivateHeaders/kern_config.hpp

Lines changed: 91 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,32 @@
1212
#include <Headers/kern_user.hpp>
1313
#include <Headers/kern_policy.hpp>
1414
#include <Headers/kern_util.hpp>
15+
#include <kern/thread_call.h>
1516

1617
class Configuration {
1718
/**
1819
* Possible boot arguments
1920
*/
20-
static constexpr const char *bootargOff {"-liluoff"}; // Disable the kext
21-
static constexpr const char *bootargUserOff {"-liluuseroff"}; // Disable kext user patcher
22-
static constexpr const char *bootargBeta {"-lilubeta"}; // Force enable the kext on unsupported os
23-
static constexpr const char *bootargBetaAll {"-lilubetaall"}; // Force enable the kext and all plugins on unsupported os
24-
static constexpr const char *bootargForce {"-liluforce"}; // Force enable the kext (including single user mode)
25-
static constexpr const char *bootargDebug {"-liludbg"}; // Enable debug logging
26-
static constexpr const char *bootargDebugAll {"-liludbgall"}; // Enable debug logging (for Lilu and all the plugins)
27-
static constexpr const char *bootargSlow {"-liluslow"}; // Prefer less destructive userspace measures
28-
static constexpr const char *bootargFast {"-lilufast"}; // Prefer faster userspace measures
29-
static constexpr const char *bootargLowMem {"-lilulowmem"}; // Disable decompression
30-
static constexpr const char *bootargDelay {"liludelay"}; // Extra delay timeout after each printed message
31-
21+
static constexpr const char *bootargOff {"-liluoff"}; // Disable the kext
22+
static constexpr const char *bootargUserOff {"-liluuseroff"}; // Disable kext user patcher
23+
static constexpr const char *bootargBeta {"-lilubeta"}; // Force enable the kext on unsupported os
24+
static constexpr const char *bootargBetaAll {"-lilubetaall"}; // Force enable the kext and all plugins on unsupported os
25+
static constexpr const char *bootargForce {"-liluforce"}; // Force enable the kext (including single user mode)
26+
static constexpr const char *bootargDebug {"-liludbg"}; // Enable debug logging
27+
static constexpr const char *bootargDebugAll {"-liludbgall"}; // Enable debug logging (for Lilu and all the plugins)
28+
static constexpr const char *bootargSlow {"-liluslow"}; // Prefer less destructive userspace measures
29+
static constexpr const char *bootargFast {"-lilufast"}; // Prefer faster userspace measures
30+
static constexpr const char *bootargLowMem {"-lilulowmem"}; // Disable decompression
31+
static constexpr const char *bootargDelay {"liludelay"}; // Extra delay timeout after each printed message
32+
static constexpr const char *bootargDump {"liludump"}; // Dump lilu log to /Lilu...txt after N seconds
33+
34+
public:
35+
/**
36+
* Externally handled boot arguments
37+
*/
38+
static constexpr const char *bootargCpu {"lilucpu"}; // Simulate this CPU generation, handled in kern_cpu.cpp
39+
40+
private:
3241
/**
3342
* Minimal required kernel version
3443
*/
@@ -38,19 +47,19 @@ class Configuration {
3847
* Maxmimum supported kernel version
3948
*/
4049
static constexpr KernelVersion maxKernel {KernelVersion::Mojave};
41-
50+
4251
/**
4352
* Set once the arguments are parsed
4453
*/
4554
bool readArguments {false};
46-
55+
4756
/**
4857
* Initialise kernel and user patchers if necessary
4958
*
5059
* @return true on success
5160
*/
5261
bool performInit();
53-
62+
5463
/**
5564
* TrustedBSD policy called at exec
5665
*
@@ -60,8 +69,7 @@ class Configuration {
6069
* @return 0 on success
6170
*/
6271
static int policyCredCheckLabelUpdateExecve(kauth_cred_t old, vnode_t vp, ...);
63-
64-
72+
6573
/**
6674
* TrustedBSD policy called before remounting
6775
*
@@ -70,22 +78,48 @@ class Configuration {
7078
* @param mlabel mount point label
7179
*/
7280
static int policyCheckRemount(kauth_cred_t cred, mount *mp, label *mlabel);
73-
81+
7482
/**
7583
* TrustedBSD policy options
7684
*/
7785
mac_policy_ops policyOps {
7886
.mpo_policy_initbsd = Policy::dummyPolicyInitBSD
7987
};
80-
88+
89+
#ifdef DEBUG
90+
/**
91+
* Debug buffer dump timeout in seconds
92+
*/
93+
uint32_t debugDumpTimeout {0};
94+
95+
/**
96+
* Debug buffer dump thread call
97+
*/
98+
thread_call_t debugDumpCall {nullptr};
99+
100+
/**
101+
* Initialise log to custom buffer support
102+
* You may call it from a debugger if you need to save the log once again.
103+
*/
104+
void initCustomDebugSupport();
105+
106+
/**
107+
* Stores debug log on disk
108+
*
109+
* @param param0 unused
110+
* @param param1 unused
111+
*/
112+
static void saveCustomDebugOnDisk(thread_call_param_t param0, thread_call_param_t param1);
113+
#endif
114+
81115
public:
82116
/**
83117
* Retrieve boot arguments
84118
*
85119
* @return true if allowed to continue
86120
*/
87121
bool getBootArguments();
88-
122+
89123
/**
90124
* Disable the extension by default
91125
*/
@@ -95,17 +129,17 @@ class Configuration {
95129
* User patcher is disabled on request
96130
*/
97131
bool isUserDisabled {false};
98-
132+
99133
/**
100134
* Do not patch dyld shared cache unless asked
101135
*/
102136
bool preferSlowMode {false};
103-
137+
104138
/**
105139
* Allow decompression
106140
*/
107141
bool allowDecompress {true};
108-
142+
109143
/**
110144
* Install or recovery
111145
*/
@@ -115,7 +149,7 @@ class Configuration {
115149
* Safe mode
116150
*/
117151
bool safeMode {false};
118-
152+
119153
/**
120154
* Beta for all plugins and Lilu itself
121155
*/
@@ -140,23 +174,52 @@ class Configuration {
140174
* User patcher
141175
*/
142176
UserPatcher userPatcher;
143-
177+
144178
/**
145179
* Kernel patcher
146180
*/
147181
KernelPatcher kernelPatcher;
148-
182+
149183
/**
150184
* Policy controller
151185
*/
152186
Policy policy;
153-
187+
154188
#ifdef DEBUG
189+
/**
190+
* Full policy name
191+
*/
155192
static constexpr const char *fullName {xStringify(PRODUCT_NAME) " Kernel Extension " xStringify(MODULE_VERSION) " DEBUG build"};
193+
194+
/**
195+
* Maximum amount of data we can via the internal buffer (8 MB)
196+
*/
197+
static constexpr size_t MaxDebugBufferSize {1024*1024*8};
198+
199+
/**
200+
* Custom logging lock
201+
*/
202+
IOSimpleLock *debugLock {nullptr};
203+
204+
/**
205+
* Debug buffer with logged data, intentionally disabled in RELEASE mode
206+
* to avoid sensitive information leak.
207+
* Contains debugBufferLength symbols, not null-terminated.
208+
*/
209+
uint8_t *debugBuffer {nullptr};
210+
211+
/**
212+
* Debug buffer current length
213+
*/
214+
size_t debugBufferLength {0};
156215
#else
216+
217+
/**
218+
* Full policy name
219+
*/
157220
static constexpr const char *fullName {xStringify(PRODUCT_NAME) " Kernel Extension " xStringify(MODULE_VERSION)};
158221
#endif
159-
222+
160223
Configuration() : policy(xStringify(PRODUCT_NAME), fullName, &policyOps) {}
161224
};
162225

Lilu/Sources/kern_cpu.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <Headers/kern_cpu.hpp>
99
#include <Headers/kern_devinfo.hpp>
10+
#include <PrivateHeaders/kern_config.hpp>
1011
#include <i386/proc_reg.h>
1112

1213
extern "C" {
@@ -53,7 +54,7 @@ void CPUInfo::loadCpuInformation() {
5354

5455
// Last but not least detect CPU generation
5556
uint32_t generation = 0;
56-
if (PE_parse_boot_argn("lilucpu", &generation, sizeof(generation))) {
57+
if (PE_parse_boot_argn(Configuration::bootargCpu, &generation, sizeof(generation))) {
5758
DBGLOG("cpu", "found CPU generation override %u", generation);
5859
if (generation < static_cast<uint32_t>(CPUInfo::CpuGeneration::MaxGeneration)) {
5960
currentGeneration = static_cast<CPUInfo::CpuGeneration>(generation);

Lilu/Sources/kern_start.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <Headers/kern_api.hpp>
1414
#include <Headers/kern_efi.hpp>
1515
#include <Headers/kern_cpu.hpp>
16+
#include <Headers/kern_file.hpp>
17+
#include <Headers/kern_time.hpp>
1618

1719
#include <IOKit/IOLib.h>
1820
#include <IOKit/IORegistryEntry.h>
@@ -98,6 +100,73 @@ int Configuration::policyCredCheckLabelUpdateExecve(kauth_cred_t auth, vnode_t v
98100
return 0;
99101
}
100102

103+
#ifdef DEBUG
104+
105+
void Configuration::initCustomDebugSupport() {
106+
if (debugDumpTimeout == 0)
107+
return;
108+
109+
if (!debugBuffer)
110+
debugBuffer = Buffer::create<uint8_t>(MaxDebugBufferSize);
111+
112+
if (!debugLock)
113+
debugLock = IOSimpleLockAlloc();
114+
115+
if (debugBuffer && debugLock) {
116+
if (debugDumpCall) {
117+
while (!thread_call_free(debugDumpCall))
118+
thread_call_cancel(debugDumpCall);
119+
debugDumpCall = nullptr;
120+
}
121+
122+
debugDumpCall = thread_call_allocate(saveCustomDebugOnDisk, nullptr);
123+
if (debugDumpCall) {
124+
uint64_t deadlineNs = convertScToNs(debugDumpTimeout);
125+
uint64_t deadlineAbs = 0;
126+
nanoseconds_to_absolutetime(deadlineNs, &deadlineAbs);
127+
thread_call_enter_delayed(debugDumpCall, mach_absolute_time() + deadlineAbs);
128+
return;
129+
}
130+
}
131+
132+
if (debugBuffer) {
133+
Buffer::deleter(debugBuffer);
134+
debugBuffer = nullptr;
135+
}
136+
137+
if (debugLock) {
138+
IOSimpleLockFree(debugLock);
139+
debugLock = nullptr;
140+
}
141+
}
142+
143+
void Configuration::saveCustomDebugOnDisk(thread_call_param_t, thread_call_param_t) {
144+
if (ADDPR(config).debugLock && ADDPR(config).debugBuffer) {
145+
auto logBuf = Buffer::create<uint8_t>(MaxDebugBufferSize);
146+
if (logBuf) {
147+
size_t logBufSize = 0;
148+
IOSimpleLockLock(ADDPR(config).debugLock);
149+
logBufSize = ADDPR(config).debugBufferLength;
150+
if (logBufSize > 0)
151+
lilu_os_memcpy(logBuf, ADDPR(config).debugBuffer, logBufSize);
152+
IOSimpleLockUnlock(ADDPR(config).debugLock);
153+
154+
if (logBufSize > 0) {
155+
char name[64];
156+
snprintf(name, sizeof(name), "/var/log/Lilu_" xStringify(MODULE_VERSION) "_%d.%d.txt", getKernelVersion(), getKernelMinorVersion());
157+
FileIO::writeBufferToFile(name, logBuf, logBufSize);
158+
}
159+
160+
Buffer::deleter(logBuf);
161+
}
162+
}
163+
164+
thread_call_free(ADDPR(config).debugDumpCall);
165+
ADDPR(config).debugDumpCall = nullptr;
166+
}
167+
168+
#endif
169+
101170
bool Configuration::getBootArguments() {
102171
if (readArguments) return !isDisabled;
103172

@@ -109,6 +178,12 @@ bool Configuration::getBootArguments() {
109178

110179
PE_parse_boot_argn(bootargDelay, &ADDPR(debugPrintDelay), sizeof(ADDPR(debugPrintDelay)));
111180

181+
#ifdef DEBUG
182+
PE_parse_boot_argn(bootargDump, &debugDumpTimeout, sizeof(debugDumpTimeout));
183+
// Slightly out of place, but we need to do that as early as possible.
184+
initCustomDebugSupport();
185+
#endif
186+
112187
isDisabled |= checkKernelArgument(bootargOff);
113188
if (!checkKernelArgument(bootargForce)) {
114189
isDisabled |= checkKernelArgument("-s");

0 commit comments

Comments
 (0)