Skip to content

Instantly share code, notes, and snippets.

@kotenok2000
Created August 9, 2025 14:27
Show Gist options
  • Save kotenok2000/81efed371e08e5afacac147152527fa3 to your computer and use it in GitHub Desktop.
Save kotenok2000/81efed371e08e5afacac147152527fa3 to your computer and use it in GitHub Desktop.
wsl1 exec format error fix
Given that Microsoft has effectively deprioritized addressing core issues in WSL1, I’ve implemented a workaround for this issue with ELF binaries.
The solution uses a custom wrapper (elf_wrapper.c) with ld.so.preload to automatically intercept and redirect ELF execution through /lib64/ld-linux-x86-64.so.2, enabling system-wide compatibility without user intervention. Unlike direct invocations of /lib64/ld-linux-x86-64.so.2, this approach captures ELF execution at the system level, eliminating the need for wrapper scripts, shell aliases, or direct binary modifications with patchelf.
elf_wrapper.c source code:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
// Path to the ELF interpreter used to execute ELF binaries
static const char *ld_linux_so = "/lib64/ld-linux-x86-64.so.2";
// Pointer to the original execve function
static int (*original_execve)(const char *filename, char *const argv[], char *const envp[]) = NULL;
// Wrapper function for execve
int execve(const char *filename, char *const argv[], char *const envp[]) {
if (!original_execve) {
// Load the original execve function
original_execve = dlsym(RTLD_NEXT, "execve");
}
// Check if the original file has the SUID bit set
struct stat file_stat;
if (stat(filename, &file_stat) == 0 && (file_stat.st_mode & S_ISUID)) {
// If the SUID bit is set, call the original execve directly
return original_execve(filename, argv, envp);
}
// Check if the file is an ELF binary
FILE *file = fopen(filename, "rb");
if (file) {
char magic[4];
fread(magic, 1, 4, file);
fclose(file);
// Check the ELF magic number: 0x7f 0x45 0x4c 0x46
if (memcmp(magic, "\x7f""ELF", 4) == 0) {
int argc;
for (argc = 0; argv[argc] != NULL; argc++);
char **new_argv = malloc((argc + 2) * sizeof(char *));
new_argv[0] = (char *)ld_linux_so;
new_argv[1] = (char *)filename;
int i;
for (i = 1; i < argc; i++) {
if (argv[i] != NULL) {
new_argv[i + 1] = argv[i];
}
}
new_argv[i + 1] = NULL; // Finalize the array with NULL
// Execute the binary with the ELF interpreter
int result = original_execve(ld_linux_so, new_argv, envp);
free(new_argv);
return result;
}
}
// If not ELF, execute normally
return original_execve(filename, argv, envp);
}
Run:
sudo gcc -shared -fPIC -o /usr/local/lib/libelf_wrapper.so elf_wrapper.c -ldl
echo "/usr/local/lib/libelf_wrapper.so" | sudo tee -a /etc/ld.so.preload
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment