1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
6
|
|
7
|
|
8
|
|
9
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
15
|
|
16
|
|
17
|
|
18
|
|
19
|
|
20
|
|
21
|
#define _GNU_SOURCE
|
22
|
#include <dlfcn.h>
|
23
|
#include <err.h>
|
24
|
#include <fcntl.h>
|
25
|
#include <stdio.h>
|
26
|
#include <stdlib.h>
|
27
|
#include <string.h>
|
28
|
#include <linux/memfd.h>
|
29
|
#include <sys/mman.h>
|
30
|
#include <sys/sendfile.h>
|
31
|
#include <sys/syscall.h>
|
32
|
#include <sys/types.h>
|
33
|
#include <sys/stat.h>
|
34
|
#include <unistd.h>
|
35
|
|
36
|
#define LIBPULSE_SIMPLE "libpulse-simple.so.0"
|
37
|
|
38
|
#ifdef __NR_memfd_create
|
39
|
static inline int memfd_create(const char *name, unsigned int flags) {
|
40
|
return syscall(__NR_memfd_create, name, flags);
|
41
|
}
|
42
|
#else
|
43
|
#error "memfd_create syscall missing!"
|
44
|
#endif
|
45
|
|
46
|
static int check_pulseaudio_running(void) {
|
47
|
void *h;
|
48
|
pid_t pid;
|
49
|
int (*pa_pid_file_check_running)(pid_t *, const char *), running;
|
50
|
|
51
|
if(!(h = dlopen(LIBPULSE_SIMPLE, RTLD_LAZY))) {
|
52
|
warnx("Failed to resolve " LIBPULSE_SIMPLE);
|
53
|
|
54
|
return 0;
|
55
|
}
|
56
|
|
57
|
if(!(pa_pid_file_check_running = dlsym(h, "pa_pid_file_check_running")))
|
58
|
errx(1, "Failed to resolve symbol pa_pid_file_check_running");
|
59
|
|
60
|
running = (pa_pid_file_check_running(&pid, "pulseaudio") < 0) ? 0 : 1;
|
61
|
|
62
|
dlclose(h);
|
63
|
|
64
|
return running;
|
65
|
}
|
66
|
|
67
|
int main(int argc, char **argv) {
|
68
|
int fd, mfd;
|
69
|
char **args, *mem, *p;
|
70
|
ssize_t s;
|
71
|
struct stat stbuf;
|
72
|
|
73
|
if(argc < 2)
|
74
|
errx(1, "Usage: %s <program> [<arg1> ... <argN>]", argv[0]);
|
75
|
|
76
|
args = malloc(sizeof(char *) * argc);
|
77
|
if(!args)
|
78
|
err(1, "Failed to allocate argument vector");
|
79
|
|
80
|
for(int i = 1; i < argc; ++i)
|
81
|
args[i - 1] = strdup(argv[i]);
|
82
|
|
83
|
args[argc - 1] = NULL;
|
84
|
|
85
|
if(check_pulseaudio_running()) {
|
86
|
warnx("Pulseaudio is running");
|
87
|
|
88
|
execv(argv[1], args);
|
89
|
err(1, "Failed to exec '%s'", argv[1]);
|
90
|
}
|
91
|
else {
|
92
|
warnx("Pulseaudio is NOT running");
|
93
|
|
94
|
if((fd = open(argv[1], O_RDONLY | O_CLOEXEC)) < 0)
|
95
|
err(1, "Failed to open executable '%s'", argv[1]);
|
96
|
|
97
|
if(fstat(fd, &stbuf) < 0)
|
98
|
err(1, "Failed to stat executable");
|
99
|
|
100
|
if((mfd = memfd_create(argv[1], MFD_CLOEXEC)) < 0)
|
101
|
err(1, "Failed to create memfd");
|
102
|
|
103
|
if(ftruncate(mfd, stbuf.st_size) < 0)
|
104
|
err(1, "Failed to truncate memfd");
|
105
|
|
106
|
if((p = mem = mmap(NULL, stbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0)) == MAP_FAILED)
|
107
|
err(1, "Failed to mmap memfd");
|
108
|
|
109
|
while((s = read(fd, p, 64 * 1024 * 1024)) > 0)
|
110
|
p += s;
|
111
|
|
112
|
if(s < 0)
|
113
|
err(1, "Failed to load executable into memory");
|
114
|
|
115
|
if((p = memmem(mem, stbuf.st_size, LIBPULSE_SIMPLE, strlen(LIBPULSE_SIMPLE))) != NULL) {
|
116
|
strcpy(p, "/dev/null");
|
117
|
p += strlen("/dev/null") + 1;
|
118
|
while(*p)
|
119
|
*p++ = '\0';
|
120
|
|
121
|
warnx(LIBPULSE_SIMPLE " reference replaced");
|
122
|
}
|
123
|
else
|
124
|
warnx(LIBPULSE_SIMPLE " reference not found");
|
125
|
|
126
|
munmap(mem, stbuf.st_size);
|
127
|
|
128
|
fexecve(mfd, args, environ);
|
129
|
err(1, "Failed to exec '%s'", argv[1]);
|
130
|
}
|
131
|
}
|