Subject: Re: kern/36548: Trailing NULs written to files over NFS
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Steve Woodford <scw@netbsd.org>
List: netbsd-bugs
Date: 06/24/2007 16:15:04
The following reply was made to PR kern/36548; it has been noted by GNATS.

From: Steve Woodford <scw@netbsd.org>
To: gnats-bugs@netbsd.org
Cc: kern-bug-people@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org
Subject: Re: kern/36548: Trailing NULs written to files over NFS
Date: Sun, 24 Jun 2007 17:10:11 +0100

 --Boundary-00=_jdpfGaNAnRLmwD6
 Content-Type: text/plain;
   charset="iso-8859-1"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 
 > Interestingly, it's the data from the final call to write(2) which is
 > being replaced by the NUL bytes. Immediately after the write(2), the
 > process invokes exit(2). The file size is correct.
 
 It's actually a bit more subtle than this, as shown by the annotated 
 kdump(1) output, attached.
 
 Process creates a file and writes some stuff to it. It does not close 
 the file descriptor.
 
 Process then forks and execs /bin/cat to append some more data to the 
 same file.
 
 Process waits for /bin/cat to exit, then writes some more data to the 
 file. It is the data from these two write(2) calls which end up being 
 NUL bytes in the file.
 
 Cheers, Steve
 
 --Boundary-00=_jdpfGaNAnRLmwD6
 Content-Type: text/plain;
   charset="iso-8859-1";
   name="nfs-corruption"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename="nfs-corruption"
 
 
 pid 363 opens/creates .tools_makevars.mk
 
    363      1 sh       CALL  open(0x3428c,0x601,0x1b6)
    363      1 sh       NAMI  "/export/netbsd/pkgsrc-current/pkgtools/digest/work/.tools_makevars.mk"
    363      1 sh       RET   open 1
    363      1 sh       CALL  break(0x37000)
    363      1 sh       RET   break 0
 
 Starts writing to it
    363      1 sh       CALL  write(1,0x35400,0x1b)
    363      1 sh       GIO   fd 1 wrote 27 bytes
        ".if !defined(_MAKEVARS_MK)
        "
    363      1 sh       RET   write 27/0x1b
    363      1 sh       CALL  write(1,0x35400,0x16)
    363      1 sh       GIO   fd 1 wrote 22 bytes
        "_MAKEVARS_MK=	defined
        "
    363      1 sh       RET   write 22/0x16
    363      1 sh       CALL  write(1,0x35400,1)
    363      1 sh       GIO   fd 1 wrote 1 bytes
        "
        "
    363      1 sh       RET   write 1
 
 Hmm, now it forks...
    363      1 sh       CALL  __vfork14
    366      1 sh       EMUL  "netbsd"
    366      1 sh       RET   fork 0
 
 And exec(2)s /bin/cat
    366      1 sh       CALL  execve(0x342dc,0x3434c,0x3435c)
    366      1 sh       NAMI  "/bin/cat"
    366      1 sh       NAMI  "/libexec/ld.elf_so"
    366      1 cat      EMUL  "netbsd"
    366      1 cat      RET   execve JUSTRETURN
    363      1 sh       RET   __vfork14 366/0x16e
    363      1 sh       CALL  getpgrp
    363      1 sh       RET   getpgrp 98/0x62
    363      1 sh       CALL  wait4(0xffffffff,0xbfffe388,0,0)
    366      1 cat      CALL  mmap(0,0x8000,3,0x1002,0xffffffff,0,0,0)
    366      1 cat      RET   mmap 537202688/0x20051000
    366      1 cat      CALL  open(0x20040570,0,0x20050590)
    366      1 cat      NAMI  "/etc/ld.so.conf"
    366      1 cat      RET   open -1 errno 2 No such file or directory
    366      1 cat      CALL  open(0xbfffe264,0,0x20053000)
    366      1 cat      NAMI  "/lib/libc.so.12"
    366      1 cat      RET   open 3
    366      1 cat      CALL  __fstat30(3,0xbfffe1cc)
    366      1 cat      RET   __fstat30 0
    366      1 cat      CALL  mmap(0,0x1000,1,1,3,0,0,0)
    366      1 cat      RET   mmap 536940544/0x20011000
    366      1 cat      CALL  munmap(0x20011000,0x1000)
    366      1 cat      RET   munmap 0
    366      1 cat      CALL  mmap(0,0xfa000,5,0xf000002,3,0,0,0)
    366      1 cat      RET   mmap 537264128/0x20060000
    366      1 cat      CALL  mmap(0x20143000,0x7000,3,0x12,3,0,0,0xdb000)
    366      1 cat      RET   mmap 538193920/0x20143000
    366      1 cat      CALL  mmap(0x2014a000,0x10000,3,0x1012,0xffffffff,0,0,0)
    366      1 cat      RET   mmap 538222592/0x2014a000
    366      1 cat      CALL  mprotect(0x2013c000,0x7000,0)
    366      1 cat      RET   mprotect 0
    366      1 cat      CALL  close(3)
    366      1 cat      RET   close 0
    366      1 cat      CALL  __sysctl(0xbfffe8d4,2,0x201518fc,0xbfffe8dc,0,0)
    366      1 cat      RET   __sysctl 0
    366      1 cat      CALL  issetugid
    366      1 cat      RET   issetugid 0
    366      1 cat      CALL  open(0xbfffea75,0,0)
    366      1 cat      NAMI  "/export/netbsd/pkgsrc-current/pkgtools/digest/work/.tools_makevars.mk.tmp"
    366      1 cat      RET   open 3
    366      1 cat      CALL  __fstat30(1,0xbfffe804)
    366      1 cat      RET   __fstat30 0
    366      1 cat      CALL  __sysctl(0xbfffe688,2,0xbfffe6e0,0xbfffe6e4,0,0)
    366      1 cat      RET   __sysctl 0
    366      1 cat      CALL  readlink(0x20136c64,0xbfffe743,0x3f)
    366      1 cat      NAMI  "/etc/malloc.conf"
    366      1 cat      RET   readlink -1 errno 2 No such file or directory
    366      1 cat      CALL  mmap(0,0x1000,3,0x1002,0xffffffff,0,0,0)
    366      1 cat      RET   mmap 536940544/0x20011000
    366      1 cat      CALL  break(0x12128)
    366      1 cat      RET   break 0
    366      1 cat      CALL  break(0x13128)
    366      1 cat      RET   break 0
    366      1 cat      CALL  break(0x14000)
    366      1 cat      RET   break 0
    366      1 cat      CALL  break(0x16000)
    366      1 cat      RET   break 0
    366      1 cat      CALL  read(3,0x14000,0x2000)
    366      1 cat      GIO   fd 3 read 718 bytes
        "_BLNK_PHYSICAL_PATH.LOCALBASE=	/usr/pkg
 	_BLNK_PHYSICAL_PATH.WRKDIR=	/export/netbsd/pkgsrc-current/pkgtools\
 	/digest/work
 	_IGNORE_INFO_PATH=	
 	_MANCOMPRESSED=	no
 	_MANZ=	no
 	_USE_TOOLS=	[ awk basename cat chgrp chmod chown cmp cp cut date d\
 	iff dirname echo egrep env expr false file find grep head hostname id \
 	install ln ls mkdir mv pax printf pwd rm rmdir sed sh sort tail test t\
 	ouch tr true uname wc xargs
 	_WRAP_PATH=	/export/netbsd/pkgsrc-current/pkgtools/digest/work/.bu\
 	ildlink/bin:/export/netbsd/pkgsrc-current/pkgtools/digest/work/.gcc/bi\
 	n:/export/netbsd/pkgsrc-current/pkgtools/digest/work/.tools/bin:/usr/p\
 	kg/bin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/pkg/sbin:/usr/pkg/bin:/usr/X\
 	11R6/bin:/usr/local/sbin:/usr/local/bin
        "
    366      1 cat      RET   read 718/0x2ce
 
 
 /bin/cat now appends to the file first written to by PID 363, above:
    366      1 cat      CALL  write(1,0x14000,0x2ce)
    366      1 cat      GIO   fd 1 wrote 718 bytes
        "_BLNK_PHYSICAL_PATH.LOCALBASE=	/usr/pkg
 	_BLNK_PHYSICAL_PATH.WRKDIR=	/export/netbsd/pkgsrc-current/pkgtools\
 	/digest/work
 	_IGNORE_INFO_PATH=	
 	_MANCOMPRESSED=	no
 	_MANZ=	no
 	_USE_TOOLS=	[ awk basename cat chgrp chmod chown cmp cp cut date d\
 	iff dirname echo egrep env expr false file find grep head hostname id \
 	install ln ls mkdir mv pax printf pwd rm rmdir sed sh sort tail test t\
 	ouch tr true uname wc xargs
 	_WRAP_PATH=	/export/netbsd/pkgsrc-current/pkgtools/digest/work/.bu\
 	ildlink/bin:/export/netbsd/pkgsrc-current/pkgtools/digest/work/.gcc/bi\
 	n:/export/netbsd/pkgsrc-current/pkgtools/digest/work/.tools/bin:/usr/p\
 	kg/bin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/pkg/sbin:/usr/pkg/bin:/usr/X\
 	11R6/bin:/usr/local/sbin:/usr/local/bin
        "
    366      1 cat      RET   write 718/0x2ce
    366      1 cat      CALL  read(3,0x14000,0x2000)
    366      1 cat      GIO   fd 3 read 0 bytes
        ""
    366      1 cat      RET   read 0
    366      1 cat      CALL  close(3)
    366      1 cat      RET   close 0
    366      1 cat      CALL  close(1)
    366      1 cat      RET   close 0
 
 /bin/cat is done
    366      1 cat      CALL  exit(0)
 
 
 PID 363 now writes some more to the file. The data from both these write(2)
 calls are written as NUL.
    363      1 sh       RET   wait4 366/0x16e
    363      1 sh       CALL  write(1,0x35400,1)
    363      1 sh       GIO   fd 1 wrote 1 bytes
        "
        "
    363      1 sh       RET   write 1
    363      1 sh       CALL  write(1,0x35400,0x16)
    363      1 sh       GIO   fd 1 wrote 22 bytes
        ".endif # _MAKEVARS_MK
        "
    363      1 sh       RET   write 22/0x16
    363      1 sh       CALL  exit(0)
 
 
 --Boundary-00=_jdpfGaNAnRLmwD6--