Created
March 20, 2014 10:56
-
-
Save dvdhrm/9661331 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define _GNU_SOURCE | |
| #include <fcntl.h> | |
| #include <signal.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <sys/mman.h> | |
| #include <sys/stat.h> | |
| #include <unistd.h> | |
| int main(int argc, char **argv) | |
| { | |
| char *args[64]; | |
| struct stat st; | |
| sigset_t set; | |
| char path[128]; | |
| void *map; | |
| size_t size; | |
| int sig, fd_exe, fd_map, fd; | |
| pid_t pid; | |
| ssize_t res; | |
| /* | |
| * If called with arguments, we just act as a sleeping process that | |
| * waits for any signal to arrive. | |
| */ | |
| if (argc > 1) { | |
| printf("dummy waiter init\n"); | |
| /* dummy waiter; SIGTERM terminates us anyway */ | |
| sigemptyset(&set); | |
| sigaddset(&set, SIGTERM); | |
| sigwait(&set, &sig); | |
| printf("dummy waiter exit\n"); | |
| exit(0); | |
| } | |
| fd_exe = open("/proc/self/exe", O_RDONLY); | |
| if (fd_exe < 0) { | |
| printf("open(/proc/self/exe) failed: %m\n"); | |
| abort(); | |
| } | |
| if (fstat(fd_exe, &st) < 0) { | |
| printf("fstat(fd_exe) failed: %m\n"); | |
| abort(); | |
| } | |
| /* page-align */ | |
| size = (st.st_size + 4095ULL) & ~4095ULL; | |
| map = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, | |
| MAP_SHARED | MAP_ANONYMOUS, -1, 0); | |
| if (map == MAP_FAILED) { | |
| printf("mmap(MAP_ANON) failed: %m\n"); | |
| abort(); | |
| } | |
| res = read(fd_exe, map, st.st_size); | |
| if (res != st.st_size) { | |
| if (res < 0) | |
| printf("read(fd_exe) failed: %m\n"); | |
| else | |
| printf("read(fd_exe) was truncated to %zu\n", | |
| (size_t)res); | |
| abort(); | |
| } | |
| sprintf(path, "/proc/self/map_files/%lx-%lx", | |
| (unsigned long)map, | |
| (unsigned long)map + size); | |
| fd_map = open(path, O_RDONLY); | |
| if (fd_map < 0) { | |
| printf("open(%s) failed: %m\n", path); | |
| abort(); | |
| } | |
| pid = fork(); | |
| if (pid < 0) { | |
| printf("fork() failed: %m\n"); | |
| abort(); | |
| } else if (!pid) { | |
| args[0] = argv[0]; | |
| args[1] = "dummy"; | |
| args[2] = NULL; | |
| execve(path, args, NULL); | |
| printf("execve() failed: %m\n"); | |
| abort(); | |
| } | |
| /* sleep 100ms to make sure the execve() really worked */ | |
| usleep(100 * 1000ULL); | |
| sprintf(path, "/proc/self/fd/%d", fd_map); | |
| fd = open(path, O_RDWR); | |
| if (fd < 0) { | |
| printf("open(%s) failed: %m\n", path); | |
| abort(); | |
| } | |
| munmap(map, size); | |
| close(fd_exe); | |
| close(fd); | |
| close(fd_map); | |
| printf("exiting\n"); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment