mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
6.8 KiB

  1. /* Internal Functions */
  2. static void * get_dl_symbol(char * symname)
  3. {
  4. void * rc;
  5. #if DLOPEN_LIBC
  6. static void * libc_handle = 0;
  7. if (!libc_handle) libc_handle=dlopen("libc.so.6", RTLD_LAZY);
  8. if (!libc_handle) {
  9. printf("fl_wrapper.so: Can't dlopen libc: %s\n", dlerror());
  10. abort();
  11. }
  12. rc = dlsym(libc_handle, symname);
  13. # if DEBUG == 1
  14. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' in libc (%p) has been resolved to %p.\n",
  15. getpid(), symname, libc_handle, rc);
  16. # endif
  17. #else
  18. rc = dlsym(RTLD_NEXT, symname);
  19. # if DEBUG == 1
  20. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: Symbol '%s' (RTLD_NEXT) has been resolved to %p.\n",
  21. getpid(), symname, rc);
  22. # endif
  23. #endif
  24. if (!rc) {
  25. printf("fl_wrapper.so: Can't resolve %s: %s\n",
  26. symname, dlerror());
  27. abort();
  28. }
  29. return rc;
  30. }
  31. extern int open(const char* f, int a, ...);
  32. static int pid2ppid(int pid)
  33. {
  34. char buffer[100];
  35. int fd, rc, ppid = 0;
  36. if (!orig_open) orig_open = get_dl_symbol("open");
  37. if (!orig_close) orig_close = get_dl_symbol("close");
  38. sprintf(buffer, "/proc/%d/stat", pid);
  39. if ( (fd = orig_open(buffer, O_RDONLY, 0)) < 0 ) return 0;
  40. if ( (rc = read(fd, buffer, 99)) > 0) {
  41. buffer[rc] = 0;
  42. /* format: 27910 (bash) S 27315 ... */
  43. sscanf(buffer, "%*[^ ] %*[^ ] %*[^ ] %d", &ppid);
  44. }
  45. orig_close(fd);
  46. return ppid;
  47. }
  48. /* this is only called from fl_wrapper_init(). so it doesn't need to be
  49. * reentrant. */
  50. static char *getpname(int pid)
  51. {
  52. static char p[512];
  53. char buffer[513]="";
  54. char *arg=0, *b;
  55. int i, fd, rc;
  56. sprintf(buffer, "/proc/%d/cmdline", pid);
  57. if ( (fd = orig_open(buffer, O_RDONLY, 0)) < 0 ) return "unkown";
  58. if ( (rc = read(fd, buffer, 512)) > 0) {
  59. buffer[rc--] = 0;
  60. for (i=0; i<rc; i++)
  61. if (buffer[i] == 0 && buffer[i+1] != '-')
  62. { arg = buffer+i+1; break; }
  63. }
  64. orig_close(fd);
  65. b = basename(buffer);
  66. snprintf(p, 512, "%s", b);
  67. if ( !strcmp(b, "bash") || !strcmp(b, "sh") ||
  68. !strcmp(b, "perl") || !strcmp(b, "python") )
  69. if ( arg && *arg &&
  70. strlen(arg) < 100 && !strchr(arg, '\n') &&
  71. !strchr(arg, ' ') && !strchr(arg, ';') )
  72. snprintf(p, 512, "%s(%s)", b, basename(arg));
  73. return p;
  74. }
  75. /* invert the order by recursion. there will be only one recursion tree
  76. * so we can use a static var for managing the last ent */
  77. static void addptree(int *txtpos, char *cmdtxt, int pid, int basepid)
  78. {
  79. static char l[512] = "";
  80. char *p;
  81. if (!pid || pid == basepid) return;
  82. addptree(txtpos, cmdtxt, pid2ppid(pid), basepid);
  83. p = getpname(pid);
  84. if (*txtpos < 4000)
  85. {
  86. if ( strcmp(l, p) )
  87. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "%s%s",
  88. *txtpos ? "." : "", getpname(pid));
  89. else
  90. *txtpos += snprintf(cmdtxt+*txtpos, 4096-*txtpos, "*");
  91. }
  92. strcpy(l, p);
  93. }
  94. void __attribute__ ((constructor)) fl_wrapper_init()
  95. {
  96. # if DEBUG == 1
  97. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_init()\n", getpid());
  98. # endif
  99. char cmdtxt[4096] = "";
  100. char *basepid_txt = getenv("FLWRAPPER_BASEPID");
  101. int basepid = 0, txtpos=0;
  102. if (basepid_txt)
  103. basepid = atoi(basepid_txt);
  104. addptree(&txtpos, cmdtxt, getpid(), basepid);
  105. cmdname = strdup(cmdtxt);
  106. wlog = getenv("FLWRAPPER_WLOG");
  107. rlog = getenv("FLWRAPPER_RLOG");
  108. # if DEBUG == 1
  109. char *debugwrapper = getenv("FLWRAPPER_DEBUG");
  110. if (debugwrapper) debug = atoi(debugwrapper);
  111. # endif
  112. }
  113. /*
  114. Clean up file descriptors still registered for this pid, if any.
  115. */
  116. void __attribute__ ((destructor)) fl_wrapper_finish()
  117. {
  118. # if DEBUG == 1
  119. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fl_wrapper_finish()\n", getpid());
  120. # endif
  121. # if FD_TRACKER == 1
  122. struct pid_reg **pid = find_pid(getpid());
  123. if (*pid)
  124. {
  125. # if DEBUG == 1
  126. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID still registered!\n", getpid());
  127. # endif
  128. struct fd_reg **fd = &(*pid)->fd_head;
  129. while (*fd)
  130. {
  131. handle_file_access_after("fl_wrapper_finish", (*fd)->filename, &(*fd)->status);
  132. remove_fd(fd);
  133. }
  134. remove_pid(pid);
  135. }
  136. # endif
  137. }
  138. static void handle_file_access_before(const char * func, const char * file,
  139. struct status_t * status)
  140. {
  141. struct stat st;
  142. # if DEBUG == 1
  143. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  144. getpid(), func, file);
  145. # endif
  146. if ( lstat(file,&st) ) {
  147. status->inode=0; status->size=0;
  148. status->mtime=0; status->ctime=0;
  149. } else {
  150. status->inode=st.st_ino; status->size=st.st_size;
  151. status->mtime=st.st_mtime; status->ctime=st.st_ctime;
  152. }
  153. # if DEBUG == 1
  154. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_before(\"%s\", \"%s\", xxx)\n",
  155. getpid(), func, file);
  156. # endif
  157. }
  158. /*
  159. Declared in fl_wrapper_open.c and fl_wrapper_close.c,
  160. reused here since logging access to the log files eventually
  161. overwrites close'd but not yet deregistered file descriptors.
  162. int (*orig_open)(const char* f, int a, ...) = 0;
  163. int (*orig_open64)(const char* f, int a, ...) = 0;
  164. int (*orig_close)(int fd) = 0;
  165. */
  166. static void handle_file_access_after(const char * func, const char * file,
  167. struct status_t * status)
  168. {
  169. char buf[512], *buf2, *logfile;
  170. int fd; struct stat st;
  171. #ifdef __USE_LARGEFILE
  172. if (!orig_open64) orig_open64 = get_dl_symbol("open64");
  173. #else
  174. if (!orig_open) orig_open = get_dl_symbol("open");
  175. #endif
  176. if (!orig_close) orig_close = get_dl_symbol("close");
  177. # if DEBUG == 1
  178. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: begin of handle_file_access_after(\"%s\", \"%s\", xxx), %d, %s, %s\n",
  179. getpid(), func, file, status != 0, wlog, rlog);
  180. # endif
  181. if ( lstat(file, &st) )
  182. {
  183. # if DEBUG == 1
  184. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: lstat(%s, ...) failed\n",
  185. getpid(), file);
  186. # endif
  187. return;
  188. }
  189. if ( (status != 0) && (status->inode != st.st_ino ||
  190. status->size != st.st_size || status->mtime != st.st_mtime ||
  191. status->ctime != st.st_ctime) ) { logfile = wlog; }
  192. else { logfile = rlog; }
  193. if ( logfile == 0 )
  194. {
  195. # if DEBUG == 1
  196. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: no log file\n",
  197. getpid());
  198. # endif
  199. return;
  200. }
  201. #ifdef __USE_LARGEFILE
  202. fd=orig_open64(logfile,O_APPEND|O_WRONLY|O_LARGEFILE,0);
  203. #else
  204. #warning "The wrapper library will not work properly for large logs!"
  205. fd=orig_open(logfile,O_APPEND|O_WRONLY,0);
  206. #endif
  207. if (fd == -1)
  208. {
  209. # if DEBUG == 1
  210. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: log open failed (%s)\n",
  211. getpid(), strerror(errno));
  212. # endif
  213. return;
  214. }
  215. if (file[0] == '/') {
  216. sprintf(buf,"%s.%s:\t%s\n",
  217. cmdname, func, file);
  218. } else {
  219. buf2=get_current_dir_name();
  220. sprintf(buf,"%s.%s:\t%s%s%s\n",
  221. cmdname, func, buf2,
  222. strcmp(buf2,"/") ? "/" : "", file);
  223. free(buf2);
  224. }
  225. write(fd,buf,strlen(buf));
  226. orig_close(fd);
  227. # if DEBUG == 1
  228. if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: end of handle_file_access_after(\"%s\", \"%s\", xxx)\n",
  229. getpid(), func, file);
  230. # endif
  231. }