|
|
@ -42,7 +42,7 @@ cat << EOT |
|
|
|
|
|
|
|
/* Headers and prototypes */ |
|
|
|
|
|
|
|
#define DEBUG 0 |
|
|
|
#define DEBUG 1 |
|
|
|
#define DLOPEN_LIBC 1 |
|
|
|
#define FD_TRACKER 1 |
|
|
|
|
|
|
@ -107,7 +107,7 @@ add_wrapper() |
|
|
|
|
|
|
|
ret_type=$1 ; shift ; function=$1 ; shift |
|
|
|
p1="" ; p2="" ; for x ; do p1="$p1$x, " ; done |
|
|
|
for x ; do x="${x%%\[\]}" ; p2="$p2${x##* }, " ; done |
|
|
|
for x ; do x="${x%%'[]'}" ; p2="$p2${x##* }, " ; done |
|
|
|
p1="${p1%, }" ; p2="${p2%, }" |
|
|
|
|
|
|
|
if [ "${function#exec}" = "${function}" ] |
|
|
@ -142,6 +142,8 @@ $ret_type $function($p1) |
|
|
|
EOT |
|
|
|
else |
|
|
|
echo ; cat << EOT |
|
|
|
extern int fcntl(int fd, int cmd, ...); |
|
|
|
|
|
|
|
extern $ret_type $function($p1); |
|
|
|
$ret_type (*orig_$function)($p1) = 0; |
|
|
|
|
|
|
@ -152,6 +154,7 @@ $ret_type $function($p1) |
|
|
|
|
|
|
|
handle_file_access_after("$function", f, 0); |
|
|
|
if (!orig_$function) orig_$function = get_dl_symbol("$function"); |
|
|
|
if (!orig_fcntl) orig_fcntl = get_dl_symbol("fcntl"); |
|
|
|
|
|
|
|
# if FD_TRACKER == 1 |
|
|
|
struct pid_reg *pid = *find_pid(getpid()); |
|
|
@ -161,7 +164,7 @@ $ret_type $function($p1) |
|
|
|
fd_iter = &pid->fd_head; |
|
|
|
while (*fd_iter != 0) |
|
|
|
{ |
|
|
|
(*fd_iter)->closed = fcntl((*fd_iter)->fd, F_GETFD) & FD_CLOEXEC; |
|
|
|
(*fd_iter)->closed = orig_fcntl((*fd_iter)->fd, F_GETFD) & FD_CLOEXEC; |
|
|
|
fd_iter = &(*fd_iter)->next; |
|
|
|
} |
|
|
|
pid->executed = 1; |
|
|
@ -220,266 +223,5 @@ add_wrapper 'int, utimes, const char* f, struct timeval* t' |
|
|
|
add_wrapper 'int, execv, const char* f, char* const a[]' |
|
|
|
add_wrapper 'int, execve, const char* f, char* const a[], char* const e[]' |
|
|
|
|
|
|
|
echo ; cat << "EOT" |
|
|
|
/* Internal Functions */ |
|
|
|
|
|
|
|
static void * get_dl_symbol(char * symname) |
|
|
|
{ |
|
|
|
void * rc; |
|
|
|
#if DLOPEN_LIBC |
|
|
|
static void * libc_handle = 0; |
|
|
|
|
|
|
|
if (!libc_handle) libc_handle=dlopen("libc.so.6", RTLD_LAZY); |
|
|
|
if (!libc_handle) { |
|
|
|
printf("fl_wrapper.so: Can't dlopen libc: %s\n", dlerror()); |
|
|
|
abort(); |
|
|
|
} |
|
|
|
|
|
|
|
rc = dlsym(libc_handle, symname); |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' in libc (%p) has been resolved to %p.\n", |
|
|
|
getpid(), symname, libc_handle, rc); |
|
|
|
# endif |
|
|
|
#else |
|
|
|
rc = dlsym(RTLD_NEXT, symname); |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n", |
|
|
|
getpid(), symname, rc); |
|
|
|
# endif |
|
|
|
#endif |
|
|
|
if (!rc) { |
|
|
|
printf("fl_wrapper.so: Can't resolve %s: %s\n", |
|
|
|
symname, dlerror()); |
|
|
|
abort(); |
|
|
|
} |
|
|
|
|
|
|
|
return rc; |
|
|
|
} |
|
|
|
|
|
|
|
static int pid2ppid(int pid) |
|
|
|
{ |
|
|
|
char buffer[100]; |
|
|
|
int fd, rc, ppid = 0; |
|
|
|
|
|
|
|
sprintf(buffer, "/proc/%d/stat", pid); |
|
|
|
if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return 0; |
|
|
|
if ( (rc = read(fd, buffer, 99)) > 0) { |
|
|
|
buffer[rc] = 0; |
|
|
|
/* format: 27910 (bash) S 27315 ... */ |
|
|
|
sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid); |
|
|
|
} |
|
|
|
close(fd); |
|
|
|
|
|
|
|
return ppid; |
|
|
|
} |
|
|
|
|
|
|
|
/* this is only called from fl_wrapper_init(). so it doesn't need to be |
|
|
|
* reentrant. */ |
|
|
|
static char *getpname(int pid) |
|
|
|
{ |
|
|
|
static char p[512]; |
|
|
|
char buffer[513]=""; |
|
|
|
char *arg=0, *b; |
|
|
|
int i, fd, rc; |
|
|
|
|
|
|
|
sprintf(buffer, "/proc/%d/cmdline", pid); |
|
|
|
if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return "unkown"; |
|
|
|
if ( (rc = read(fd, buffer, 512)) > 0) { |
|
|
|
buffer[rc--] = 0; |
|
|
|
for (i=0; i<rc; i++) |
|
|
|
if (buffer[i] == 0 && buffer[i+1] != '-') |
|
|
|
{ arg = buffer+i+1; break; } |
|
|
|
} |
|
|
|
close(fd); |
|
|
|
|
|
|
|
b = basename(buffer); |
|
|
|
snprintf(p, 512, "%s", b); |
|
|
|
|
|
|
|
if ( !strcmp(b, "bash") || !strcmp(b, "sh") || |
|
|
|
!strcmp(b, "perl") || !strcmp(b, "python") ) |
|
|
|
if ( arg && *arg && |
|
|
|
strlen(arg) < 100 && !strchr(arg, '\n') && |
|
|
|
!strchr(arg, ' ') && !strchr(arg, ';') ) |
|
|
|
snprintf(p, 512, "%s(%s)", b, basename(arg)); |
|
|
|
|
|
|
|
return p; |
|
|
|
} |
|
|
|
|
|
|
|
/* invert the order by recursion. there will be only one recursion tree |
|
|
|
* so we can use a static var for managing the last ent */ |
|
|
|
static void addptree(int *txtpos, char *cmdtxt, int pid, int basepid) |
|
|
|
{ |
|
|
|
static char l[512] = ""; |
|
|
|
char *p; |
|
|
|
|
|
|
|
if (!pid || pid == basepid) return; |
|
|
|
|
|
|
|
addptree(txtpos, cmdtxt, pid2ppid(pid), basepid); |
|
|
|
|
|
|
|
p = getpname(pid); |
|
|
|
|
|
|
|
if (*txtpos < 4000) |
|
|
|
{ |
|
|
|
if ( strcmp(l, p) ) |
|
|
|
*txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "%s%s", |
|
|
|
*txtpos ? "." : "", getpname(pid)); |
|
|
|
else |
|
|
|
*txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "*"); |
|
|
|
} |
|
|
|
|
|
|
|
strcpy(l, p); |
|
|
|
} |
|
|
|
|
|
|
|
void __attribute__ ((constructor)) fl_wrapper_init() |
|
|
|
{ |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_init()\n", getpid()); |
|
|
|
# endif |
|
|
|
|
|
|
|
char cmdtxt[4096] = ""; |
|
|
|
char *basepid_txt = getenv("FLWRAPPER_BASEPID"); |
|
|
|
int basepid = 0, txtpos=0; |
|
|
|
|
|
|
|
if (basepid_txt) |
|
|
|
basepid = atoi(basepid_txt); |
|
|
|
|
|
|
|
addptree(&txtpos, cmdtxt, getpid(), basepid); |
|
|
|
cmdname = strdup(cmdtxt); |
|
|
|
|
|
|
|
wlog = getenv("FLWRAPPER_WLOG"); |
|
|
|
rlog = getenv("FLWRAPPER_RLOG"); |
|
|
|
# if DEBUG == 1 |
|
|
|
char *debugwrapper = getenv("FLWRAPPER_DEBUG"); |
|
|
|
if (debugwrapper) debug = atoi(debugwrapper); |
|
|
|
# endif |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
Clean up file descriptors still registered for this pid, if any. |
|
|
|
*/ |
|
|
|
void __attribute__ ((destructor)) fl_wrapper_finish() |
|
|
|
{ |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_finish()\n", getpid()); |
|
|
|
# endif |
|
|
|
struct pid_reg **pid = find_pid(getpid()); |
|
|
|
if (*pid) |
|
|
|
{ |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID still registered!\n", getpid()); |
|
|
|
# endif |
|
|
|
struct fd_reg **fd = &(*pid)->fd_head; |
|
|
|
while (*fd) |
|
|
|
{ |
|
|
|
handle_file_access_after("fl_wrapper_finish", (*fd)->filename, &(*fd)->status); |
|
|
|
remove_fd(fd); |
|
|
|
} |
|
|
|
remove_pid(pid); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void handle_file_access_before(const char * func, const char * file, |
|
|
|
struct status_t * status) |
|
|
|
{ |
|
|
|
struct stat st; |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n", |
|
|
|
getpid(), func, file); |
|
|
|
# endif |
|
|
|
if ( lstat(file,&st) ) { |
|
|
|
status->inode=0; status->size=0; |
|
|
|
status->mtime=0; status->ctime=0; |
|
|
|
} else { |
|
|
|
status->inode=st.st_ino; status->size=st.st_size; |
|
|
|
status->mtime=st.st_mtime; status->ctime=st.st_ctime; |
|
|
|
} |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n", |
|
|
|
getpid(), func, file); |
|
|
|
# endif |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
Declared in fl_wrapper_open.c and fl_wrapper_close.c, |
|
|
|
reused here since logging access to the log files eventually |
|
|
|
overwrites close'd but not yet deregistered file descriptors. |
|
|
|
|
|
|
|
int (*orig_open)(const char* f, int a, ...) = 0; |
|
|
|
int (*orig_open64)(const char* f, int a, ...) = 0; |
|
|
|
int (*orig_close)(int fd) = 0; |
|
|
|
*/ |
|
|
|
|
|
|
|
static void handle_file_access_after(const char * func, const char * file, |
|
|
|
struct status_t * status) |
|
|
|
{ |
|
|
|
char buf[512], *buf2, *logfile; |
|
|
|
int fd; struct stat st; |
|
|
|
|
|
|
|
#ifdef __USE_LARGEFILE |
|
|
|
if (!orig_open64) orig_open64 = get_dl_symbol("open64"); |
|
|
|
#else |
|
|
|
if (!orig_open) orig_open = get_dl_symbol("open"); |
|
|
|
#endif |
|
|
|
if (!orig_close) orig_close = get_dl_symbol("close"); |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx), %d, %s, %s\n", |
|
|
|
getpid(), func, file, status != 0, wlog, rlog); |
|
|
|
# endif |
|
|
|
|
|
|
|
if ( lstat(file, &st) ) |
|
|
|
{ |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: lstat(%s, ...) failed\n", |
|
|
|
getpid(), file); |
|
|
|
# endif |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ( (status != 0) && (status->inode != st.st_ino || |
|
|
|
status->size != st.st_size || status->mtime != st.st_mtime || |
|
|
|
status->ctime != st.st_ctime) ) { logfile = wlog; } |
|
|
|
else { logfile = rlog; } |
|
|
|
|
|
|
|
if ( logfile == 0 ) |
|
|
|
{ |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: no log file\n", |
|
|
|
getpid()); |
|
|
|
# endif |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef __USE_LARGEFILE |
|
|
|
fd=orig_open64(logfile,O_APPEND|O_WRONLY|O_LARGEFILE,0); |
|
|
|
#else |
|
|
|
#warning "The wrapper library will not work properly for large logs!" |
|
|
|
fd=orig_open(logfile,O_APPEND|O_WRONLY,0); |
|
|
|
#endif |
|
|
|
|
|
|
|
if (fd == -1) |
|
|
|
{ |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: log open failed (%s)\n", |
|
|
|
getpid(), strerror(errno)); |
|
|
|
# endif |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (file[0] == '/') { |
|
|
|
sprintf(buf,"%s.%s:\t%s\n", |
|
|
|
cmdname, func, file); |
|
|
|
} else { |
|
|
|
buf2=get_current_dir_name(); |
|
|
|
sprintf(buf,"%s.%s:\t%s%s%s\n", |
|
|
|
cmdname, func, buf2, |
|
|
|
strcmp(buf2,"/") ? "/" : "", file); |
|
|
|
free(buf2); |
|
|
|
} |
|
|
|
write(fd,buf,strlen(buf)); |
|
|
|
orig_close(fd); |
|
|
|
# if DEBUG == 1 |
|
|
|
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n", |
|
|
|
getpid(), func, file); |
|
|
|
# endif |
|
|
|
} |
|
|
|
EOT |
|
|
|
echo |
|
|
|
cat fl_wrapper_internal.c |