From owner-freebsd-bugs@FreeBSD.ORG Thu Nov 11 23:10:11 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C03A11065674 for ; Thu, 11 Nov 2010 23:10:11 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 9D2D88FC12 for ; Thu, 11 Nov 2010 23:10:11 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id oABNABLo025186 for ; Thu, 11 Nov 2010 23:10:11 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oABNABaD025185; Thu, 11 Nov 2010 23:10:11 GMT (envelope-from gnats) Resent-Date: Thu, 11 Nov 2010 23:10:11 GMT Resent-Message-Id: <201011112310.oABNABaD025185@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Bron Gondwana Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C6C421065693 for ; Thu, 11 Nov 2010 23:03:06 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id B5DCB8FC1C for ; Thu, 11 Nov 2010 23:03:06 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id oABN36RE040541 for ; Thu, 11 Nov 2010 23:03:06 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id oABN362Z040540; Thu, 11 Nov 2010 23:03:06 GMT (envelope-from nobody) Message-Id: <201011112303.oABN362Z040540@www.freebsd.org> Date: Thu, 11 Nov 2010 23:03:06 GMT From: Bron Gondwana To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: bin/152151: truss causes programs to open fd number 2, clobbering random files X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Nov 2010 23:10:11 -0000 >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 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: