NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/59431: install(1) may report bogus write(2) error
>Number: 59431
>Category: bin
>Synopsis: install(1) may report bogus write(2) error
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat May 17 16:00:00 +0000 2025
>Originator: Taylor R Campbell
>Release: current, 10, 9, ...
>Organization:
The WriteBSD Installation
>Environment:
>Description:
install(1) will sometimes mmap the source file and write from the mmapped buffer:
905 /*
906 * Mmap and write if less than 8M (the limit is so we
907 * don't totally trash memory on big files). This is
908 * really a minor hack, but it wins some CPU back.
909 */
910
911 if (size <= 8 * 1048576) {
912 if ((p = mmap(NULL, (size_t)size, PROT_READ,
913 MAP_FILE|MAP_SHARED, from_fd, (off_t)0))
914 == MAP_FAILED) {
915 goto mmap_failed;
916 }
917 #if defined(MADV_SEQUENTIAL) && !defined(__APPLE__)
918 if (madvise(p, (size_t)size, MADV_SEQUENTIAL) == -1
919 && errno != EOPNOTSUPP)
920 warn("madvise");
921 #endif
922
923 if (to_fd >= 0 && write(to_fd, p, size) != size) {
924 serrno = errno;
925 (void)unlink(to_name);
926 errc(EXIT_FAILURE, serrno, "%s: write",
927 to_name);
928 }
https://nxr.netbsd.org/xref/src/usr.bin/xinstall/xinstall.c?r=1.130#905
If the source file is truncated, however, _during write(2)_, the write may _partially_ succeed, short of the requested size. (The next write will probably fail with EFAULT.)
>How-To-Repeat:
concurrently truncate a source file and install it to a target file, as in PR toolchain/57241: mips64el--netbsd-install core dumps randomly (https://gnats.NetBSD.org/57241)
>Fix:
ssize_t nwrit;
if (to_fd >= 0) {
if ((nwrit = write(to_fd, p, size)) == -1) {
serror = errno;
(void)unlink(to_name);
errc(EXIT_FAILURE, serrno, "%s: write", to_name);
} else if ((size_t)nwrit != size) {
(void)unlink(to_name);
errx(EXIT_FAILURE, "%s: write truncated, %zu != %zu",
(size_t)nwrit, size);
}
}
Actually this should maybe do write in a loop -- I'm not sure POSIX guarantees complete write(2) even on success except for PIPE_BUF-sized writes to pipes. But this change should be good for now to mitigate the red herrings.
Home |
Main Index |
Thread Index |
Old Index