src/preload.c
download
#define open real_open
#define open64 real_open64
#define openat real_openat
#define openat64 real_openat64
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <zip.h>
#include <stdlib.h>
#include <string.h>
#undef open
#undef open64
#undef openat
#undef openat64
#define JNDI_LOOKUP_CLASS \
"org/apache/logging/log4j/core/lookup/JndiLookup.class"
typedef int (*openat_t)(int dirfd, const char *pathname,
int flags, mode_t mode);
typedef int (*open_t)(const char *pathname, int flags, mode_t mode);
static int
check_load_file(int dirfd, const char *pathname, int flags, mode_t mode) {
static openat_t real_openat64 = NULL;
if (!real_openat64) { real_openat64 = dlsym(RTLD_NEXT, "openat64"); }
int fd = real_openat64(dirfd, pathname, flags, mode);
printf("Checking file %s\n", pathname);
if (fd < 0) { return fd; }
int fd2 = real_openat64(dirfd, pathname, O_RDONLY, mode);
zip_t *zip = zip_fdopen(fd2, 0, NULL);
if (!zip) { close(fd2); return fd; }
zip_int64_t loc = zip_name_locate(zip, JNDI_LOOKUP_CLASS, 0);
if (loc < 0) { goto done_close_zip; }
close(fd); fd = -1;
if (dirfd != AT_FDCWD && pathname[0] != '/') {
fprintf(stderr, "TODO: Can't inspect readdirat() paths yet (libzip...)\n");
goto done_close_zip;
}
zip_close(zip);
zip = zip_open(pathname, 0, NULL);
if (!zip) { fprintf(stderr, "Reopen failed\n"); goto done_close_zip; }
loc = zip_name_locate(zip, JNDI_LOOKUP_CLASS, 0);
if (loc < 0) {
printf("JndiLookup disappeared?\n");
goto done_close_zip;
}
if (zip_delete(zip, loc) < 0) {
fprintf(stderr, "Zip modification failed: %s\n", zip_strerror(zip));
goto done_close_zip;
}
if (zip_close(zip) < 0) {
fprintf(stderr,"Could not save zip: %s\n", zip_strerror(zip));
return fd;
}
return real_openat64(dirfd, pathname, flags, mode);
done_close_zip:
if (zip_close(zip) < 0) {
fprintf(stderr,"Could not save zip: %s\n", zip_strerror(zip));
}
ret:
return fd;
}
int openat(int dirfd, const char *pathname, int flags, mode_t mode) {
printf("openat intercepted %d %s\n", dirfd, pathname);
return check_load_file(dirfd, pathname, flags, mode);
}
int openat64(int dirfd, const char *pathname, int flags, mode_t mode) {
printf("openat64 intercepted %d %s\n", dirfd, pathname);
return check_load_file(dirfd, pathname, flags, mode);
}
int open(const char *pathname, int flags, mode_t mode) {
Dl_info info1, info2;
if (dladdr(__builtin_return_address(0), &info1) &&
dladdr(&open, &info2) &&
info1.dli_fname == info2.dli_fname) {
static open_t real_open = NULL;
if (!real_open) { real_open = dlsym(RTLD_NEXT, "open"); }
printf("skipping self call %s\n", info1.dli_sname);
return real_open(pathname, flags, mode);
}
printf("open intercepted %s\n", pathname);
return check_load_file(AT_FDCWD, pathname, flags, mode);
}
int open64(const char *pathname, int flags, mode_t mode) {
printf("open64 intercepted %s\n", pathname);
return check_load_file(AT_FDCWD, pathname, flags, mode);
}