aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/zfs_namecheck.h2
-rw-r--r--lib/libzfs/libzfs_dataset.c10
-rw-r--r--module/zcommon/zfs_namecheck.c21
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh4
4 files changed, 36 insertions, 1 deletions
diff --git a/include/zfs_namecheck.h b/include/zfs_namecheck.h
index 527db92b0..56d3d36f0 100644
--- a/include/zfs_namecheck.h
+++ b/include/zfs_namecheck.h
@@ -43,6 +43,8 @@ typedef enum {
NAME_ERR_RESERVED, /* entire name is reserved */
NAME_ERR_DISKLIKE, /* reserved disk name (c[0-9].*) */
NAME_ERR_TOOLONG, /* name is too long */
+ NAME_ERR_SELF_REF, /* reserved self path name ('.') */
+ NAME_ERR_PARENT_REF, /* reserved parent path name ('..') */
NAME_ERR_NO_AT, /* permission set is missing '@' */
} namecheck_err_t;
diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c
index 93af50b99..3be205f1f 100644
--- a/lib/libzfs/libzfs_dataset.c
+++ b/lib/libzfs/libzfs_dataset.c
@@ -197,6 +197,16 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
"reserved disk name"));
break;
+ case NAME_ERR_SELF_REF:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "self reference, '.' is found in name"));
+ break;
+
+ case NAME_ERR_PARENT_REF:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "parent reference, '..' is found in name"));
+ break;
+
default:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"(%d) not defined"), why);
diff --git a/module/zcommon/zfs_namecheck.c b/module/zcommon/zfs_namecheck.c
index 58b23b0e0..b1e0de6d8 100644
--- a/module/zcommon/zfs_namecheck.c
+++ b/module/zcommon/zfs_namecheck.c
@@ -232,6 +232,27 @@ entity_namecheck(const char *path, namecheck_err_t *why, char *what)
}
}
+ if (*end == '\0' || *end == '/') {
+ int component_length = end - start;
+ /* Validate the contents of this component is not '.' */
+ if (component_length == 1) {
+ if (start[0] == '.') {
+ if (why)
+ *why = NAME_ERR_SELF_REF;
+ return (-1);
+ }
+ }
+
+ /* Validate the content of this component is not '..' */
+ if (component_length == 2) {
+ if (start[0] == '.' && start[1] == '.') {
+ if (why)
+ *why = NAME_ERR_PARENT_REF;
+ return (-1);
+ }
+ }
+ }
+
/* Snapshot or bookmark delimiter found */
if (*end == '@' || *end == '#') {
/* Multiple delimiters are not allowed */
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
index b8190626c..63f5e595e 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_009_neg.ksh
@@ -90,7 +90,9 @@ set -A args "$TESTPOOL/" "$TESTPOOL//blah" "$TESTPOOL/@blah" \
"$TESTPOOL/blah*blah" "$TESTPOOL/blah blah" \
"-s $TESTPOOL/$TESTFS1" "-b 1092 $TESTPOOL/$TESTFS1" \
"-b 64k $TESTPOOL/$TESTFS1" "-s -b 32k $TESTPOOL/$TESTFS1" \
- "$TESTPOOL/$BYND_MAX_NAME" "$TESTPOOL/$BYND_NEST_LIMIT"
+ "$TESTPOOL/$BYND_MAX_NAME" "$TESTPOOL/$BYND_NEST_LIMIT" \
+ "$TESTPOOL/." "$TESTPOOL/.." "$TESTPOOL/../blah" "$TESTPOOL/./blah" \
+ "$TESTPOOL/blah/./blah" "$TESTPOOL/blah/../blah"
log_assert "Verify 'zfs create <filesystem>' fails with bad <filesystem> argument."