From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1222237-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id 1F83B138359
	for <garchives@archives.gentoo.org>; Sat, 14 Nov 2020 17:06:53 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 407E5E03EC;
	Sat, 14 Nov 2020 17:06:52 +0000 (UTC)
Received: from smtp.gentoo.org (woodpecker.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id E365CE03EC
	for <gentoo-commits@lists.gentoo.org>; Sat, 14 Nov 2020 17:06:51 +0000 (UTC)
Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 4D164340BE8
	for <gentoo-commits@lists.gentoo.org>; Sat, 14 Nov 2020 17:06:50 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id 8F40D448
	for <gentoo-commits@lists.gentoo.org>; Sat, 14 Nov 2020 17:06:48 +0000 (UTC)
From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" <grobian@gentoo.org>
Message-ID: <1605372287.77a0017b2ea736670eba1f3923201dc1c2858feb.grobian@gentoo>
Subject: [gentoo-commits] proj/portage-utils:master commit in: /
X-VCS-Repository: proj/portage-utils
X-VCS-Files: qmerge.c
X-VCS-Directories: /
X-VCS-Committer: grobian
X-VCS-Committer-Name: Fabian Groffen
X-VCS-Revision: 77a0017b2ea736670eba1f3923201dc1c2858feb
X-VCS-Branch: master
Date: Sat, 14 Nov 2020 17:06:48 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
X-Archives-Salt: a7c1e0d1-7da3-45dc-9cda-080a737a54cd
X-Archives-Hash: dcc1e3d45bfb712cb357ac4549c8b128

commit:     77a0017b2ea736670eba1f3923201dc1c2858feb
Author:     Peter Stuge <peter <AT> stuge <DOT> se>
AuthorDate: Tue Nov 10 19:01:44 2020 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Nov 14 16:44:47 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=77a0017b

qmerge: copy tbz2 archive into decompressor/tar pipe ourselves

We have nothing to do while tar is running so let's copy the tbz2
archive part into a popen():ed tar pipe ourselves, rather than depend
on an external program.

Doing so also fixes a possible shell injection vulnerability and
improves performance.

Fixes: 7171479f ("qmerge: unpack tbz2 file without splitting it first", 2020-05-17)
Signed-off-by: Peter Stuge <peter <AT> stuge.se>
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 qmerge.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/qmerge.c b/qmerge.c
index 36d3596..6d98329 100644
--- a/qmerge.c
+++ b/qmerge.c
@@ -1231,13 +1231,59 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
 	 * Since some tools (e.g. zstd) complain about the .bz2
 	 * extension, we feed the tool by input redirection. */
 	snprintf(buf, sizeof(buf),
-		BUSYBOX " sh -c 'dd status=none if=%s bs=1 count=%d %s%s | "
+		BUSYBOX " sh -c '%s%s"
 		"tar -x%sf - -C image/'",
-		tbz2, tbz2size, compr[0] == '\0' ? "" : "| ", compr,
+		compr, compr[0] == '\0' ? "" : " | ",
 		((verbose > 1) ? "v" : ""));
 
+	/* start the tar pipe and copy tbz2size binpkg bytes into it
+	 * "manually" rather than depending on dd or head */
+	{
+		FILE *tarpipe, *tbz2f;
+		unsigned char iobuf[8192];
+		int piped = 0;
+		size_t n, rd, wr;
+
+		tarpipe = popen(buf, "w");
+		if (NULL == tarpipe)
+			errp("popen(%s)", buf);
+
+		tbz2f = fopen(tbz2, "r");
+		if (NULL == tbz2f)
+			errp("fopen(%s)", tbz2);
+
+		for (piped = wr = 0; piped < tbz2size; piped += wr) {
+			n = MIN(tbz2size - piped, (ssize_t)sizeof iobuf);
+			rd = fread(iobuf, 1, n, tbz2f);
+			if (0 == rd) {
+				errno = ferror(tbz2f);
+				if (errno)
+					errp("fread(%s)", tbz2);
+
+				if (feof(tbz2f))
+					err("%s: unexpected EOF; corrupted binpkg", tbz2);
+			}
+
+			for (wr = n = 0; wr < rd; wr += n) {
+				n = fwrite(iobuf + wr, 1, rd - wr, tarpipe);
+				if (n != rd - wr) {
+					errno = ferror(tarpipe);
+					if (errno)
+						errp("fwrite(%s)", buf);
+
+					if (feof(tarpipe))
+						err("%s pipe: unexpected EOF", buf);
+				}
+			}
+		}
+
+		fclose(tbz2f);
+
+		if (-1 == pclose(tarpipe))
+			errp("pclose(%s)", buf);
+	}
+
 	free(tbz2);
-	xsystem(buf);
 	fflush(stdout);
 
 	eat_file("vdb/DEFINED_PHASES", &phases, &phases_len);