Compare commits

...

4 commits

Author SHA1 Message Date
Jeff Epler
3b4e63a696 (nonportable) print stack trace when enforcer fires
.. also, print all messages to stderr instead of stdout

backtrace() and backtrace_symbols_fd() are GNU extensions in libc
enabled by _GNU_SOURCE
2012-09-04 07:22:06 -05:00
Gergely Nagy
509b0c58b5 Cache the dlsym() results instead of looking up on each call
Instead of looking up the appropriate symbols on each call to open,
mkdir & the rest, use a constructor function to populate a few static
variables, which we'll use later instead of the repeated lookups.

Signed-off-by: Gergely Nagy <algernon@balabit.hu>
2012-09-04 10:28:49 +02:00
Gergely Nagy
12a342d1f9 enforcer(): Use abort() instead of exit(255)
By using abort(), the program has a chance to produce a core dump,
which one can use to determine where from the hard-coded /tmp stuff
was called from. It also makes it possible to determine which program
had this bug, by examining the core, a simple exit in a longer
pipeline may not be as helpful.

Signed-off-by: Gergely Nagy <algernon@balabit.hu>
2012-09-04 10:19:52 +02:00
Gergely Nagy
0869b206b9 Simplify enforcer(), and fix a memory leak
The enforcer() function allocated memory to copy the first N bytes of
the pathname to check, but never free()d it. The copy was unnecessary
too, as strncmp() can limit the number of bytes to check.

For these reasons, this patch simplifies the function by hard-coding
/tmp/ and its length, and getting rid of the malloc, and thus, the
memory leak.

Signed-off-by: Gergely Nagy <algernon@balabit.hu>
2012-09-04 10:17:27 +02:00

View file

@ -34,17 +34,41 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <execinfo.h>
#include "tmperamental.h"
static int (*orig_open2)(const char *, int);
static int (*orig_open3)(const char *, int, mode_t);
static int (*orig_mkdir)(const char *, mode_t);
static int (*orig_creat)(const char *, mode_t);
static FILE * (*orig_fopen)(const char *, const char *);
static FILE * (*orig_freopen)(const char *, const char *, FILE *);
static void tmperamental_init ( void ) __attribute__((constructor));
static void tmperamental_init ( void ) {
orig_open2 = dlsym(RTLD_NEXT, "open");
orig_open3 = dlsym(RTLD_NEXT, "open");
orig_mkdir = dlsym(RTLD_NEXT, "mkdir");
orig_creat = dlsym(RTLD_NEXT, "creat");
orig_fopen = dlsym(RTLD_NEXT, "fopen");
orig_freopen = dlsym(RTLD_NEXT, "freopen");
}
#define SIZE (100)
#define FIRST_FRAME (1)
void enforcer ( const char * pathname ) {
const char * to_check = "/tmp/";
int len = strlen( to_check );
char * leading = malloc(sizeof(char) * len);
strncpy ( leading, pathname, len );
if ( strcmp(to_check, leading) == 0 ) {
printf("tmperamental: caught a write to /tmp.\n");
exit(255);
if ( strncmp("/tmp/", pathname, 5) == 0 ) {
int nframes;
void *buffer[SIZE];
fprintf(stderr, "tmperamental: caught a write to /tmp.\n");
nframes = backtrace(buffer, SIZE);
if(nframes > FIRST_FRAME)
backtrace_symbols_fd(buffer+FIRST_FRAME, nframes+FIRST_FRAME, 2);
abort();
}
}
@ -55,40 +79,32 @@ int open ( const char * pathname, int flags, ... ) {
va_start(v, flags);
mode_t mode = va_arg(v, mode_t);
va_end(v);
if ( mode ) {
int (*orig_addr)(const char *, int, mode_t) = dlsym(RTLD_NEXT, "open");
return orig_addr(pathname, flags, mode);
} else {
int (*orig_addr)(const char *, int) = dlsym(RTLD_NEXT, "open");
return orig_addr(pathname, flags);
}
if ( mode )
return orig_open3(pathname, flags, mode);
else
return orig_open2(pathname, flags);
}
int mkdir ( const char *pathname, mode_t mode ) {
enforcer( pathname );
int (*orig_addr)(const char *, mode_t) = dlsym(RTLD_NEXT, "mkdir");
return orig_addr(pathname, mode);
return orig_mkdir(pathname, mode);
}
int creat ( const char *pathname, mode_t mode ) {
enforcer( pathname );
int (*orig_addr)(const char *, mode_t) = dlsym(RTLD_NEXT, "creat");
return orig_addr(pathname, mode);
return orig_creat(pathname, mode);
}
FILE * fopen ( const char * path, const char *mode ) {
enforcer(path);
FILE * (*orig_addr)(const char *, const char *) = dlsym(RTLD_NEXT, "fopen");
return orig_addr( path, mode );
return orig_fopen( path, mode );
}
FILE * freopen ( const char *path, const char *mode, FILE * stream ) {
enforcer(path);
FILE * (*orig_addr)(const char *, const char *, FILE *)
= dlsym(RTLD_NEXT, "freopen");
return orig_addr(path, mode, stream);
return orig_freopen(path, mode, stream);
}