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--