From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202408 header.b=Z5mOOQg1; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 274BA5A004C for ; Tue, 17 Sep 2024 08:46:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202408; t=1726555562; bh=QJ44A2xvitsnRQVEWl4fJ2Hkxy0TR92xqEXjwRexhr4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z5mOOQg1Rwy6fnURs62HCYMC3BTB36W3+5cd3oeoeYq8M4iumHbtKY4OhoV2q4BHf QFq8zO3z1lexl4FyivwE5C2zrvaeV/PJ0SFB8M3JrH9Y4fLQG+jT8/gaHPCwOcg+Du fIqJckd4xGZKcOtrRSkf5AngzIYX1p4VGfoawROE2Echq66bLlOSOMMlqA7ZmPbPGH fFaLWNXCqAJ72KVNVhHwrOl2wTX1WUelHlQZr7+pi6ov3E4pWNq5CEatAS41Dv3Zt8 JaTucSRLLJDDayO+RwPT4rMNPAwWxDTAZIjN1WTWFo3qsJJ33BS6KE48qhvjpnXZdA QaKg0qyvRM+UQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4X7C3Z5WHmz4xbg; Tue, 17 Sep 2024 16:46:02 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH v2 2/2] util: Remove possible quadratic behaviour from write_remainder() Date: Tue, 17 Sep 2024 16:45:55 +1000 Message-ID: <20240917064555.1040365-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240917064555.1040365-1-david@gibson.dropbear.id.au> References: <20240917064555.1040365-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: 6WT3I27DO7YRROVBQPXXVYFU2UTLARRC X-Message-ID-Hash: 6WT3I27DO7YRROVBQPXXVYFU2UTLARRC X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Markus Armbruster , David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: write_remainder() steps through the buffers in an IO vector writing out everything past a certain byte offset. However, on each iteration it rescans the buffer from the beginning to find out where we're up to. With an unfortunate set of write sizes this could lead to quadratic behaviour. In an even less likely set of circumstances (total vector length > maximum size_t) the 'skip' variable could overflow. This is one factor in a longstanding Coverity error we've seen (although I still can't figure out the remainder of its complaint). Rework write_remainder() to always work out our new position in the vector relative to our old/current position, rather than starting from the beginning each time. As a bonus this seems to fix the Coverity error. Signed-off-by: David Gibson --- util.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/util.c b/util.c index 7db7c2e7..43e5f5ec 100644 --- a/util.c +++ b/util.c @@ -615,28 +615,30 @@ int write_all_buf(int fd, const void *buf, size_t len) * * Return: 0 on success, -1 on error (with errno set) * - * #syscalls write writev + * #syscalls writev */ int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size_t skip) { - size_t offset, i; + size_t i = 0, offset; - while ((i = iov_skip_bytes(iov, iovcnt, skip, &offset)) < iovcnt) { + while ((i += iov_skip_bytes(iov + i, iovcnt - i, skip, &offset)) < iovcnt) { ssize_t rc; if (offset) { - rc = write(fd, (char *)iov[i].iov_base + offset, - iov[i].iov_len - offset); - } else { - rc = writev(fd, &iov[i], iovcnt - i); + /* Write the remainder of the partially written buffer */ + if (write_all_buf(fd, (char *)iov[i].iov_base + offset, + iov[i].iov_len - offset) < 0) + return -1; + i++; } + /* Write as much of the remaining whole buffers as we can */ + rc = writev(fd, &iov[i], iovcnt - i); if (rc < 0) return -1; - skip += rc; + skip = rc; } - return 0; } -- 2.46.0