18
#define MAX_FILES 1024
19
#define PIDFILE "/var/run/memlockd.pid"
21
typedef struct file_data
30
FILE_DATA files[MAX_FILES];
31
FILE_DATA new_files[MAX_FILES];
33
int num_new_files = 0;
34
const char * config = "/etc/memlockd.cfg";
41
void log(int priority, const char * const format, ...)
44
va_start(argp, format);
47
vfprintf(stderr, format, argp);
48
fprintf(stderr, "\n");
51
vsyslog(priority, format, argp);
54
void unmap_file(FILE_DATA *data)
56
munmap(data->start, data->sb.st_size);
57
log(LOG_INFO, "Unmapped file %s", data->name);
60
void unmap_close_file(FILE_DATA *data)
69
// return 1 if a file is mapped
70
int open_map(int fd, struct stat *sb, const char * const name)
72
new_files[num_new_files].start = mmap(NULL, sb->st_size, PROT_READ, MAP_SHARED, fd, 0);
73
if(new_files[num_new_files].start == MAP_FAILED)
75
log(LOG_ERR, "Error mmaping %s: %s", name, strerror(errno));
79
if(mlock(new_files[num_new_files].start, sb->st_size) == -1)
81
log(LOG_ERR, "Can't lock memory for %s, error %s", name, strerror(errno));
82
munmap(new_files[num_new_files].start, sb->st_size);
86
if(sb->st_size % PAGE_SIZE)
87
new_files[num_new_files].map_size = sb->st_size - (sb->st_size % PAGE_SIZE)
90
new_files[num_new_files].map_size = sb->st_size;
91
new_files[num_new_files].fd = fd;
92
memcpy(&new_files[num_new_files].sb, sb, sizeof(struct stat));
93
new_files[num_new_files].name = strdup(name);
95
log(LOG_INFO, "Mapped file %s", name);
99
int open_file(const char * const name)
101
int fd = open(name, O_RDONLY);
104
log(LOG_ERR, "Can't open file %s", name);
108
if(fstat(fd, &sb) == -1)
110
log(LOG_ERR, "Can't stat file %s", name);
115
for(i = 0; i < num_files; i++)
117
if(files[i].fd != -1 && files[i].sb.st_dev == sb.st_dev
118
&& files[i].sb.st_ino == sb.st_ino)
120
if(files[i].sb.st_size == sb.st_size
121
&& files[i].sb.st_mtime == sb.st_mtime)
123
memcpy(&new_files[num_new_files], &files[i], sizeof(FILE_DATA));
125
files[i].name = NULL;
131
memcpy(&new_files[num_new_files], &files[i], sizeof(FILE_DATA));
135
files[i].name = NULL;
136
unmap_file(&new_files[num_new_files - 1]);
137
open_map(new_files[num_new_files - 1].fd
138
, &new_files[num_new_files - 1].sb, name);
143
for(i = 0; i < num_new_files; i++)
145
if(new_files[i].fd != -1 && new_files[i].sb.st_ino == sb.st_ino)
151
return open_map(fd, &sb, name);
154
void map_file_dependencies(const char * const name)
160
if(pipe(pipe_fd) == -1)
162
log(LOG_ERR, "Can't create pipe, not recursing");
169
log(LOG_ERR, "Can't fork, not recursing");
179
if(dup2(pipe_fd[1], 1) == -1)
181
log(LOG_ERR, "Can't create pipe");
184
if(setresgid(gid, gid, gid) == -1 || setresuid(uid, uid, uid) == -1)
186
log(LOG_ERR, "Can't set UID and GID");
189
sprintf(buf, "/usr/bin/ldd %s", name);
191
argv[0] = strdup("/usr/bin/ldd");
192
argv[1] = strdup(name);
194
execv(argv[0], (char * const *)argv);
195
log(LOG_ERR, "Can't exec ldd");
199
FILE *fp = fdopen(pipe_fd[0], "r");
204
while(fgets(buf, sizeof(buf), fp))
206
char *tmp = strchr(buf, '/');
216
void parse_config(int)
218
FILE *fp = fopen(config, "r");
221
log(LOG_ERR, "Can't open config file %s", config);
226
while(fgets(buf, BUF_SIZE, fp))
228
int len = strlen(buf) - 1;
233
const char *ptr = buf;
234
int map_dependencies = 0;
238
map_dependencies = 1;
244
map_file_dependencies(ptr);
247
for(int i = 0; i < num_files; i++)
248
if(files[i].fd != -1)
249
unmap_close_file(&files[i]);
252
log(LOG_INFO, "No files to lock - exiting");
255
memcpy(files, new_files, sizeof(FILE_DATA) * num_new_files);
256
num_files = num_new_files;
262
fprintf(stderr, "Usage: memlockd [-c config-file] [-d]\n"
263
" -d is for debugging mode (running in foreground)\n");
266
int main(int argc, char **argv)
270
while(-1 != (c = getopt(argc, argv, "dc:u:")) )
285
struct passwd *pw = getpwnam(optarg);
288
log(LOG_ERR, "Can't look up user %s", optarg);
298
openlog("memlockd", LOG_CONS, LOG_DAEMON);
300
int write_pidfile = 1;
301
if(debug || getuid())
308
FILE *fp = fopen(PIDFILE, "r");
312
if(fgets(buf, sizeof(buf), fp))
315
log(LOG_ERR, "Can't read pidfile " PIDFILE);
320
if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1)
322
log(LOG_ERR, "Can't lock memory, exiting");
328
sa.sa_sigaction = NULL;
329
sa.sa_flags = SA_SIGINFO;
330
sa.sa_handler = parse_config;
331
if(sigaction(SIGHUP, &sa, NULL))
332
log(LOG_ERR, "Can't handle sighup");
335
FILE *fp = fopen(PIDFILE, "w");
338
if(fprintf(fp, "%d", (int)getpid()) <= 0)
340
log(LOG_ERR, "Can't write to " PIDFILE);
346
log(LOG_ERR, "Can't open " PIDFILE " for writing");
349
kill(old_pid, SIGKILL);