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.

NetBSD Home
NetBSD PR Database Search

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