Page MenuHomeFreeBSD

D44161.id135243.diff
No OneTemporary

D44161.id135243.diff

diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c
--- a/sys/fs/tarfs/tarfs_vfsops.c
+++ b/sys/fs/tarfs/tarfs_vfsops.c
@@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2013 Juniper Networks, Inc.
- * Copyright (c) 2022-2023 Klara, Inc.
+ * Copyright (c) 2022-2024 Klara, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -451,7 +451,7 @@
int64_t num;
int endmarker = 0;
char *namep, *sep;
- struct tarfs_node *parent, *tnp;
+ struct tarfs_node *parent, *tnp, *other;
size_t namelen = 0, linklen = 0, realsize = 0, sz;
ssize_t res;
dev_t rdev;
@@ -732,28 +732,41 @@
link = hdrp->linkname;
linklen = strnlen(link, sizeof(hdrp->linkname));
}
- error = tarfs_alloc_node(tmp, namep, sep - namep, VREG,
- 0, 0, 0, 0, 0, 0, 0, NULL, 0, parent, &tnp);
- if (error != 0) {
+ if (linklen == 0) {
+ TARFS_DPF(ALLOC, "%s: %.*s: link without target\n",
+ __func__, (int)namelen, name);
+ error = EINVAL;
goto bad;
}
error = tarfs_lookup_path(tmp, link, linklen, NULL,
- NULL, NULL, &tnp->other, false);
- if (tnp->other == NULL ||
- tnp->other->type != VREG ||
- tnp->other->other != NULL) {
- TARFS_DPF(ALLOC, "%s: %.*s: dead hard link to %.*s\n",
+ NULL, NULL, &other, false);
+ if (error != 0) {
+ goto bad;
+ }
+ if (other->type != VREG || other->other != NULL) {
+ TARFS_DPF(ALLOC, "%s: %.*s: invalid link to %.*s\n",
__func__, (int)namelen, name, (int)linklen, link);
error = EINVAL;
goto bad;
}
- tnp->other->nlink++;
+ error = tarfs_alloc_node(tmp, namep, sep - namep, VREG,
+ 0, 0, 0, 0, 0, 0, 0, NULL, 0, parent, &tnp);
+ if (error == 0) {
+ tnp->other = other;
+ tnp->other->nlink++;
+ }
break;
case TAR_TYPE_SYMLINK:
if (link == NULL) {
link = hdrp->linkname;
linklen = strnlen(link, sizeof(hdrp->linkname));
}
+ if (linklen == 0) {
+ TARFS_DPF(ALLOC, "%s: %.*s: link without target\n",
+ __func__, (int)namelen, name);
+ error = EINVAL;
+ goto bad;
+ }
error = tarfs_alloc_node(tmp, namep, sep - namep, VLNK,
0, linklen, mtime, uid, gid, mode, flags, link, 0,
parent, &tnp);
diff --git a/tests/sys/fs/tarfs/Makefile b/tests/sys/fs/tarfs/Makefile
--- a/tests/sys/fs/tarfs/Makefile
+++ b/tests/sys/fs/tarfs/Makefile
@@ -3,7 +3,7 @@
TESTSDIR= ${TESTSBASE}/sys/fs/tarfs
BINDIR= ${TESTSDIR}
-PROGS+= mktar
+PROGS+= mktar tarsum
ATF_TESTS_SH+= tarfs_test
diff --git a/tests/sys/fs/tarfs/tarfs_test.sh b/tests/sys/fs/tarfs/tarfs_test.sh
--- a/tests/sys/fs/tarfs/tarfs_test.sh
+++ b/tests/sys/fs/tarfs/tarfs_test.sh
@@ -2,7 +2,7 @@
#-
# SPDX-License-Identifier: BSD-2-Clause
#
-# Copyright (c) 2023 Klara, Inc.
+# Copyright (c) 2023-2024 Klara, Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -43,6 +43,10 @@
"$(atf_get_srcdir)"/mktar ${TARFS_USE_GNU_TAR+-g} "$@"
}
+tarsum() {
+ "$(atf_get_srcdir)"/tarsum
+}
+
atf_test_case tarfs_basic cleanup
tarfs_basic_head() {
atf_set "descr" "Basic function test"
@@ -225,6 +229,47 @@
tarfs_notdir_file_cleanup
}
+atf_test_case tarfs_emptylink cleanup
+tarfs_emptylink_head() {
+ atf_set "descr" "Regression test for PR 277360: empty link target"
+ atf_set "require.user" "root"
+}
+tarfs_emptylink_body() {
+ kldload -n tarfs || atf_skip "This test requires tarfs and could not load it"
+ mkdir "${mnt}"
+ touch z
+ ln -f z hard
+ ln -fs z soft
+ tar -cf - z hard soft | dd bs=512 skip=1 | tr z '\0' | \
+ tarsum >> tarfs_emptylink.tar
+ atf_check -s not-exit:0 -e match:"Invalid" \
+ mount -rt tarfs tarfs_emptylink.tar "${mnt}"
+}
+tarfs_emptylink_cleanup() {
+ umount "${mnt}" || true
+}
+
+atf_test_case tarfs_linktodir cleanup
+tarfs_linktodir_head() {
+ atf_set "descr" "Regression test for PR 277360: link to directory"
+ atf_set "require.user" "root"
+}
+tarfs_linktodir_body() {
+ kldload -n tarfs || atf_skip "This test requires tarfs and could not load it"
+ mkdir "${mnt}"
+ mkdir d
+ tar -cf - d | dd bs=512 count=1 > tarfs_linktodir.tar
+ rmdir d
+ touch d
+ ln -f d link
+ tar -cf - d link | dd bs=512 skip=1 >> tarfs_linktodir.tar
+ atf_check -s not-exit:0 -e match:"Invalid" \
+ mount -rt tarfs tarfs_linktodir.tar "${mnt}"
+}
+tarfs_linktodir_cleanup() {
+ umount "${mnt}" || true
+}
+
atf_init_test_cases() {
atf_add_test_case tarfs_basic
atf_add_test_case tarfs_basic_gnu
@@ -236,4 +281,6 @@
atf_add_test_case tarfs_notdir_dotdot_gnu
atf_add_test_case tarfs_notdir_file
atf_add_test_case tarfs_notdir_file_gnu
+ atf_add_test_case tarfs_emptylink
+ atf_add_test_case tarfs_linktodir
}
diff --git a/tests/sys/fs/tarfs/tarsum.c b/tests/sys/fs/tarfs/tarsum.c
new file mode 100644
--- /dev/null
+++ b/tests/sys/fs/tarfs/tarsum.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2024 Klara, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * This program reads a tarball from stdin, recalculates the checksums of
+ * all ustar records within it, and writes the result to stdout.
+ */
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main(void)
+{
+ union {
+ uint8_t bytes[512];
+ struct {
+ uint8_t prelude[148];
+ char checksum[8];
+ uint8_t interlude[101];
+ char magic[6];
+ char version[2];
+ char postlude[];
+ };
+ } ustar;
+ unsigned long sum;
+ ssize_t ret;
+ size_t i;
+
+ for (;;) {
+ if ((ret = fread(&ustar, 1, sizeof(ustar), stdin)) < 0)
+ err(1, "stdin");
+ else if (ret == 0)
+ break;
+ else if ((size_t)ret < sizeof(ustar))
+ err(1, "stdin: Short read");
+ if (strcmp(ustar.magic, "ustar") == 0 &&
+ ustar.version[0] == '0' && ustar.version[1] == '0') {
+ memset(ustar.checksum, ' ', sizeof(ustar.checksum));
+ for (sum = i = 0; i < sizeof(ustar); i++)
+ sum += ustar.bytes[i];
+ sprintf(ustar.checksum, "%#lo", sum);
+ }
+ if ((ret = fwrite(&ustar, 1, sizeof(ustar), stdout)) < 0)
+ err(1, "stdout");
+ else if ((size_t)ret < sizeof(ustar))
+ err(1, "stdout: Short write");
+ }
+ return (0);
+}

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 7, 3:05 PM (4 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31038623
Default Alt Text
D44161.id135243.diff (6 KB)

Event Timeline