NetBSD Problem Report #59431
From www@netbsd.org Sat May 17 15:55:51 2025
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 33DC61A9241
for <gnats-bugs@gnats.NetBSD.org>; Sat, 17 May 2025 15:55:51 +0000 (UTC)
Message-Id: <20250517155549.C4C341A9242@mollari.NetBSD.org>
Date: Sat, 17 May 2025 15:55:49 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: install(1) may report bogus write(2) error
X-Send-Pr-Version: www-1.0
>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.
(Contact us)
$NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.