-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhugeelfexec.c
73 lines (61 loc) · 1.88 KB
/
hugeelfexec.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// See also https://github.com/abbat/elfexec/blob/master/elfexec.c
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
void perror_exit(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
int memfd;
int binfd;
const char *binary_path;
struct stat binary_stat;
void *binary_addr;
void *mem_addr;
size_t size;
if (argc < 2)
{
fprintf(stderr, "Usage: %s /path/to/bin args-for-bin\n", argv[0]);
exit(1);
}
binary_path = argv[1];
if (access(binary_path, R_OK|X_OK))
perror_exit("access(binary)");
binfd = open(binary_path, O_RDONLY|O_CLOEXEC);
if (binfd < 0)
perror_exit("open(binary)");
if (fstat(binfd, &binary_stat))
perror_exit("stat(binary)");
size = binary_stat.st_size;
binary_addr = mmap(NULL, size, PROT_READ, MAP_SHARED, binfd, 0);
if (!binary_addr)
perror_exit("mmap(binary)");
// Do not uses MFD_HUGETLB to avoid hugetlbfs setup requirement
// Will use madvise(MADV_HUGEPAGE) later.
memfd = memfd_create("hugeelfexec", MFD_CLOEXEC);
if (!memfd)
perror_exit("memfd_create");
if (ftruncate(memfd, size))
perror_exit("ftruncate(memfd)");
mem_addr = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, memfd, 0);
if (!mem_addr)
perror_exit("mmap(memfd)");
// Required only if /sys/kernel/mm/transparent_hugepage/shmem_enabled == advise
if (madvise(mem_addr, size, MADV_HUGEPAGE))
perror_exit("madvise");
// Suboptimal
memcpy(mem_addr, binary_addr, size);
munmap(mem_addr, size);
munmap(binary_addr, size);
if (fexecve(memfd, &argv[1] /* skip "./hugeelfexec" */, environ) == -1)
perror_exit("fexecve");
return EXIT_SUCCESS;
}