Skip to content

Instantly share code, notes, and snippets.

@polprog
Created July 15, 2024 06:53
Show Gist options
  • Save polprog/1be8ed92910845f11add1e9bc7a03bb5 to your computer and use it in GitHub Desktop.
Save polprog/1be8ed92910845f11add1e9bc7a03bb5 to your computer and use it in GitHub Desktop.
memrun.c
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#ifndef NDEBUG
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#else
#define DEBUG(...)
#endif
/* memrun - load executable into memory and run it
* polprog 20.07.2023, version 1.0
* A modification of Guilherme Thomazi's implementation
* which runs the executable under a custom name,
* this version runs an executable with empty name.
*/
int main(int argc, char** argv, char** envp){
if(argc < 2) {
fprintf(stderr, "Give executable name\n");
return 1;
}
int target = open(argv[1], O_RDONLY);
DEBUG("file open: fd:%d\n", target);
struct stat file_stat;
fstat(target, &file_stat);
DEBUG("filesz = %d\n", file_stat.st_size);
void* tgt = mmap(NULL, file_stat.st_size, PROT_EXEC, MAP_PRIVATE, target, 0);
DEBUG("target in memory=%p\n", tgt);
close(target);
DEBUG("target fd closed\n");
//flags may be MFD_CLOEXEC, but it will fail on scripts.
//see fexecve man page part on ENOENT errno.
int memfd = memfd_create("", 0);
DEBUG("Memory fd = %d\n", memfd);
write(memfd, tgt, file_stat.st_size);
DEBUG("Running the memory executable...\n");
char* argv2[] = {(char*)0};
int rc = fexecve(memfd, argv2, envp);
//Guilherme's version
//int rc = execve("/proc/self/fd/3", argv2, envp);
//This should never print because we execve
if(errno) perror("fexecve(memfd, ..)");
DEBUG("Post fexecve, rc=%d\n", rc);
printf("ok\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment