From 109731cd73c56c378b4c71732b9b9d3504a7a7e1 Mon Sep 17 00:00:00 2001
From: Damian Szuberski <szuberskidamian@gmail.com>
Date: Wed, 9 Nov 2022 04:16:01 +1000
Subject: [PATCH] dsl_prop_known_index(): check for invalid prop

Resolve UBSAN array-index-out-of-bounds error in zprop_desc_t.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: szubersk <szuberskidamian@gmail.com>
Closes #14142
Closes #14147
---
 module/zcommon/zfs_prop.c | 26 ++++++++++++++++++++++++++
 module/zfs/dsl_prop.c     |  3 ++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c
index c03933d126..9c65702b8d 100644
--- a/module/zcommon/zfs_prop.c
+++ b/module/zcommon/zfs_prop.c
@@ -748,6 +748,8 @@ zfs_prop_init(void)
 boolean_t
 zfs_prop_delegatable(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	zprop_desc_t *pd = &zfs_prop_table[prop];
 
 	/* The mlslabel property is never delegatable. */
@@ -858,6 +860,8 @@ zfs_prop_valid_for_type(int prop, zfs_type_t types, boolean_t headcheck)
 zprop_type_t
 zfs_prop_get_type(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_proptype);
 }
 
@@ -867,6 +871,8 @@ zfs_prop_get_type(zfs_prop_t prop)
 boolean_t
 zfs_prop_readonly(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_attr == PROP_READONLY ||
 	    zfs_prop_table[prop].pd_attr == PROP_ONETIME ||
 	    zfs_prop_table[prop].pd_attr == PROP_ONETIME_DEFAULT);
@@ -878,6 +884,8 @@ zfs_prop_readonly(zfs_prop_t prop)
 boolean_t
 zfs_prop_visible(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_visible &&
 	    zfs_prop_table[prop].pd_zfs_mod_supported);
 }
@@ -888,6 +896,8 @@ zfs_prop_visible(zfs_prop_t prop)
 boolean_t
 zfs_prop_setonce(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_attr == PROP_ONETIME ||
 	    zfs_prop_table[prop].pd_attr == PROP_ONETIME_DEFAULT);
 }
@@ -895,12 +905,16 @@ zfs_prop_setonce(zfs_prop_t prop)
 const char *
 zfs_prop_default_string(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_strdefault);
 }
 
 uint64_t
 zfs_prop_default_numeric(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_numdefault);
 }
 
@@ -911,6 +925,8 @@ zfs_prop_default_numeric(zfs_prop_t prop)
 const char *
 zfs_prop_to_name(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_name);
 }
 
@@ -920,6 +936,8 @@ zfs_prop_to_name(zfs_prop_t prop)
 boolean_t
 zfs_prop_inheritable(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_attr == PROP_INHERIT ||
 	    zfs_prop_table[prop].pd_attr == PROP_ONETIME);
 }
@@ -972,6 +990,8 @@ zfs_prop_valid_keylocation(const char *str, boolean_t encrypted)
 const char *
 zfs_prop_values(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_values);
 }
 
@@ -983,6 +1003,8 @@ zfs_prop_values(zfs_prop_t prop)
 int
 zfs_prop_is_string(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING ||
 	    zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX);
 }
@@ -994,6 +1016,8 @@ zfs_prop_is_string(zfs_prop_t prop)
 const char *
 zfs_prop_column_name(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_colname);
 }
 
@@ -1004,6 +1028,8 @@ zfs_prop_column_name(zfs_prop_t prop)
 boolean_t
 zfs_prop_align_right(zfs_prop_t prop)
 {
+	ASSERT3S(prop, >=, 0);
+	ASSERT3S(prop, <, ZFS_NUM_PROPS);
 	return (zfs_prop_table[prop].pd_rightalign);
 }
 
diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c
index ad927b622f..d1c0059092 100644
--- a/module/zfs/dsl_prop.c
+++ b/module/zfs/dsl_prop.c
@@ -75,7 +75,8 @@ static int
 dsl_prop_known_index(zfs_prop_t prop, uint64_t value)
 {
 	const char *str = NULL;
-	if (zfs_prop_get_type(prop) == PROP_TYPE_INDEX)
+	if (prop != ZPROP_CONT && prop != ZPROP_INVAL &&
+	    zfs_prop_get_type(prop) == PROP_TYPE_INDEX)
 		return (!zfs_prop_index_to_string(prop, value, &str));
 
 	return (-1);