Enable lsw --launch hello.exe to execute PE binaries from userspace by delegating execution to the kernel module.
- Added
#include "shared/lsw_kernel_client.h"to access kernel communication functions - Rewrote
pe_execute()function to:- Open
/dev/lswkernel device usinglsw_kernel_open() - Prepare
struct lsw_pe_infowith PE details:- PID (current process)
- Base address (where PE is loaded in memory)
- Entry point (where to start execution)
- Image size
- Architecture (32-bit or 64-bit)
- Executable path
- Register PE with kernel using
lsw_kernel_register_pe() - Clean up with
lsw_kernel_unregister_pe()andlsw_kernel_close()
- Open
Before:
$ ./lsw --launch hello.exe
[loads PE]
[tries to execute directly in userspace]
Segmentation faultAfter (with working kernel module):
$ ./lsw --launch hello.exe
[loads PE]
[registers with kernel module]
✅ PE registered with kernel successfully
TODO: Kernel needs to execute the PE at entry point- ✅ PE parsing and loading (all 19 sections)
- ✅ Import resolution (47 functions from 2 DLLs)
- ✅ Memory mapping at correct base address
- ✅ Kernel communication infrastructure (
lsw_kernel_client.c) - ✅ Code compiles and links successfully
-
Add execution capability to kernel module
- When PE is registered, kernel should:
- Create kernel thread for PE process
- Set up TEB/PEB structures
- Jump to entry point in kernel context
- Handle Win32 API calls via syscall dispatcher
- When PE is registered, kernel should:
-
Add execution trigger ioctl
- New ioctl:
LSW_IOCTL_EXECUTE_PE - Userspace calls this after registration
- Kernel creates process and starts execution
- New ioctl:
-
Add status/wait mechanism
- Userspace needs to wait for PE execution to complete
- Get exit code back from kernel
- Handle process termination properly
// In kernel module (lsw_device.c)
static long lsw_execute_pe(pid_t pid) {
// Find registered PE by PID
// Create kernel thread for PE process
// Set up Win32 environment (TEB, PEB)
// Jump to entry point
// Return 0 on success
}
// In userspace (pe_loader.c)
int pe_execute(pe_image_t* image, int argc, char** argv) {
// ... existing registration code ...
// NEW: Trigger execution
ret = ioctl(kernel_fd, LSW_IOCTL_EXECUTE_PE, pe_info.pid);
// NEW: Wait for completion
int exit_code = lsw_kernel_wait_for_pe(kernel_fd, pe_info.pid);
// Cleanup
lsw_kernel_unregister_pe(kernel_fd, pe_info.pid);
lsw_kernel_close(kernel_fd);
return exit_code;
}- Cannot test yet: Kernel module in bad state (Used by: -1)
- Need: Reboot or fix module load issue
- Device node:
/dev/lswnot created (module initialization incomplete)
When complete, this should work:
$ ./lsw --launch hello.exe
[19:43:34] INFO LSW starting - Linux Subsystem for Windows
[19:43:34] INFO Target: hello.exe
[19:43:34] INFO PE file loaded successfully
[19:43:34] INFO Registering PE with kernel
[19:43:34] INFO ✅ PE registered with kernel successfully
[19:43:34] INFO 🚀 Executing PE via kernel module
[19:43:34] INFO Hello from Windows executable!
[19:43:34] INFO Program exited with code: 0src/pe-loader/pe_loader.c- Added kernel communication tope_execute()include/pe-loader/pe_loader.c- Added kernel client header
- Reboot to clear kernel module state OR investigate module reload
- Test PE registration with fresh kernel module
- Implement kernel-side execution if registration works
- Test end-to-end:
lsw --launch hello.exe→ kernel execution → output
- Wine took 30 years. LSW has kernel-level integration from day 1.
- This is the critical bridge that makes LSW actually RUN Windows programs.
- Once this works, we can test with Notepad++, then eventually gaming workloads.
🏴☠️ BFSL v1.2 - Building the Wine killer, one syscall at a time.