Browse Source

Stefan Fiedler:


			
			
				rocklinux
			
			
		
Stefan Fiedler 17 years ago
parent
commit
14323571ca
6 changed files with 347 additions and 331 deletions
  1. +0
    -10
      misc/tools-source/fd_tracker.c
  2. +46
    -36
      misc/tools-source/fl_wrapper.c
  3. +8
    -266
      misc/tools-source/fl_wrapper.c.sh
  4. +24
    -17
      misc/tools-source/fl_wrapper_close.c
  5. +268
    -0
      misc/tools-source/fl_wrapper_internal.c
  6. +1
    -2
      scripts/Build-Tools

+ 0
- 10
misc/tools-source/fd_tracker.c

@ -1,15 +1,5 @@
/* /*
TODO:
get rid of the compiler warnings:
fl_wrapper.c: In function '_Exit':
fl_wrapper.c:1100: warning: 'noreturn' function does return
fl_wrapper.c: In function '_exit':
fl_wrapper.c:1075: warning: 'noreturn' function does return
fl_wrapper.c: In function 'exit':
fl_wrapper.c:1050: warning: 'noreturn' function does return
maybe TODO: maybe TODO:
wrape clone(); catch termination of child process created with clone() wrape clone(); catch termination of child process created with clone()
*/ */

+ 46
- 36
misc/tools-source/fl_wrapper.c

@ -37,7 +37,7 @@
/* Headers and prototypes */ /* Headers and prototypes */
#define DEBUG 0
#define DEBUG 1
#define DLOPEN_LIBC 1 #define DLOPEN_LIBC 1
#define FD_TRACKER 1 #define FD_TRACKER 1
@ -93,16 +93,6 @@ int debug = 0;
/* /*
TODO:
get rid of the compiler warnings:
fl_wrapper.c: In function '_Exit':
fl_wrapper.c:1100: warning: 'noreturn' function does return
fl_wrapper.c: In function '_exit':
fl_wrapper.c:1075: warning: 'noreturn' function does return
fl_wrapper.c: In function 'exit':
fl_wrapper.c:1050: warning: 'noreturn' function does return
maybe TODO: maybe TODO:
wrape clone(); catch termination of child process created with clone() wrape clone(); catch termination of child process created with clone()
*/ */
@ -1203,7 +1193,8 @@ int fork()
if ( rc == 0) copy_fds(caller_pid, getpid()); if ( rc == 0) copy_fds(caller_pid, getpid());
# endif # endif
# if DEBUG == 1
# if FD_TRACKER == 1
# if DEBUG == 1
struct pid_reg *pid = pid_head; struct pid_reg *pid = pid_head;
while (pid) while (pid)
{ {
@ -1218,14 +1209,14 @@ int fork()
} }
pid = pid->next; pid = pid->next;
} }
# endif
# endif # endif
errno=old_errno; errno=old_errno;
return rc; return rc;
} }
extern void exit(int status) __attribute__ ((noreturn)); extern void exit(int status) __attribute__ ((noreturn));
void (*orig_exit)(int status) = 0;
void (*orig_exit)(int status) __attribute__ ((noreturn)) = 0;
void exit(int status) void exit(int status)
{ {
@ -1241,11 +1232,13 @@ void exit(int status)
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
if (pid) if (pid)
{ {
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
struct fd_reg *fd_iter = pid->fd_head;
while (fd_iter)
{ {
handle_file_access_after("exit", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
struct fd_reg *new_fd_iter=fd_iter->next;
handle_file_access_after("exit", fd_iter->filename, &fd_iter->status);
deregister_fd(fd_iter->fd);
fd_iter=new_fd_iter;
} }
} }
# endif # endif
@ -1255,7 +1248,7 @@ void exit(int status)
} }
extern void _exit(int status) __attribute__ ((noreturn)); extern void _exit(int status) __attribute__ ((noreturn));
void (*orig__exit)(int status) = 0;
void (*orig__exit)(int status) __attribute__ ((noreturn)) = 0;
void _exit(int status) void _exit(int status)
{ {
@ -1271,11 +1264,13 @@ void _exit(int status)
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
if (pid) if (pid)
{ {
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
struct fd_reg *fd_iter = pid->fd_head;
while (fd_iter)
{ {
handle_file_access_after("_exit", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
struct fd_reg *new_fd_iter=fd_iter->next;
handle_file_access_after("_exit", fd_iter->filename, &fd_iter->status);
deregister_fd(fd_iter->fd);
fd_iter=new_fd_iter;
} }
} }
# endif # endif
@ -1285,7 +1280,7 @@ void _exit(int status)
} }
extern void _Exit(int status) __attribute__ ((noreturn)); extern void _Exit(int status) __attribute__ ((noreturn));
void (*orig__Exit)(int status) = 0;
void (*orig__Exit)(int status) __attribute__ ((noreturn)) = 0;
void _Exit(int status) void _Exit(int status)
{ {
@ -1301,11 +1296,13 @@ void _Exit(int status)
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
if (pid) if (pid)
{ {
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
struct fd_reg *fd_iter = pid->fd_head;
while (fd_iter)
{ {
handle_file_access_after("_Exit", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
struct fd_reg *new_fd_iter=fd_iter->next;
handle_file_access_after("_Exit", fd_iter->filename, &fd_iter->status);
deregister_fd(fd_iter->fd);
fd_iter=new_fd_iter;
} }
} }
# endif # endif
@ -1503,6 +1500,8 @@ int utimes(const char* f, struct timeval* t)
return rc; return rc;
} }
extern int fcntl(int fd, int cmd, ...);
extern int execv(const char* f, char* const a[]); extern int execv(const char* f, char* const a[]);
int (*orig_execv)(const char* f, char* const a[]) = 0; int (*orig_execv)(const char* f, char* const a[]) = 0;
@ -1513,6 +1512,7 @@ int execv(const char* f, char* const a[])
handle_file_access_after("execv", f, 0); handle_file_access_after("execv", f, 0);
if (!orig_execv) orig_execv = get_dl_symbol("execv"); if (!orig_execv) orig_execv = get_dl_symbol("execv");
if (!orig_fcntl) orig_fcntl = get_dl_symbol("fcntl");
# if FD_TRACKER == 1 # if FD_TRACKER == 1
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
@ -1522,7 +1522,7 @@ int execv(const char* f, char* const a[])
fd_iter = &pid->fd_head; fd_iter = &pid->fd_head;
while (*fd_iter != 0) 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; fd_iter = &(*fd_iter)->next;
} }
pid->executed = 1; pid->executed = 1;
@ -1555,6 +1555,8 @@ int execv(const char* f, char* const a[])
return rc; return rc;
} }
extern int fcntl(int fd, int cmd, ...);
extern int execve(const char* f, char* const a[], char* const e[]); extern int execve(const char* f, char* const a[], char* const e[]);
int (*orig_execve)(const char* f, char* const a[], char* const e[]) = 0; int (*orig_execve)(const char* f, char* const a[], char* const e[]) = 0;
@ -1565,6 +1567,7 @@ int execve(const char* f, char* const a[], char* const e[])
handle_file_access_after("execve", f, 0); handle_file_access_after("execve", f, 0);
if (!orig_execve) orig_execve = get_dl_symbol("execve"); if (!orig_execve) orig_execve = get_dl_symbol("execve");
if (!orig_fcntl) orig_fcntl = get_dl_symbol("fcntl");
# if FD_TRACKER == 1 # if FD_TRACKER == 1
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
@ -1574,7 +1577,7 @@ int execve(const char* f, char* const a[], char* const e[])
fd_iter = &pid->fd_head; fd_iter = &pid->fd_head;
while (*fd_iter != 0) 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; fd_iter = &(*fd_iter)->next;
} }
pid->executed = 1; pid->executed = 1;
@ -1642,19 +1645,24 @@ static void * get_dl_symbol(char * symname)
return rc; return rc;
} }
extern int open(const char* f, int a, ...);
static int pid2ppid(int pid) static int pid2ppid(int pid)
{ {
char buffer[100]; char buffer[100];
int fd, rc, ppid = 0; int fd, rc, ppid = 0;
if (!orig_open) orig_open = get_dl_symbol("open");
if (!orig_close) orig_close = get_dl_symbol("close");
sprintf(buffer, "/proc/%d/stat", pid); sprintf(buffer, "/proc/%d/stat", pid);
if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return 0;
if ( (fd = orig_open(buffer, O_RDONLY, 0)) < 0 ) return 0;
if ( (rc = read(fd, buffer, 99)) > 0) { if ( (rc = read(fd, buffer, 99)) > 0) {
buffer[rc] = 0; buffer[rc] = 0;
/* format: 27910 (bash) S 27315 ... */ /* format: 27910 (bash) S 27315 ... */
sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid); sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid);
} }
close(fd);
orig_close(fd);
return ppid; return ppid;
} }
@ -1669,14 +1677,14 @@ static char *getpname(int pid)
int i, fd, rc; int i, fd, rc;
sprintf(buffer, "/proc/%d/cmdline", pid); sprintf(buffer, "/proc/%d/cmdline", pid);
if ( (fd = open(buffer, O_RDONLY, 0)) < 0 ) return "unkown";
if ( (fd = orig_open(buffer, O_RDONLY, 0)) < 0 ) return "unkown";
if ( (rc = read(fd, buffer, 512)) > 0) { if ( (rc = read(fd, buffer, 512)) > 0) {
buffer[rc--] = 0; buffer[rc--] = 0;
for (i=0; i<rc; i++) for (i=0; i<rc; i++)
if (buffer[i] == 0 && buffer[i+1] != '-') if (buffer[i] == 0 && buffer[i+1] != '-')
{ arg = buffer+i+1; break; } { arg = buffer+i+1; break; }
} }
close(fd);
orig_close(fd);
b = basename(buffer); b = basename(buffer);
snprintf(p, 512, "%s", b); snprintf(p, 512, "%s", b);
@ -1748,12 +1756,13 @@ void __attribute__ ((destructor)) fl_wrapper_finish()
# if DEBUG == 1 # if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_finish()\n", getpid()); if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_finish()\n", getpid());
# endif # endif
# if FD_TRACKER == 1
struct pid_reg **pid = find_pid(getpid()); struct pid_reg **pid = find_pid(getpid());
if (*pid) if (*pid)
{ {
# if DEBUG == 1
# if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID still registered!\n", getpid()); if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID still registered!\n", getpid());
# endif
# endif
struct fd_reg **fd = &(*pid)->fd_head; struct fd_reg **fd = &(*pid)->fd_head;
while (*fd) while (*fd)
{ {
@ -1762,6 +1771,7 @@ void __attribute__ ((destructor)) fl_wrapper_finish()
} }
remove_pid(pid); remove_pid(pid);
} }
# endif
} }
static void handle_file_access_before(const char * func, const char * file, static void handle_file_access_before(const char * func, const char * file,

+ 8
- 266
misc/tools-source/fl_wrapper.c.sh

@ -42,7 +42,7 @@ cat << EOT
/* Headers and prototypes */ /* Headers and prototypes */
#define DEBUG 0
#define DEBUG 1
#define DLOPEN_LIBC 1 #define DLOPEN_LIBC 1
#define FD_TRACKER 1 #define FD_TRACKER 1
@ -107,7 +107,7 @@ add_wrapper()
ret_type=$1 ; shift ; function=$1 ; shift ret_type=$1 ; shift ; function=$1 ; shift
p1="" ; p2="" ; for x ; do p1="$p1$x, " ; done 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%, }" p1="${p1%, }" ; p2="${p2%, }"
if [ "${function#exec}" = "${function}" ] if [ "${function#exec}" = "${function}" ]
@ -142,6 +142,8 @@ $ret_type $function($p1)
EOT EOT
else else
echo ; cat << EOT echo ; cat << EOT
extern int fcntl(int fd, int cmd, ...);
extern $ret_type $function($p1); extern $ret_type $function($p1);
$ret_type (*orig_$function)($p1) = 0; $ret_type (*orig_$function)($p1) = 0;
@ -152,6 +154,7 @@ $ret_type $function($p1)
handle_file_access_after("$function", f, 0); handle_file_access_after("$function", f, 0);
if (!orig_$function) orig_$function = get_dl_symbol("$function"); if (!orig_$function) orig_$function = get_dl_symbol("$function");
if (!orig_fcntl) orig_fcntl = get_dl_symbol("fcntl");
# if FD_TRACKER == 1 # if FD_TRACKER == 1
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
@ -161,7 +164,7 @@ $ret_type $function($p1)
fd_iter = &pid->fd_head; fd_iter = &pid->fd_head;
while (*fd_iter != 0) 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; fd_iter = &(*fd_iter)->next;
} }
pid->executed = 1; 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, execv, const char* f, char* const a[]'
add_wrapper 'int, execve, const char* f, char* const a[], char* const e[]' 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

+ 24
- 17
misc/tools-source/fl_wrapper_close.c

@ -122,7 +122,8 @@ int fork()
if ( rc == 0) copy_fds(caller_pid, getpid()); if ( rc == 0) copy_fds(caller_pid, getpid());
# endif # endif
# if DEBUG == 1
# if FD_TRACKER == 1
# if DEBUG == 1
struct pid_reg *pid = pid_head; struct pid_reg *pid = pid_head;
while (pid) while (pid)
{ {
@ -137,14 +138,14 @@ int fork()
} }
pid = pid->next; pid = pid->next;
} }
# endif
# endif # endif
errno=old_errno; errno=old_errno;
return rc; return rc;
} }
extern void exit(int status) __attribute__ ((noreturn)); extern void exit(int status) __attribute__ ((noreturn));
void (*orig_exit)(int status) = 0;
void (*orig_exit)(int status) __attribute__ ((noreturn)) = 0;
void exit(int status) void exit(int status)
{ {
@ -160,11 +161,13 @@ void exit(int status)
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
if (pid) if (pid)
{ {
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
struct fd_reg *fd_iter = pid->fd_head;
while (fd_iter)
{ {
handle_file_access_after("exit", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
struct fd_reg *new_fd_iter=fd_iter->next;
handle_file_access_after("exit", fd_iter->filename, &fd_iter->status);
deregister_fd(fd_iter->fd);
fd_iter=new_fd_iter;
} }
} }
# endif # endif
@ -174,7 +177,7 @@ void exit(int status)
} }
extern void _exit(int status) __attribute__ ((noreturn)); extern void _exit(int status) __attribute__ ((noreturn));
void (*orig__exit)(int status) = 0;
void (*orig__exit)(int status) __attribute__ ((noreturn)) = 0;
void _exit(int status) void _exit(int status)
{ {
@ -190,11 +193,13 @@ void _exit(int status)
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
if (pid) if (pid)
{ {
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
struct fd_reg *fd_iter = pid->fd_head;
while (fd_iter)
{ {
handle_file_access_after("_exit", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
struct fd_reg *new_fd_iter=fd_iter->next;
handle_file_access_after("_exit", fd_iter->filename, &fd_iter->status);
deregister_fd(fd_iter->fd);
fd_iter=new_fd_iter;
} }
} }
# endif # endif
@ -204,7 +209,7 @@ void _exit(int status)
} }
extern void _Exit(int status) __attribute__ ((noreturn)); extern void _Exit(int status) __attribute__ ((noreturn));
void (*orig__Exit)(int status) = 0;
void (*orig__Exit)(int status) __attribute__ ((noreturn)) = 0;
void _Exit(int status) void _Exit(int status)
{ {
@ -220,11 +225,13 @@ void _Exit(int status)
struct pid_reg *pid = *find_pid(getpid()); struct pid_reg *pid = *find_pid(getpid());
if (pid) if (pid)
{ {
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
struct fd_reg *fd_iter = pid->fd_head;
while (fd_iter)
{ {
handle_file_access_after("_Exit", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
struct fd_reg *new_fd_iter=fd_iter->next;
handle_file_access_after("_Exit", fd_iter->filename, &fd_iter->status);
deregister_fd(fd_iter->fd);
fd_iter=new_fd_iter;
} }
} }
# endif # endif

+ 268
- 0
misc/tools-source/fl_wrapper_internal.c

@ -0,0 +1,268 @@
/* 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;
}
extern int open(const char* f, int a, ...);
static int pid2ppid(int pid)
{
char buffer[100];
int fd, rc, ppid = 0;
if (!orig_open) orig_open = get_dl_symbol("open");
if (!orig_close) orig_close = get_dl_symbol("close");
sprintf(buffer, "/proc/%d/stat", pid);
if ( (fd = orig_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);
}
orig_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 = orig_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; }
}
orig_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
# if FD_TRACKER == 1
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);
}
# endif
}
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
}

+ 1
- 2
scripts/Build-Tools

@ -262,8 +262,7 @@ EOT
if [ "$ROCKCFG_FLIST" = "flwrapper" ] ; then if [ "$ROCKCFG_FLIST" = "flwrapper" ] ; then
echo_status "Building $toolsdir/lib/fl_wrapper.so." echo_status "Building $toolsdir/lib/fl_wrapper.so."
$BUILDCC -Wall -O2 -ldl -fPIC -shared misc/tools-source/fl_wrapper.c \ $BUILDCC -Wall -O2 -ldl -fPIC -shared misc/tools-source/fl_wrapper.c \
-o build/$ROCKCFG_ID/ROCK/$toolsdir/lib/fl_wrapper.so.$$ \
2>/dev/null || exit 1
-o build/$ROCKCFG_ID/ROCK/$toolsdir/lib/fl_wrapper.so.$$ || exit 1
mv build/$ROCKCFG_ID/ROCK/$toolsdir/lib/fl_wrapper.so.$$ \ mv build/$ROCKCFG_ID/ROCK/$toolsdir/lib/fl_wrapper.so.$$ \
build/$ROCKCFG_ID/ROCK/$toolsdir/lib/fl_wrapper.so build/$ROCKCFG_ID/ROCK/$toolsdir/lib/fl_wrapper.so

Loading…
Cancel
Save