lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <f610468635ef9933d03b130aa81cc07f8bfc6d00.1659003817.git.noodles@fb.com>
Date:   Thu, 28 Jul 2022 14:09:38 +0000
From:   Jonathan McDowell <noodles@...com>
To:     "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        "linux-fsdevel@...r.kernel.org" <linux-fsdevel@...r.kernel.org>,
        "linux-integrity@...r.kernel.org" <linux-integrity@...r.kernel.org>,
        "linux-security-module@...r.kernel.org" 
        <linux-security-module@...r.kernel.org>
CC:     Alexander Viro <viro@...iv.linux.org.uk>,
        Mimi Zohar <zohar@...ux.ibm.com>,
        Dmitry Kasatkin <dmitry.kasatkin@...il.com>,
        James Morris <jmorris@...ei.org>,
        "Serge E. Hallyn" <serge@...lyn.com>,
        Matthew Garrett <mjg59@...f.ucam.org>,
        Dmitrii Potoskuev <dpotoskuev@...com>
Subject: [RFC PATCH v2 5/7] lib/cpio: Add a parse-only option that doesn't
 extract any files

In order to allow a CPIO archive to be parsed without actually
extracting anything add a parse_only flag.

Signed-off-by: Jonathan McDowell <noodles@...com>
---
 include/linux/cpio.h |  2 ++
 lib/cpio.c           | 35 ++++++++++++++++++++++++++++-------
 2 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/include/linux/cpio.h b/include/linux/cpio.h
index 7e9888e6a1ad..5b897d1d3143 100644
--- a/include/linux/cpio.h
+++ b/include/linux/cpio.h
@@ -78,6 +78,8 @@ struct cpio_context {
 	struct cpio_link_hash *link_hash[CPIO_LINK_HASH_SIZE];
 
 	struct list_head dir_list;
+
+	bool parse_only;
 };
 
 int __cpio cpio_start(struct cpio_context *ctx);
diff --git a/lib/cpio.c b/lib/cpio.c
index 03967e063c76..37e2e2071c8d 100644
--- a/lib/cpio.c
+++ b/lib/cpio.c
@@ -15,7 +15,12 @@ static ssize_t __cpio xwrite(struct cpio_context *ctx, struct file *file,
 
 	/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
 	while (count) {
-		ssize_t rv = kernel_write(file, p, count, pos);
+		ssize_t rv;
+
+		if (ctx->parse_only)
+			rv = count;
+		else
+			rv = kernel_write(file, p, count, pos);
 
 		if (rv < 0) {
 			if (rv == -EINTR || rv == -EAGAIN)
@@ -136,7 +141,8 @@ static void __cpio dir_utime(struct cpio_context *ctx)
 
 	list_for_each_entry_safe(de, tmp, &ctx->dir_list, list) {
 		list_del(&de->list);
-		do_utime(de->name, de->mtime);
+		if (!ctx->parse_only)
+			do_utime(de->name, de->mtime);
 		kfree(de);
 	}
 }
@@ -374,6 +380,13 @@ static int __cpio do_name(struct cpio_context *ctx)
 		free_hash(ctx);
 		return 0;
 	}
+
+	if (ctx->parse_only) {
+		if (S_ISREG(ctx->mode))
+			ctx->state = CPIO_COPYFILE;
+		return 0;
+	}
+
 	clean_path(ctx->collected, ctx->mode);
 	if (S_ISREG(ctx->mode)) {
 		int ml = maybe_link(ctx);
@@ -454,8 +467,10 @@ static int __cpio do_copy(struct cpio_context *ctx)
 		if (ret != ctx->body_len)
 			return (ret < 0) ? ret : -EIO;
 
-		do_utime_path(&ctx->wfile->f_path, ctx->mtime);
-		fput(ctx->wfile);
+		if (!ctx->parse_only) {
+			do_utime_path(&ctx->wfile->f_path, ctx->mtime);
+			fput(ctx->wfile);
+		}
 		if (ctx->csum_present && ctx->io_csum != ctx->hdr_csum)
 			return -EBADMSG;
 
@@ -480,6 +495,12 @@ static int __cpio do_symlink(struct cpio_context *ctx)
 	struct path path;
 	int error;
 
+	ctx->state = CPIO_SKIPIT;
+	ctx->next_state = CPIO_RESET;
+
+	if (ctx->parse_only)
+		return 0;
+
 	ctx->collected[N_ALIGN(ctx->name_len) + ctx->body_len] = '\0';
 	clean_path(ctx->collected, 0);
 
@@ -498,8 +519,7 @@ static int __cpio do_symlink(struct cpio_context *ctx)
 
 	cpio_chown(ctx->collected, ctx->uid, ctx->gid, AT_SYMLINK_NOFOLLOW);
 	do_utime(ctx->collected, ctx->mtime);
-	ctx->state = CPIO_SKIPIT;
-	ctx->next_state = CPIO_RESET;
+
 	return 0;
 }
 
@@ -581,7 +601,8 @@ int __cpio cpio_start(struct cpio_context *ctx)
 
 void __cpio cpio_finish(struct cpio_context *ctx)
 {
-	dir_utime(ctx);
+	if (!ctx->parse_only)
+		dir_utime(ctx);
 	kfree(ctx->name_buf);
 	kfree(ctx->symlink_buf);
 	kfree(ctx->header_buf);
-- 
2.30.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ