LISTING 1 - SIMPLE PROGRAM TO REORDER LINES ------------------------------------------- #include #include #include #include #define BSZ 128 /* input buffer size */ #define MAXLINE 100000 /* lines stored */ char *lines[MAXLINE]; char buf[32]; /* BUG FIX #2: change 32 to BSZ */ int nlines; char * append(const char *str1, const char *str2) { int n = strlen(str1) + strlen(str2) + 1; char *p = malloc(n); if (p != NULL) { strcpy(p, str1); strcat(p, str2); } return(p); } void printrandom() { long idx = random() % nlines; fputs(lines[idx], stdout); /* free(lines[idx]); BUG FIX #3: add this line */ lines[idx] = lines[--nlines]; } int main() { int n, doappend; char *str, *ostr; close(0); /* BUG FIX #1: remove this line */ srandom(time(NULL)); nlines = 0; doappend = 0; str = NULL; while (fgets(buf, BSZ, stdin) != NULL) { n = strlen(buf); if (n == BSZ-1 && buf[BSZ-2] != '\n') doappend = 1; else doappend = 0; if (str != NULL) { ostr = str; str = append(ostr, buf); while (str == NULL) { printrandom(); str = append(ostr, buf); } free(ostr); } else { str = strdup(buf); while (str == NULL) { printrandom(); str = strdup(buf); } } if (!doappend) { if (nlines == MAXLINE) printrandom(); lines[nlines++] = str; str = NULL; } } while (nlines != 0) printrandom(); exit(0); } LISTING 2 - OUTPUT FROM strace ------------------------------ execve("./reorder", ["./reorder"], [/* 37 vars */]) = 0 ... (shared library access lined elided) close(0) =0 fstat(0, 0x7fff9e553e80) = -1 EBADF (Bad file descriptor) read(0, 0x7fe8e866e000, 8192) = -1 EBADF (Bad file descriptor) exit_group(0) = ? LISTING 3 - OUTPUT FROM gdb --------------------------- (gdb) run : 53 '5' 54 '6' 55 '7' 56 '8' (gdb) x/40c buf 0x6010a0 : 10 '\n' 0 '\000' 53 '5' 54 '6' 55 '7' 56 '8' 57 '9' 48 '0' 0x6010a8 : 49 '1' 50 '2' 51 '3' 52 '4' 53 '5' 54 '6' 55 '7' 56 '8' 0x6010b0 : 57 '9' 48 '0' 49 '1' 50 '2' 51 '3' 52 '4' 53 '5' 54 '6' 0x6010b8 : 55 '7' 56 '8' 57 '9' 48 '0' 49 '1' 50 '2' 51 '3' 52 '4' 0x6010c0 : 53 '5' 54 '6' 55 '7' 56 '8' 57 '9' 48 '0' 49 '1' 50 '2' LISTING 4 - OUTPUT FROM valgrind -------------------------------- ==5129== Memcheck, a memory error detector ==5129== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==5129== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==5129== Command: ./reorder ==5129== ==5129== ==5129== HEAP SUMMARY: ==5129== in use at exit: 81 bytes in 10 blocks ==5129== total heap usage: 10 allocs, 0 frees, 81 bytes allocated ==5129== ==5129== 32 bytes in 4 blocks are definitely lost in loss record 1 of 2 ==5129== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5129== by 0x4EBAD81: strdup (strdup.c:43) ==5129== by 0x400A4D: main (reorder.c:60) ==5129== ==5129== LEAK SUMMARY: ==5129== definitely lost: 32 bytes in 4 blocks ==5129== indirectly lost: 0 bytes in 0 blocks ==5129== possibly lost: 0 bytes in 0 blocks ==5129== still reachable: 49 bytes in 6 blocks ==5129== suppressed: 0 bytes in 0 blocks ==5129== Reachable blocks (those to which a pointer was found) are not shown. ==5129== To see them, rerun with: --leak-check=full --show-reachable=yes ==5129== ==5129== For counts of detected and suppressed errors, rerun with: -v ==5129== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2) LISTING 5 - SAMPLE SYSTEMTAP SCRIPT ----------------------------------- %{ #include %} probe begin { printf("Starting probe. Hit ^C to stop\n"); } function get_maxfds:long(fs:long) %{ struct files_struct *p; struct fdtable *f; long maxfd; p = (struct files_struct *)THIS->fs; f = kread(&(p->fdt)); rcu_read_lock(); maxfd = kread(&(f->max_fds)); rcu_read_unlock(); THIS->__retvalue = maxfd; CATCH_DEREF_FAULT(); %} function get_long:long(fs:long, idx:long) %{ struct files_struct *p; struct fdtable *f; fd_set *s; long val; p = (struct files_struct *)THIS->fs; f = kread(&(p->fdt)); rcu_read_lock(); s = kread(&(f->open_fds)); val = kread(&(s->fds_bits[THIS->idx])); rcu_read_unlock(); THIS->__retvalue = val; CATCH_DEREF_FAULT(); %} function get_sizeoflong() %{ THIS->__retvalue = sizeof(long); CATCH_DEREF_FAULT(); %} probe kernel.function("flush_old_files").return { printf("process %s: open fds", execname()); max_fds = get_maxfds($files); i = 0; word = 0; sol = get_sizeoflong(); while (i < max_fds) { bits = get_long($files, word); word++; for (j = 0; j < 8*sol; j++) { if (bits & 1) printf(" %d", i); bits >>= 1; i++; if (i >= max_fds) break; } } printf("\n"); } LISTING 6 - OUTPUT GENERATED BY RUNNING THE SYSTEMTAP SCRIPT FROM LISTING 5 --------------------------------------------------------------------------- $ sudo stap -g openfiles.stp Starting probe. Hit ^C to stop process ls: open fds 0 1 2 process ps: open fds 0 1 2 process who: open fds 0 1 2 process bash: open fds 0 1 2 process groups: open fds 0 1 2 process lesspipe: open fds 0 1 2 process basename: open fds 0 1 2 process dirname: open fds 0 1 2 process dircolors: open fds 0 1 2 process uname: open fds 0 1 2 process sed: open fds 0 1 2 process ls: open fds 0 1 2 process uname: open fds 0 1 2 process sed: open fds 0 1 2