Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Feb 2023 02:13:34 GMT
From:      =?utf-8?Q?Dag-Erling=20Sm=C3=B8rgrav?= <des@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: ae6cff89738b - main - tarfs: Don't panic if the parent of a new node is not a directory.
Message-ID:  <202302150213.31F2DYAH062010@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=ae6cff89738bab9a4a956c230fb9dc6c4d5e113f

commit ae6cff89738bab9a4a956c230fb9dc6c4d5e113f
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-02-15 02:12:45 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-02-15 02:13:11 +0000

    tarfs: Don't panic if the parent of a new node is not a directory.
    
    PR:             269519
    Sponsored by:   Juniper Networks, Inc.
    Sponsored by:   Klara, Inc.
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D38587
---
 sys/fs/tarfs/tarfs_subr.c        |  3 ++-
 sys/fs/tarfs/tarfs_vfsops.c      | 12 +++++++++++-
 tests/sys/fs/tarfs/tarfs_test.sh | 30 ++++++++++++++++++++++++++----
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/sys/fs/tarfs/tarfs_subr.c b/sys/fs/tarfs/tarfs_subr.c
index fc2955b44606..0cba43a8c21b 100644
--- a/sys/fs/tarfs/tarfs_subr.c
+++ b/sys/fs/tarfs/tarfs_subr.c
@@ -171,6 +171,8 @@ tarfs_alloc_node(struct tarfs_mount *tmp, const char *name, size_t namelen,
 
 	TARFS_DPF(ALLOC, "%s(%.*s)\n", __func__, (int)namelen, name);
 
+	if (parent != NULL && parent->type != VDIR)
+		return (ENOTDIR);
 	tnp = malloc(sizeof(struct tarfs_node), M_TARFSNODE, M_WAITOK | M_ZERO);
 	mtx_init(&tnp->lock, "tarfs node lock", NULL, MTX_DEF);
 	tnp->gen = arc4random();
@@ -233,7 +235,6 @@ tarfs_alloc_node(struct tarfs_mount *tmp, const char *name, size_t namelen,
 		panic("%s: type %d not allowed", __func__, type);
 	}
 	if (parent != NULL) {
-		MPASS(parent->type == VDIR);
 		TARFS_NODE_LOCK(parent);
 		TAILQ_INSERT_TAIL(&parent->dir.dirhead, tnp, dirents);
 		parent->size += sizeof(struct tarfs_node);
diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c
index 138a57c22e7f..b3c30e884a9d 100644
--- a/sys/fs/tarfs/tarfs_vfsops.c
+++ b/sys/fs/tarfs/tarfs_vfsops.c
@@ -320,6 +320,12 @@ tarfs_lookup_path(struct tarfs_mount *tmp, char *name, size_t namelen,
 			break;
 		}
 
+		/* we're not at the end, so parent must be a directory */
+		if (parent->type != VDIR) {
+			error = ENOTDIR;
+			break;
+		}
+
 		/* locate the next separator */
 		for (sep = name, len = 0;
 		     *sep != '\0' && *sep != '/' && len < namelen;
@@ -685,8 +691,12 @@ again:
 
 	error = tarfs_lookup_path(tmp, name, namelen, &namep,
 	    &sep, &parent, &tnp, true);
-	if (error != 0)
+	if (error != 0) {
+		TARFS_DPF(ALLOC, "%s: failed to look up %.*s\n", __func__,
+		    (int)namelen, name);
+		error = EINVAL;
 		goto bad;
+	}
 	if (tnp != NULL) {
 		if (hdrp->typeflag[0] == TAR_TYPE_DIRECTORY) {
 			/* XXX set attributes? */
diff --git a/tests/sys/fs/tarfs/tarfs_test.sh b/tests/sys/fs/tarfs/tarfs_test.sh
index d812ced80bbb..634b6be3dd08 100644
--- a/tests/sys/fs/tarfs/tarfs_test.sh
+++ b/tests/sys/fs/tarfs/tarfs_test.sh
@@ -33,10 +33,11 @@ mnt="$(realpath ${TMPDIR:-/tmp})/mnt.$$"
 sum=4da2143234486307bb44eaa610375301781a577d1172f362b88bb4b1643dee62
 
 atf_test_case tarfs_test
-tarfs_test_head() {
+tarfs_basic_head() {
+	atf_set "descr" "Basic function test"
 	atf_set "require.user" "root"
 }
-tarfs_test_body() {
+tarfs_basic_body() {
 	mkdir "${mnt}"
 	"${mktar}" tarfs_test.tar.zst
 	atf_check mount -rt tarfs tarfs_test.tar.zst "${mnt}"
@@ -45,10 +46,31 @@ tarfs_test_body() {
 	atf_check_equal "$(stat -f%d,%i "${mnt}"/sparse_file)" "$(stat -L -f%d,%i "${mnt}"/long_link)"
 	atf_check_equal "$(sha256 -q "${mnt}"/sparse_file)" ${sum}
 }
-tarfs_test_cleanup() {
+tarfs_basic_cleanup() {
+	umount "${mnt}"
+}
+
+atf_test_case tarfs_notdir
+tarfs_notdir_head() {
+	atf_set "descr" "Regression test for PR 269519"
+	atf_set "require.user" "root"
+}
+tarfs_notdir_body() {
+	mkdir "${mnt}"
+	echo "hello" >d
+	tar cf tarfs_notdir.tar d
+	rm d
+	mkdir -p d/s
+	echo "world" >d/s/f
+	tar rf tarfs_notdir.tar d/s/f
+	atf_check -s not-exit:0 -e match:"Invalid" \
+	    mount -rt tarfs tarfs_notdir.tar "${mnt}"
+}
+tarfs_notdir_cleanup() {
 	umount "${mnt}"
 }
 
 atf_init_test_cases() {
-	atf_add_test_case tarfs_test
+	atf_add_test_case tarfs_basic
+	atf_add_test_case tarfs_notdir
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302150213.31F2DYAH062010>