Date: Thu, 11 Nov 2010 23:03:06 GMT From: Bron Gondwana <brong@fastmail.fm> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/152151: truss causes programs to open fd number 2, clobbering random files Message-ID: <201011112303.oABN362Z040540@www.freebsd.org> Resent-Message-ID: <201011112310.oABNABaD025185@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 152151 >Category: bin >Synopsis: truss causes programs to open fd number 2, clobbering random files >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Nov 11 23:10:11 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Bron Gondwana >Release: 8.1 >Organization: FastMail.FM >Environment: FreeBSD cyrus1.surfcloud.nl 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul 19 02:36:49 UTC 2010 root@mason.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64 >Description: Truss attempts to protect its output file from the environment: /* * Set FD_CLOEXEC, so that the output file is not shared with * the traced process. */ if (fcntl(fileno(trussinfo->outfile), F_SETFD, FD_CLOEXEC) == -1) warn("fcntl()"); Unfortunately, this has the side effect of making the same fd available to the executed program. Above, this was set to stderr. trussinfo->outfile = stderr; So when the executed program later tries to report an issue to stderr, it gets written to whatever file was unlucky enough to be opened with fd 2. The case that lead me to investigating this was a Cyrus IMAPd reconstruct program being run under truss causing the error code to be written right over the header of the main database. Not cool. >How-To-Repeat: Here's a little test case someone on the #freebsd channel put together. 1. monte-cristo!abbe:~ % truss ./test 2. __sysctl(0x7fffffffe310,0x2,0x7fffffffe32c,0x7fffffffe320,0x0,0x0) = 0 (0x0) 3. mmap(0x0,672,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34365177856 (0x800530000) 4. munmap(0x800530000,672) = 0 (0x0) 5. __sysctl(0x7fffffffe380,0x2,0x800639428,0x7fffffffe378,0x0,0x0) = 0 (0x0) 6. mmap(0x0,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365177856 (0x800530000) 7. issetugid(0x800531015,0x80052acc4,0x800645c50,0x800645c20,0x6351,0x0) = 0 (0x0) 8. open("/etc/libmap.conf",O_RDONLY,0666) ERR#2 'No such file or directory' 9. open("/var/run/ld-elf.so.hints",O_RDONLY,057) = 2 (0x2) 10. read(2,"Ehnt\^A\0\0\0\M^@\0\0\0\M-*\0\0"...,128) = 128 (0x80) 11. lseek(2,0x80,SEEK_SET) = 128 (0x80) 12. read(2,"/lib:/usr/lib:/usr/lib/compat:/u"...,170) = 170 (0xaa) 13. close(2) = 0 (0x0) 14. access("/lib/libc.so.7",0) = 0 (0x0) 15. open("/lib/libc.so.7",O_RDONLY,030711400) = 2 (0x2) 16. fstat(2,{ mode=-r--r--r-- ,inode=23554,size=1270640,blksize=16384 }) = 0 (0x0) 17. pread(0x2,0x8006382e0,0x1000,0x0,0x101010101010101,0x8080808080808080) = 4096 (0x1000) 18. mmap(0x0,2342912,PROT_NONE,MAP_PRIVATE|MAP_ANON|MAP_NOCORE,-1,0x0) = 34366316544 (0x800646000) 19. mmap(0x800646000,1056768,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED|MAP_NOCORE,2,0x0) = 34366316544 (0x800646000) 20. mmap(0x800848000,126976,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,2,0x102000) = 34368421888 (0x800848000) 21. mprotect(0x800867000,110592,PROT_READ|PROT_WRITE) = 0 (0x0) 22. close(2) = 0 (0x0) 23. sysarch(0x81,0x7fffffffe400,0x800535088,0x0,0xffffffffffce3530,0x800661e78) = 0 (0x0) 24. mmap(0x0,192,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34365210624 (0x800538000) 25. munmap(0x800538000,192) = 0 (0x0) 26. mmap(0x0,43696,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34365210624 (0x800538000) 27. munmap(0x800538000,43696) = 0 (0x0) 28. sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0) 29. sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0) 30. __sysctl(0x7fffffffe3a0,0x2,0x80086da60,0x7fffffffe398,0x0,0x0) = 0 (0x0) 31. sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0) 32. sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0) 33. open("/tmp/test.txt",O_RDWR|O_CREAT|O_TRUNC,0666) = 2 (0x2) 34. write(2,"Cool\n",5) = 5 (0x5) 35. close(2) = 0 (0x0) 36. sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0) 37. sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0) 38. sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0) 39. sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0) 40. process exit, rval = 0 41. monte-cristo!abbe:~ % cat /tmp/test.txt 42. Cool 43. monte-cristo!abbe:~ % cat test.c 44. #include <stdio.h> 45. 46. int 47. main() 48. { 49. FILE* fp; 50. 51. fp = fopen("/tmp/test.txt","w+"); 52. fprintf(stderr, "Cool\n"); 53. fclose(fp); 54. 55. } >Fix: I suspect you need to clone the stderr fd and write to the clone'd fd instead. Strace on Linux and truss on Solaris both get it right. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011112303.oABN362Z040540>