Getting information about handles from hang analysis - windbg

I have the following results of !analyze -hang -v on a dump file I have. I see that thread 0 is waiting for some handle to be released, as specified in derived_wait_chain. How can I get more information about this handle? !handle 784.183c returns an error...
0:000> !analyze -hang -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
FAULTING_IP:
+0
00000000 ?? ???
EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 00000000
ExceptionCode: 80000007 (Wake debugger)
ExceptionFlags: 00000000
NumberParameters: 0
CONTEXT: 00000000 -- (.cxr 0x0;r)
eax=00000000 ebx=00000000 ecx=00000007 edx=00000000 esi=00000003 edi=00000003
eip=7725ca2c esp=0018edc4 ebp=0018ef4c iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ntdll!NtWaitForMultipleObjects+0xc:
7725ca2c c21400 ret 14h
BUGCHECK_STR: HANG
PROCESS_NAME: scktsrvr.exe
ERROR_CODE: (NTSTATUS) 0xcfffffff - <Unable to get error code text>
EXCEPTION_CODE: (NTSTATUS) 0xcfffffff - <Unable to get error code text>
NTGLOBALFLAG: 0
APPLICATION_VERIFIER_FLAGS: 0
APP: scktsrvr.exe
ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre
DERIVED_WAIT_CHAIN:
Dl Eid Cid WaitType
-- --- ------- --------------------------
0 784.183c Handle
WAIT_CHAIN_COMMAND: ~0s;k;;
BLOCKING_THREAD: 0000183c
DEFAULT_BUCKET_ID: APPLICATION_HANG_HungIn_ExceptionHandler
PRIMARY_PROBLEM_CLASS: APPLICATION_HANG_HungIn_ExceptionHandler
PRIMARY_PROBLEM_CLASS_DATA: .exr 0x18f558 / .cxr 0x18f5a8
LAST_CONTROL_TRANSFER: from 7534112f to 7725ca2c
FAULTING_THREAD: 00000000
STACK_TEXT:
0018edc0 7534112f 00000003 0018ef90 00000001 ntdll!NtWaitForMultipleObjects+0xc
0018ef4c 75817b89 00000003 0018ef90 00000000 KERNELBASE!WaitForMultipleObjectsEx+0xcc
0018ef68 758707bf 00000003 0018ef90 00000000 kernel32!WaitForMultipleObjects+0x19
0018f3a8 75870295 00000000 00000001 00000000 kernel32!WerpReportFaultInternal+0x50b
0018f3b8 75851709 0018f44c 753ef705 0018f45c kernel32!WerpReportFault+0x74
0018f3c0 753ef705 0018f45c 00000001 5931c527 kernel32!BasepReportFault+0x19
0018f44c 00403764 0018f45c 772600b1 0018f558 KERNELBASE!UnhandledExceptionFilter+0x1f4
WARNING: Stack unwind information not available. Following frames may be wrong.
0018f478 77260083 0018f558 0018ff74 0018f5a8 scktsrvr+0x3764
0018f540 772607ff 0018f558 0018f5a8 0018f558 ntdll!ExecuteHandler+0x24
0018f540 75344598 0018f558 0018f5a8 0018f558 ntdll!KiUserExceptionDispatcher+0xf
0018f8e8 0046f881 0eedfade 00000001 00000007 KERNELBASE!RaiseException+0x48
0018fefc 0046f987 0018ff4c 0018ff14 0046fa00 scktsrvr+0x6f881
0018ff4c 0046f502 00470bd4 7ffde000 00470ce3 scktsrvr+0x6f987
0018ff80 75817c04 7ffde000 75817be0 599eeb0a scktsrvr+0x6f502
0018ff94 7727ad1f 7ffde000 5b3cddf8 00000000 kernel32!BaseThreadInitThunk+0x24
0018ffdc 7727acea ffffffff 7726024e 00000000 ntdll!__RtlUserThreadStart+0x2f
0018ffec 00000000 00470bd4 7ffde000 00000000 ntdll!_RtlUserThreadStart+0x1b
FOLLOWUP_IP:
scktsrvr+3764
00403764 83f800 cmp eax,0
SYMBOL_STACK_INDEX: 7
SYMBOL_NAME: scktsrvr+3764
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: scktsrvr
IMAGE_NAME: scktsrvr.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 2a425e19
STACK_COMMAND: ~0s ; kb
BUCKET_ID: HANG_scktsrvr+3764
FAILURE_BUCKET_ID: APPLICATION_HANG_HungIn_ExceptionHandler_cfffffff_scktsrvr.exe!Unknown
ANALYSIS_SOURCE: UM
FAILURE_ID_HASH_STRING: um:application_hang_hungin_exceptionhandler_cfffffff_scktsrvr.exe!unknown
FAILURE_ID_HASH: {45df6cc2-89e8-d20a-efde-b2365e4d9c6c}
Followup: MachineOwner
---------

784 is the process ID (PID) and 183c is the thread ID (TID) of the thread waiting. To get more information about the handle it is waiting on, switch to the thread and get a call stack with parameters (kb on 32 bit). This will give you a call to WaitForMultipleObjects() or WaitForSingleObject() and from the parameters you'll get the handle(s) it waits for.
In your case, the stack is listed as part of !analyze:
STACK_TEXT:
0018edc0 7534112f 00000003 0018ef90 00000001 ntdll!NtWaitForMultipleObjects+0xc
0018ef4c 75817b89 00000003 0018ef90 00000000 KERNELBASE!WaitForMultipleObjectsEx+0xcc
0018ef68 758707bf 00000003 0018ef90 00000000 kernel32!WaitForMultipleObjects+0x19
Looking at MSDN, it says
DWORD WINAPI WaitForMultipleObjects(
_In_ DWORD nCount,
_In_ const HANDLE *lpHandles,
_In_ BOOL bWaitAll,
_In_ DWORD dwMilliseconds
);
So this thread waits for 3 handles and at address 0018ef90 there are three handles for which you can get more information with !handle.
However, it seems that the real problem is just hidden behind the "Send error report to Microsoft" functionality of Windows.
From the parameters to ntdll!KiUserExceptionDispatcher(), which are an exception record and an exception context, you can find out more about the original exception. As mentioned by #deemok, .exr 0x18f558 and .cxr 0x18f5a8 should bring up more information.
From the parameters to KERNELBASE!RaiseException(), the exception code is 0x0eedfade, which is typical for a Delphi application. Marc Durdin has a nice post about the analysis of Delphi exceptions with WinDbg.

Related

Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in…”

Background: we have an ILI2511 touch controller which raises an interrupt when touch movement is detected. Then the host polls the touch controller via I2C. During EMC testing, the touch controller might fire many interrupts and report wrong finger positions. Nevertheless the kernel should never crash. Here is the relevant code snippets:
Init:
error = devm_request_threaded_irq(dev, client->irq, NULL, ili251x_irq, IRQF_ONESHOT, client->name, data);
Bottom half:
static irqreturn_t ili251x_irq(int irq, void *irq_data)
{
struct ili251x_data *data = irq_data;
struct i2c_client *client = data->client;
struct touchdata touchdata;
int error;
error = ili251x_read_reg(client, REG_TOUCHDATA,
&touchdata,
sizeof(touchdata) -
sizeof(struct finger)*TOUCHDATA2_FINGERS);
/* more code */
if (!error)
ili251x_report_events(data, &touchdata);
else
dev_err(&client-\>dev, "Unable to get touchdata, err = %d\\n", error);
return IRQ_HANDLED;
}
ili251x_read_reg() uses the i2c controller.
I found no array overflow or pointer issues related to stack variables.
Still under EMC heavy fire I'm getting a crash. I added a crash dump further down.
I wonder if the information I'm getting through the crash dump could be used the track down / circle in the issue? For example what does "ili251x_irq+0x200/0x2e4" mean? Is this some code pointer / data pointer referenced in a map file? I assume the stack protector is only active before returning to the caller function.
Example:
Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ili251x_irq+0x200/0x2e4
[ 691.053700] 000: CPU0: stopping
[ 691.056854] 000: CPU: 0 PID: 0 Comm: swapper/0 Tainted: G O 5.4.106-rt54-ge578cc0824 #1
[ 691.066197] 000: Hardware name: Generic DRA74X (Flattened Device Tree)
[ 691.072749] 000: Backtrace:
[ 691.075634] 000:
[ 691.077561] 000: [<c0b93090>] (dump_backtrace) from [<c0b93408>] (show_stack+0x20/0x24)
[ 691.085606] 000: r7:c120dd44 r6:60000193 r5:00000000 r4:c12996e4
[ 691.091718] 000: [<c0b933e8>] (show_stack) from [<c0ba0d04>] (dump_stack+0x98/0xac)
[ 691.099408] 000: [<c0ba0c6c>] (dump_stack) from [<c0210798>] (handle_IPI+0x404/0x47c)
[ 691.107275] 000: r7:c120dd44 r6:00000004 r5:c129ebc4 r4:c12a8270
[ 691.113387] 000: [<c0210394>] (handle_IPI) from [<c0202340>] (gic_handle_irq+0x9c/0xa0)
[ 691.121428] 000: r10:c12a8000 r9:c1201ed0 r8:fa213000 r7:fa212000 r6:fa21200c r5:c125a574
[ 691.129722] 000: r4:c120df34
[ 691.132694] 000: [<c02022a4>] (gic_handle_irq) from [<c0201a78>] (__irq_svc+0x58/0xa0)
[ 691.140643] 000: Exception stack(0xc1201ed0 to 0xc1201f18)
[ 691.146148] 000: 1ec0: 00000000 0041cd04 00000000 c022879c
[ 691.154793] 000: 1ee0: c1200000 c120d730 00000000 c120d778 c129e63d c105ea48 c12a8000 c1201f2c
[ 691.163437] 000: 1f00: c1201f0c c1201f20 c02283fc c0209b34 a0000013 ffffffff
[ 691.170513] 000: r9:c1200000 r8:c129e63d r7:c1201f04 r6:ffffffff r5:a0000013 r4:c0209b34
[ 691.178719] 000: [<c0209b04>] (arch_cpu_idle) from [<c0ba713c>] (default_idle_call+0x3c/0x48)
[ 691.187282] 000: [<c0ba7100>] (default_idle_call) from [<c026ced8>] (do_idle+0xe4/0x150)
[ 691.195407] 000: [<c026cdf4>] (do_idle) from [<c026d26c>] (cpu_startup_entry+0x28/0x2c)
[ 691.203444] 000: r9:c105ea48 r8:00000001 r7:c12a8000 r6:00000000 r5:00000002 r4:000000ce
[ 691.211649] 000: [<c026d244>] (cpu_startup_entry) from [<c0ba0ee4>] (rest_init+0xd4/0xdc)
[ 691.219859] 000: [<c0ba0e10>] (rest_init) from [<c1000b88>] (arch_call_rest_init+0x18/0x1c)
[ 691.228249] 000: r5:00000001 r4:c12a8054
[ 691.232268] 000: [<c1000b70>] (arch_call_rest_init) from [<c10010e0>] (start_kernel+0x4dc/0x51c)
[ 691.241091] 000: [<c1000c04>] (start_kernel) from [00000000>] (0x0)
[ 691.247478] 001: ---[ end Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ili251x_irq+0x200/0x2e4 ]---
[ 691.259201] 001: ------------[ cut here ]------------
We have the chip ILI2511. The driver which I'm describing is from here: ili251x.
I'm using rt kernel 5.4.y and have to stay on this version.
I tried upstream driver (https://elixir.bootlin.com/linux/v5.4.225/source/drivers/input/touchscreen/ili210x.c) but it does not work: it generates input data but when I touch a button the webbrowser, nothing happens.
Typical input queue with ili251x.c driver running:
hexdump /dev/input/event0
0000000 9ae4 3fae 6874 0003 0003 0039 0006 0000
0000010 9ae4 3fae 6874 0003 0003 0035 1730 0000
0000020 9ae4 3fae 6874 0003 0003 0036 213f 0000
0000030 9ae4 3fae 6874 0003 0001 014a 0001 0000
0000040 9ae4 3fae 6874 0003 0003 0000 1730 0000
Typical input queue with (non-working) ili210x.c driver running:
0000000 53a0 3fae f15d 0002 0003 0039 0008 0000
0000010 53a0 3fae f15d 0002 0003 0035 1535 0000
0000020 53a0 3fae f15d 0002 0003 0036 1767 0000
0000030 53a0 3fae f15d 0002 0001 014a 0001 0000
0000040 53a0 3fae f15d 0002 0003 0000 1535 0000
0000050 53a0 3fae f15d 0002 0003 0001 1767 0000
I have not yet analyzed this stream.
I looked at (https://elixir.bootlin.com/linux/v5.15.82/source/drivers/input/touchscreen/ilitek_ts_i2c.c), but this one does not support ILI2511 according to compatibility list.
There is also a driver on github: (https://github.com/NewhavenDisplay/ILI2511-Ilitek-CTP-Drivers/tree/main/Linux%20-%20Ubuntu%2010.04~16.04/ilitek_limv5_9_0_1), which is I have not tried so far.

unable to handle kernel paging request at [address]

**
[ 105.823895] BUG: unable to handle kernel paging request at ffffffffc06ed026
[ 105.823899] PGD 13c80e067 P4D 13c80e067 PUD 13c810067 PMD 12f1d0067 PTE 0
[ 105.823901] Oops: 0010 [#1] SMP NOPTI
[ 105.823903] CPU: 2 PID: 2935 Comm: bash Tainted: G OE 4.19.67-2018202030 #7
[ 105.823904] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
[ 105.823907] RIP: 0010:0xffffffffc06ed026
[ 105.823910] Code: Bad RIP value.
[ 105.823910] RSP: 0018:ffffb129843cbf28 EFLAGS: 00010286
[ 105.823911] RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff8e4e001cb900
[ 105.823912] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8e4e2918f2d8
[ 105.823913] RBP: ffffb129843cbf28 R08: 0000000000000000 R09: 0000000000000000
[ 105.823913] R10: ffffb129843cbe98 R11: 0000000000000000 R12: ffffb129843cbf58
[ 105.823914] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 105.823915] FS: 00007fd974ed2700(0000) GS:ffff8e4e3de80000(0000) knlGS:0000000000000000
[ 105.823915] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 105.823916] CR2: ffffffffc06ecffc CR3: 00000000b5d0e000 CR4: 0000000000340ee0
[ 105.823932] Call Trace:
[ 105.823938] do_syscall_64+0x5a/0x110
[ 105.823941] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 105.823942] RIP: 0033:0x7fd9745c6360
[ 105.823943] Code: 0b 31 c0 48 83 c4 08 e9 ae fe ff ff 48 8d 3d 27 b4 09 00 e8 b2 1e 02 00 66 90 83 3d e9 23 2d 00 00 75 10 b8 00 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 31 c3 48 83 ec 08 e8 5e de 01 00 48 89 04 24
[ 105.823944] RSP: 002b:00007ffeb6b5eb98 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
[ 105.823945] RAX: ffffffffffffffda RBX: 00007fd9748938e0 RCX: 00007fd9745c6360
[ 105.823946] RDX: 0000000000000001 RSI: 00007ffeb6b5eba7 RDI: 0000000000000000
[ 105.823946] RBP: 00000000004d7d4a R08: 00007fd974895770 R09: 00007fd974ed2700
[ 105.823947] R10: 662f37362e39312e R11: 0000000000000246 R12: 000000000045f7d0
[ 105.823947] R13: 0000000000000001 R14: 0000000000000000 R15: 00007ffeb6b5ed60
[ 105.823948] Modules linked in: rfcomm bnep snd_ens1371 snd_ac97_codec gameport ac97_bus btusb btrtl snd_pcm crct10dif_pclmul snd_seq_midi snd_seq_midi_event crc32_pclmul ghash_clmulni_intel snd_rawmidi vmw_balloon pcbc snd_seq snd_seq_device snd_timer btbcm btintel snd bluetooth aesni_intel aes_x86_64 crypto_simd cryptd glue_helper input_leds joydev serio_raw soundcore ecdh_generic i2c_piix4 mac_hid vmw_vsock_vmci_transport vsock vmw_vmci parport_pc ppdev lp parport autofs4 hid_generic usbhid hid vmwgfx ttm drm_kms_helper mptspi mptscsih syscopyarea sysfillrect mptbase sysimgblt fb_sys_fops drm psmouse e1000 scsi_transport_spi ahci libahci pata_acpi [last unloaded: ftracehooking]
[ 105.823975] CR2: ffffffffc06ed026
[ 105.823976] ---[ end trace 2530693e2a17bef8 ]---
[ 105.823977] RIP: 0010:0xffffffffc06ed026
[ 105.823978] Code: Bad RIP value.
[ 105.823979] RSP: 0018:ffffb129843cbf28 EFLAGS: 00010286
[ 105.823980] RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff8e4e001cb900
[ 105.823980] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8e4e2918f2d8
[ 105.823981] RBP: ffffb129843cbf28 R08: 0000000000000000 R09: 0000000000000000
[ 105.823981] R10: ffffb129843cbe98 R11: 0000000000000000 R12: ffffb129843cbf58
[ 105.823982] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 105.823983] FS: 00007fd974ed2700(0000) GS:ffff8e4e3de80000(0000) knlGS:0000000000000000
[ 105.823983] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 105.823984] CR2: ffffffffc06ecffc CR3: 00000000b5d0e000 CR4: 0000000000340ee0
[ 105.829428] BUG: unable to handle kernel paging request at ffffffffc06ed026
[ 105.829433] PGD 13c80e067 P4D 13c80e067 PUD 13c810067 PMD 12f1d0067 PTE 0
[ 105.829439] Oops: 0010 [#2] SMP NOPTI
[ 105.829442] CPU: 1 PID: 1024 Comm: in:imklog Tainted: G D OE 4.19.67-2018202030 #7
[ 105.829444] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020
[ 105.829450] RIP: 0010:0xffffffffc06ed026
[ 105.829455] Code: Bad RIP value.
[ 105.829456] RSP: 0018:ffffb12981b6bf28 EFLAGS: 00010286
[ 105.829459] RAX: 0000000000000ea7 RBX: 0000000000000000 RCX: 0000000000000000
[ 105.829460] RDX: ffff8e4e0003ae00 RSI: 0000000000000000 RDI: ffff8e4d979eb200
[ 105.829461] RBP: ffffb12981b6bf28 R08: 0000000000000000 R09: 0000000000000000
[ 105.829463] R10: ffffb12981b6be98 R11: ffff8e4e3d806e80 R12: ffffb12981b6bf58
[ 105.829464] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 105.829466] FS: 00007f3d4182d700(0000) GS:ffff8e4e3de40000(0000) knlGS:0000000000000000
[ 105.829468] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 105.829469] CR2: ffffffffc06ecffc CR3: 0000000134a30000 CR4: 0000000000340ee0
[ 105.829496] Call Trace:
[ 105.829505] do_syscall_64+0x5a/0x110
[ 105.829510] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 105.829512] RIP: 0033:0x7f3d43c7c51d
[ 105.829515] Code: be 20 00 00 75 10 b8 00 00 00 00 0f 05 48 3d 01 f0 ff ff 73 31 c3 48 83 ec 08 e8 4e fc ff ff 48 89 04 24 b8 00 00 00 00 0f 05 <48> 8b 3c 24 48 89 c2 e8 97 fc ff ff 48 89 d0 48 83 c4 08 48 3d 01
[ 105.829516] RSP: 002b:00007f3d4180c580 EFLAGS: 00000293 ORIG_RAX: 0000000000000000
[ 105.829518] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f3d43c7c51d
[ 105.829520] RDX: 0000000000001fa0 RSI: 00007f3d4180cda0 RDI: 0000000000000004
[ 105.829521] RBP: 00000000011c8320 R08: 0000000000000000 R09: 0000000000000000
[ 105.829522] R10: 00007f3d4180c3d0 R11: 0000000000000293 R12: 00007f3d4180cda0
[ 105.829524] R13: 0000000000001fa0 R14: 0000000000001f9f R15: 00007f3d4180ce98
[ 105.829526] Modules linked in: rfcomm bnep snd_ens1371 snd_ac97_codec gameport ac97_bus btusb btrtl snd_pcm crct10dif_pclmul snd_seq_midi snd_seq_midi_event crc32_pclmul ghash_clmulni_intel snd_rawmidi vmw_balloon pcbc snd_seq snd_seq_device snd_timer btbcm btintel snd bluetooth aesni_intel aes_x86_64 crypto_simd cryptd glue_helper input_leds joydev serio_raw soundcore ecdh_generic i2c_piix4 mac_hid vmw_vsock_vmci_transport vsock vmw_vmci parport_pc ppdev lp parport autofs4 hid_generic usbhid hid vmwgfx ttm drm_kms_helper mptspi mptscsih syscopyarea sysfillrect mptbase sysimgblt fb_sys_fops drm psmouse e1000 scsi_transport_spi ahci libahci pata_acpi [last unloaded: ftracehooking]
[ 105.829632] CR2: ffffffffc06ed026
[ 105.829635] ---[ end trace 2530693e2a17bef9 ]---
[ 105.829638] RIP: 0010:0xffffffffc06ed026
[ 105.829641] Code: Bad RIP value.
[ 105.829643] RSP: 0018:ffffb129843cbf28 EFLAGS: 00010286
[ 105.829644] RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff8e4e001cb900
[ 105.829646] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8e4e2918f2d8
[ 105.829647] RBP: ffffb129843cbf28 R08: 0000000000000000 R09: 0000000000000000
[ 105.829648] R10: ffffb129843cbe98 R11: 0000000000000000 R12: ffffb129843cbf58
[ 105.829649] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 105.829651] FS: 00007f3d4182d700(0000) GS:ffff8e4e3de40000(0000) knlGS:0000000000000000
[ 105.829653] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 105.829654] CR2: ffffffffc06ecffc CR3: 0000000134a30000 CR4: 0000000000340ee0
os2018202030#ubuntu:~$**
I learning operating systems. I made a system call hooking and I found that it has a problem with removing it.
Although the system call hooking I made works fine. But when I remove the module from the kernel, it gives this kind of error message. I assume this kind of error is related to the page size of "syscall_table", but I can't find any relation between "syscall_table" and the address that the error message gave me. (I printed syscall_table address, gave me an address starting with 0000XXXXXX.)
those are the header files that I include.
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/kallsyms.h>
#include <linux/syscalls.h>
#include <asm/syscall_wrapper.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/namei.h>
#include <linux/sched.h>
those are codes that I've written.
#include "./ftracehooking.h"
#define __NR_ftrace 336 //trace system call identifier
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jiyong Park");
MODULE_DESCRIPTION("ftrace hook");
MODULE_VERSION("0.1");
/*
trace variables
*/
int read_count = 0;
int read_bytes = 0;
int write_count = 0;
int write_bytes = 0;
int open_count = 0;
char open_file[NAME_MAX] = {0 };
int close_count = 0;
int lseek_count = 0;
/*
make trace variables accessable from dynamically inserted modules
*/
EXPORT_SYMBOL(read_count);
EXPORT_SYMBOL(read_bytes);
EXPORT_SYMBOL(write_count);
EXPORT_SYMBOL(write_bytes);
EXPORT_SYMBOL(open_count);
EXPORT_SYMBOL(open_file);
EXPORT_SYMBOL(close_count);
EXPORT_SYMBOL(lseek_count);
void **syscall_table; //pointer to syscall table
static asmlinkage int (* orig_ftrace)(const struct pt_regs *reg); //a pointer to original syscall
static asmlinkage int hook_ftrace(const struct pt_regs *reg) //a ftrace hooking syscall
{
pid_t pid = reg->di; //get first argument of the pt_regs structure
if(pid != 0) //if current process is parent process whose pid is not 0
{
/*
initialize variables
*/
read_count = 0;
read_bytes = 0;
write_count = 0;
write_bytes = 0;
open_count = 0;
open_file[0] = '\0';
close_count = 0;
lseek_count = 0;
printk(KERN_INFO "OS Assignment2 ftrace [%d] Start\n", pid); //print kernel message
}
else
{
/*
if it is child process whose pid is 0, print kernel message below
we can get current file name from task_struct *current
*/
printk(KERN_INFO "[2018202030] %s file[%s] start [x] read - %d / written - %d\n", current->comm, open_file, read_bytes, write_bytes);
printk(KERN_INFO "open[%d] close[%d] read[%d] write[%d] lseek[%d]\n", open_count, close_count, read_count, write_count, lseek_count);
printk(KERN_INFO "OS Assignment2 ftrace [%d] End\n", pid);
}
return orig_ftrace(reg); //call original ftrace syscall and return its return value
}
/*
get read and write permission at address
*/
void make_rw(void *addr)
{
unsigned int level;
pte_t *pte = lookup_address((u64)addr, &level); //get page table entry of address
if(pte->pte &~ _PAGE_RW) //if there is no write permission on the address
pte->pte |= _PAGE_RW; //turn on read write permission
}
/*
retrieve read only permission at address
*/
void make_ro(void *addr)
{
unsigned int level;
pte_t *pte = lookup_address((u64)addr, &level); //get page table entry of address
pte->pte = pte->pte &~ _PAGE_RW; //eliminate write permission
}
static int __init hooking_init(void)
{
syscall_table = (void **)kallsyms_lookup_name("sys_call_table"); //get syscall table entry
make_rw(syscall_table); //get page write permission
orig_ftrace = syscall_table[__NR_ftrace]; //store original ftrace syscall
syscall_table[__NR_ftrace] = hook_ftrace; //hook a user defined syscall
make_ro(syscall_table); //eliminate page write permission
return 0;
}
static void __exit hooking_exit(void)
{
make_rw(syscall_table); //get page write permission
syscall_table[__NR_ftrace] = orig_ftrace; //restore pre-defined syscall
make_ro(syscall_table); //eliminate page write permission
}
module_init(hooking_init); //insert module
module_exit(hooking_exit); //exit module
#include "./ftracehooking.h"
#define __NR_ftrace 336
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_lseek 8
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jiyong Park");
MODULE_DESCRIPTION("io trace hook");
MODULE_VERSION("0.1");
void **syscall_table; //pointer to syscall table
/*
external trace variables
*/
extern int read_count;
extern int read_bytes;
extern int write_count;
extern int write_bytes;
extern int open_count;
extern char open_file[NAME_MAX];
extern int close_count;
extern int lseek_count;
/*
pointers to original syscall
*/
static asmlinkage long (*orig_read)(const struct pt_regs *);
static asmlinkage long (*orig_write)(const struct pt_regs *);
static asmlinkage long (*orig_open)(const struct pt_regs *);
static asmlinkage long (*orig_close)(const struct pt_regs *);
static asmlinkage long (*orig_lseek)(const struct pt_regs *);
static asmlinkage long ftrace_read(const struct pt_regs *reg) //read syscall hook
{
read_bytes += reg->dx; //get third argument of the pt_regs structure
++read_count; //increase read count
return orig_read(reg); //call original read syscall and return its return value
}
static asmlinkage long ftrace_write(const struct pt_regs *reg) //write syscall hook
{
write_bytes += reg->dx; //get third argument of the pt_regs structure
++write_count; //increase write count
return orig_write(reg); //call original write syscall and return its return value
}
static asmlinkage long ftrace_open(const struct pt_regs *reg) //open syscall hook
{
char __user *pathname = (char *)reg->di; //get third argument from pt_regs
strncpy_from_user(open_file, pathname, NAME_MAX); //string copy null byte aware
++open_count; //increase open count
return orig_open(reg); //call original open syscall and return its return value
}
static asmlinkage long ftrace_close(const struct pt_regs *reg) //close syscall hook
{
++close_count; //increase close count
return orig_close(reg); //call original close syscall and return its return value
}
static asmlinkage long ftrace_lseek(const struct pt_regs *reg) //lseek syscall hook
{
++lseek_count; //increase lseek count
return orig_lseek(reg); //call original lseek syscall and return its return value
}
/*
get read and write permission at address
*/
/*
void make_rw(void *addr)
{
unsigned int level;
pte_t *pte = lookup_address((u64)addr, &level); //get page table entry of address
if(pte->pte &~ _PAGE_RW) //if there is no write permission on the address
pte->pte |= _PAGE_RW; //turn on read write permission
}
*/
/*
retrieve read only permission at address
*/
/*
void make_ro(void *addr)
{
unsigned int level;
pte_t *pte = lookup_address((u64)addr, &level); //get page table entry of address
pte->pte = pte->pte &~ _PAGE_RW; //eliminate write permission
}
*/
static int __init hooking_init(void)
{
syscall_table = (void **)kallsyms_lookup_name("sys_call_table"); //get syscall table entry
//make_rw(syscall_table);
write_cr0(read_cr0() & (~0x10000)); //get page write permission
/*
store original syscalls
*/
orig_read = syscall_table[__NR_read];
orig_write = syscall_table[__NR_write];
orig_open = syscall_table[__NR_open];
orig_close = syscall_table[__NR_close];
orig_lseek = syscall_table[__NR_lseek];
/*
hook a user defined syscall
*/
syscall_table[__NR_read] = ftrace_read;
syscall_table[__NR_write] = ftrace_write;
syscall_table[__NR_open] = ftrace_open;
syscall_table[__NR_close] = ftrace_close;
syscall_table[__NR_lseek] = ftrace_lseek;
write_cr0(read_cr0() | 0x10000);
return 0;
}
static void __exit hooking_exit(void)
{
/*
restore pre-defined syscall
*/
write_cr0(read_cr0() & (~0x10000));
syscall_table[__NR_read] = orig_read;
syscall_table[__NR_write] = orig_write;
syscall_table[__NR_open] = orig_open;
syscall_table[__NR_close] = orig_close;
syscall_table[__NR_lseek] = orig_lseek;
write_cr0(read_cr0() | 0x10000);
//make_ro(syscall_table); //eliminate page write permission
}
module_init(hooking_init); //insert module
module_exit(hooking_exit); //exit module
can you guys give me an idea of how to solve this problem?

How do I jump from my own bootloader to my own kernel?

I'm developing a homebrew os and I can't figure out how to switch from my homebrew bootloader to my homebrew kernel.
I do not know how it works
 I know it starts with memory, but I don't know what number it starts with
I've been told that I can just look at the minix source, but when I parse it from the iso, it doesn't tell me anything at all, all it tells me is the configuration of the linux directory.
I've been trying to figure it out for a week, but nothing has come up.
I'm sorry if I'm not trying hard enough.
And since there didn't seem to be any similar questions, I thought I'd ask you a question
I'll show you a well commented minimal example of jumping to a C++ kernel I wrote so maybe you can go from there and write your own. I work on Linux Ubuntu 20.
In your home directory create a folder named OS and create a file named kernel.cpp in that folder. Place the following content in that file:
void map_framebuffer(){
unsigned long* page_directory_table_pointer = (unsigned long*) 0xb018;
*page_directory_table_pointer = 0x1e00f;
unsigned long* page_table_pointer = (unsigned long*) 0x1e000;
/*
This is the actual address of the framebuffer in QEMU
for the video mode I set up in boot.asm.
In this case it is hardcoded. You may want to actually get this from the VBE structure.
The VBE structure is placed at 0x7e00 in memory by the boot.asm routine.
*/
unsigned long framebuffer_address = (unsigned long) 0xfd00000f;
for (unsigned int i = 0; i < 512; i++){
*page_table_pointer = framebuffer_address;
framebuffer_address += 0x1000;
page_table_pointer++;
}
}
void main(){
map_framebuffer();
/*
I made sure that the framebuffer is mapped to adress 0x600000 in the map_framebuffer() function.
You may want to identity map it instead or map it somewhere else. You'll then have to
calculate page table offsets and stuff.
*/
unsigned char* framebuffer_pointer = (unsigned char*)0x600000;
//Make a few pixels become white. Each pixel is 3 bytes RGB.
for (unsigned int i = 0; i < 10000; i++)
*(framebuffer_pointer + i) = 0xff;
asm volatile(
"halt:\n\t"
"hlt\n\t"
"jmp halt\n\t");
}
/*
Memory map of kernel
7e00 - 8000 -> VBE INFO structure
8000 - 9000 -> paging.bin (booting asm code)
9000 - a000 -> pml4
a000 - b000 -> pdpt
b000 - c000 -> pdt
1b000 - 1c000 -> pt1 (kernel identity mapped pages)
1c000 - 1d000 -> pt2 (kernel identity mapped pages)
1d000 - 1e000 -> pt3 (kernel identity mapped pages)
1e000 - 1f000 -> pt4 (mapped to the framebuffer, only 2MB are mapped to the framebuffer which could take more than this)
30000 - 80000 -> kernel.elf (temporary kernel file)
80000 -> kernel stack (growing downward)
*/
Now create a file named boot.asm in the same directory and write the following content into it:
org 0x7c00
bits 16
;Set the video mode to VBE graphics mode for being able to draw onto the screen
jmp get_vbe_info
error:
mov ah, 0x0e
mov al, 'e'
int 0x10
hlt
get_vbe_info:
mov ax, 0x4f01 ;c0 00 00 00
mov cx, 0x118
xor bx, bx
mov es, bx
mov di, 0x7e00
int 0x10
cmp ax, 0x004f
jne error
set_video_mode:
mov ax, 0x4f02
mov bx, 0x4118
int 0x10
cmp ax, 0x004f
jne error
;Set up a real mode stack
mov ax, 0x00
mov ss, ax
mov sp, 0x7c00
;Load the second stage bootloader at 0x8000
mov ah, 0x00 ;reset drive
int 0x13
xor ax, ax
mov es, ax
mov bx, 0x8000 ;es:bx = 0x0000:0x8000 = 0x8000
mov ah, 0x02 ;read sector function
mov al, 0x09 ;read 9 sectors
mov ch, 0x00 ;cylinder 0
mov dh, 0x00 ;head 0
mov cl, 0x02 ;start from sector 2
int 0x13
;Load the cpp kernel at 0x30000
mov ah, 0x00
int 0x13
mov ax, 0x3000
mov es, ax
xor bx, bx ;es:bx = 0x3000:0x0000 = 0x3000 * 0x10 + 0x0 = 0x30000
mov ah, 0x02 ;read sector function
mov al, 0x3c ;read 60 sectors to load the whole file
mov ch, 0x00 ;cylinder 0
mov dh, 0x00 ;head 0
mov cl, 0x0a ;start from sector 10 (because this is where lies the ELF CPP kernel in the disk.img we created with dd)
int 0x13
xor ax, ax
mov ds, ax
;Set up a protected mode stack
mov ax, 0x10 ;10000b = 10 for segment selector 2 (data)
mov ss, ax
mov sp, 0x7c00
cli
lgdt[gdtr]
;Enable protected mode
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x08:protectedMode ;0x08 = 1000b, 1 for segment selector
;0 for gdt not ldt and 00 for privilege
bits 32
protectedMode:
mov ax, 0x10
mov ds, ax
;Jump to 0x8000 (the second stage bootloader)
jmp 0x08:0x8000
gdt_start:
dq 0x0
gdt_code:
dw 0xFFFF ;limit 0-15
dw 0x0 ;base 0-15
db 0x0 ;base 16-23
db 10011010b ;pr, privi (2), s, ex, dc, rw, ac
db 11001111b ;gr, sz, limit 16-19
db 0x0 ;base 24-31
gdt_data:
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdtr:
dw 24
dd gdt_start
times 510 - ($-$$) db 0
dw 0xAA55
Now create a third file named paging.asm and place the following into it:
org 0x8000
bits 32
;Set up paging
mov eax, 0x00009008
mov cr3, eax
pml4t:
mov dword [0x9000], 0x0000a00f
mov dword [0x9004], 0x0
pdpt:
mov dword [0xa000], 0x0000b00f
mov dword [0xa004], 0x0
pdt:
mov dword [0xb000], 0x0001b00f
mov dword [0xb004], 0x0
mov dword [0xb008], 0x0001c00f
mov dword [0xb00c], 0x0
mov dword [0xb010], 0x0001d00f
mov dword [0xb014], 0x0
pt:
mov edx, 0x3
mov eax, 0x200
mov ebx, 0x0000000f
mov ecx, 0x1b000
next_table:
next_entry:
mov dword [ecx], ebx
add ecx, 0x4
mov dword [ecx], 0x0
add ebx, 0x1000 ;add 4096 to the adress pointed to by ebx (the next physical page)
add ecx, 0x4
sub eax, 0x1
cmp eax, 0x0
jne next_entry
mov eax, 0x200
sub edx, 0x1
cmp edx, 0x0
jne next_table
mov eax, cr4 ;enable PAE-paging
or eax, 1 << 5
mov cr4, eax
mov ecx, 0xC0000080 ;set long mode bit in EFER MSR
rdmsr
or eax, 1 << 8
wrmsr
mov eax, cr0 ;enable paging
or eax, 1 << 31
mov cr0, eax
lgdt[gdtr] ;load a 64 bit gdt (will be ignored afterwards)
jmp 0x08:longMode
bits 64
longMode:
mov ax, 0x10 ;10000b = 10 for segment selector 2 (data)
mov ss, ax
mov rsp, 0x80000
mov rdi, 0x30000 ;address where elf reading occurs
mov rsi, 0x30000
add rdi, 24 ;program entry
mov rax, [rdi] ;placed in rax
add rdi, 8 ;program header table position
mov rbx, [rdi] ;put it in rbx
add rdi, 24 ;move to number of entries in program header
mov cx, [rdi] ;put it in cx (2 bytes)
mov rdi, 0x30000 ;beginning of file
add rdi, rbx ;go to program header 0
add rsi, rbx
next_segment:
mov edx, [rdi] ;put the type of segment in edx (4 bytes)
cmp edx, 0x1 ;determine if it is loadable
jne not_loadable ;if it isnt jump to not_loadable
add rdi, 0x8 ;else load it
mov r8, [rdi] ;put the offset in the file where data for this segment resides in r8
add rdi, 0x8 ;go to virtual address of segment
mov r9, [rdi] ;put it in r9
add rdi, 0x10 ;move to size of segment in file
mov r10, [rdi] ;put it in r10
add rdi, 0x8 ;move to size of segment in memory
mov r11, [rdi] ;put it in r11
mov rdi, 0x30000 ;move back to beginning of file
add rdi, r8 ;add segment offset to be at the segment position
next_byte:
mov dl, [rdi] ;put the byte at rdi in dl
mov [r9], dl ;move it to virtual address in r9
add r9, 0x1 ;add 1 byte to virtual address
add rdi, 0x1 ;add 1 byte to rdi
sub r10, 0x1 ;substract 1 byte from size of segment in file
sub r11, 0x1 ;substract 1 byte from size of segment in memory
cmp r10, 0x0 ;is segment finished
jne next_byte ;if not go to next_byte
cmp r11, 0x0 ;if yes tcheck memory size
je no_padding ;if no padding required jmp to no_padding
padding:
xor dl, dl
mov [r9], dl
add r9, 0x01
sub r11, 0x1
cmp r11, 0x0
jne padding
not_loadable:
no_padding:
sub cx, 0x1
cmp cx, 0x0
je finished
add rsi, 56
mov rdi, rsi
jmp next_segment
finished:
jmp rax ;Jump to the entry point of the ELF CPP file
halt:
hlt
jmp halt
;The 64-bits GDT
gdt_start:
dw 0xFFFF
dw 0
db 0
db 0
db 1
db 0
gdt_code:
dw 0x1111 ;limit 0-15
dw 0x0 ;base 0-15
db 0x0 ;base 16-23
db 10011010b ;pr, privi (2), s, ex, dc, rw, ac
db 10101111b ;gr, sz, limit 16-19
db 0x0 ;base 24-31
gdt_data:
dw 0x1111
dw 0x0
db 0x0
db 10010010b
db 00001111b
db 0x0
gdtr:
dw $ - gdt_start - 1
dq gdt_start
Now open a bash terminal and type the following commands in order (making sure to have NASM, g++ and QEMU installed):
nasm -fbin OS/boot.asm -oOS/boot.bin
nasm -fbin OS/paging.asm -oOS/paging.bin
g++ -static -ffreestanding -nostdlib -c -m64 OS/kernel.cpp -oOS/kernel.o
ld --entry main --oformat elf64-x86-64 --no-dynamic-linker -static -nostdlib OS/kernel.o -oOS/kernel.elf
dd if=/dev/zero of=OS/disk.img count=100 & dd if=OS/boot.bin of=OS/disk.img conv=notrunc & dd if=OS/paging.bin of=OS/disk.img seek=1 conv=notrunc & dd if=OS/kernel.elf of=OS/disk.img seek=9 conv=notrunc
qemu-system-x86_64 -hda OS/disk.img -s
You can always put all that in a bash file and launch it automatically. The -s in the QEMU command makes the virtual machine listen on port 1234. You can use gdb to debug the kernel. Type in gdb in a bash shell then target remote localhost:1234. You will then be debugging the machine. You can type dump memory result.bin 0x1000 0x2000 to dump the memory of the machine from 0x1000 to 0x2000 (or any address) in the file result.bin. You can use hexdump -C result.bin to look at the memory dump from terminal. The output is little endian so you need to reverse it for the actual values.
In the code above I'm loading the ELF file compiled with g++ to address 0x30000. Then I'm parsing the file and jumping to its entry point. The cpp code maps the framebuffer in virtual memory and makes a few pixels become white. The code is far from perfect but if you understand it in its entirety then you can go a long way.

Windbg: Figuring out how many times a breakpoint was hit before a crash

I set the following breakpoint:
bp MSPTLS!LsCreateLine 100
The program crashes before the break point is hit 100 times. When I do bl after the crash, I get the following:
0 e 5dca4b62 0072 (0100) 0:**** MSPTLS!LsCreateLine
I am assuming from this information that the break point was hit 72 times before the crash.
However, when I do bp MSPTLS!LsCreateLine 80 I am able to hit the breakpoint before the crash telling me that the break point was hit more than 72 times before the crash. Does this 72 not indicate how many times the break point was hit?
The default number format of WinDbg is hexadecimal. If you want decimal numbers, prefix them with 0n:
0:005> bp ntdll!DbgBreakPoint 0n100
0:005> bl
0 e 7735000c 0064 (0064) 0:**** ntdll!DbgBreakPoint
The counter 0064 before (0064) counts backwards. You can easily observe that in any GUI application:
0:000> bl
0 e 74fd78d7 000a (000a) 0:**** USER32!NtUserGetMessage+0x15
1 e 74fd78c2 0064 (0064) 0:**** USER32!NtUserGetMessage
0:000> g
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=00000000 edx=00000000 esi=001faf8c edi=74fd787b
eip=74fd78d7 esp=001faf44 ebp=001faf60 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
USER32!NtUserGetMessage+0x15:
74fd78d7 83c404 add esp,4
0:000> bl
0 e 74fd78d7 0001 (000a) 0:**** USER32!NtUserGetMessage+0x15
1 e 74fd78c2 005a (0064) 0:**** USER32!NtUserGetMessage
0:000> ? 5a
Evaluate expression: 90 = 0000005a
In the example, breakpoint 0 has been hit 10 times, leaving breakpoint 1 at 90.

app not running after enabling gcUnmanagedToManaged MDA

Because of heap corruption I enabled gcUnmanagedToManaged MDA through a system environment variable. Unfortunately I can't run my app anymore. I always get something like the following:
(a78.1150): Unknown exception - code e053534f (first chance)
eax=00000000 ebx=00dff8ac ecx=00000000 edx=00000000 esi=00000003 edi=00000000
eip=7779013d esp=00dff85c ebp=00dff8f8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!NtWaitForMultipleObjects+0x15:
7779013d 83c404 add esp,4
All my threads seem to be killed (XXXX):
0:002> !threads
ThreadCount: 5
UnstartedThread: 1
BackgroundThread: 3
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
XXXX 1 c98 00401568 6020 Enabled 00000000:00000000 003c7698 4 STA
XXXX 2 4cc 0040be80 b220 Enabled 00000000:00000000 003c7698 0 MTA (Finalizer)
XXXX 3 1150 05525948 7220 Disabled 00000000:00000000 003c7698 0 STA System.StackOverflowException (0265106c)
XXXX 4 e2c 055778c0 200b220 Enabled 00000000:00000000 003c7698 1 MTA
XXXX 5 0 055b4a28 1600 Enabled 00000000:00000000 003c7698 0 Ukn
As soon as I get rid of COMPLUS_MDA=gcUnmanagedToManaged it's working as expected. My system is x86 with .net 3.5 SP1.
Any hints?
UPDATE:
I also tried to debug it:
0:002> k 0xffff
ChildEBP RetAddr
00eef8cc 757015e9 ntdll!NtWaitForMultipleObjects+0x15
00eef968 75091a2c KERNELBASE!WaitForMultipleObjectsEx+0x100
00eef9b0 75094220 KERNEL32!WaitForMultipleObjectsExImplementation+0xe0
00eef9cc 724a7821 KERNEL32!WaitForMultipleObjects+0x18
00eefa2c 724a777e mscorwks!DebuggerRCThread::MainLoop+0xe9
00eefa5c 724a76a5 mscorwks!DebuggerRCThread::ThreadProc+0xe5
00eefa8c 750933aa mscorwks!DebuggerRCThread::ThreadProcStatic+0x9c
00eefa98 777a9ef2 KERNEL32!BaseThreadInitThunk+0xe
00eefad8 777a9ec5 ntdll!__RtlUserThreadStart+0x70
00eefaf0 00000000 ntdll!_RtlUserThreadStart+0x1b