Whamcloud - gitweb
LU-17895 lnet: Validate input for lnetctl import 40/55340/3
authorChris Horn <chris.horn@hpe.com>
Thu, 6 Jun 2024 16:55:39 +0000 (10:55 -0600)
committerOleg Drokin <green@whamcloud.com>
Wed, 19 Jun 2024 01:16:03 +0000 (01:16 +0000)
Add validation of the input being parsed by lnetctl import when it is
expecting the global parameters. This resolves segmentation faults
when it encounters bad or missing keys and values.

Test-Parameters: trivial testlist=sanity-lnet
Signed-off-by: Chris Horn <chris.horn@hpe.com>
Change-Id: I232daed773283ea89e9815bf6bd79526dfd5fd4f
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55340
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Frank Sehr <fsehr@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lnet/utils/lnetctl.c
lustre/tests/sanity-lnet.sh

index 5b318eb..a27dca3 100644 (file)
@@ -4133,6 +4133,34 @@ static int yaml_import_global_settings(char *key, unsigned long value,
        return rc;
 }
 
+static char *global_params[] = {
+       "numa_range",
+       "max_interfaces",
+       "max_intf",
+       "discovery",
+       "drop_asym_route",
+       "retry_count",
+       "transaction_timeout",
+       "health_sensitivity",
+       "recovery_interval",
+       "router_sensitivity",
+       "lnd_timeout",
+       "response_tracking",
+       "recovery_limit",
+       "max_recovery_ping_interval"
+};
+
+static bool key_is_global_param(const char *key)
+{
+       int i;
+
+       for (i = 0; i < sizeof(global_params)/sizeof(global_params[0]); i++) {
+               if (!strcmp(key, global_params[i]))
+                       return true;
+       }
+       return false;
+}
+
 static int jt_import(int argc, char **argv)
 {
        char *file = NULL;
@@ -4343,16 +4371,43 @@ static int jt_import(int argc, char **argv)
                        struct cYAML *err_rc = NULL;
                        long int value;
                        char *key;
+                       char errmsg[LNET_MAX_STR_LEN];
 
                        key = strdup((char *)event.data.scalar.value);
+                       if (!key_is_global_param(key)) {
+                               snprintf(errmsg, LNET_MAX_STR_LEN,
+                                        "invalid key '%s'", key);
+                               errno = rc = -EINVAL;
+                               yaml_lnet_print_error(flags, "import", errmsg);
+                               goto free_reply;
+                       }
+
                        rc = yaml_parser_parse(&setup, &event);
-                       if (rc == 0)
+                       if (rc == 0) {
+                               yaml_parser_log_error(&setup, stderr,
+                                                     "import: ");
+                               goto emitter_error;
+                       }
+
+                       if (!strlen((char *)event.data.scalar.value)) {
+                               snprintf(errmsg, LNET_MAX_STR_LEN,
+                                        "no value specified for key '%s'",
+                                        key);
+                               errno = rc = -EINVAL;
+                               yaml_lnet_print_error(flags, "import", errmsg);
                                goto free_reply;
+                       }
 
                        rc = parse_long((char *)event.data.scalar.value,
                                        &value);
-                       if (rc != 0)
+                       if (rc != 0) {
+                               snprintf(errmsg, LNET_MAX_STR_LEN,
+                                        "invalid value '%s' for key '%s'",
+                                        (char *)event.data.scalar.value, key);
+                               errno = rc = -EINVAL;
+                               yaml_lnet_print_error(flags, "import", errmsg);
                                goto free_reply;
+                       }
 
                        rc = yaml_import_global_settings(key, value, cmd,
                                                         show_rc, err_rc);
index 1672ab0..fdb9a45 100755 (executable)
@@ -1051,6 +1051,36 @@ test_26() {
 }
 run_test 26 "Delete peer with primary nid locked"
 
+test_27() {
+       reinit_dlc || return $?
+
+       local tmp=$(mktemp)
+
+       echo "foobar:" > $tmp
+       do_lnetctl import $tmp 2>&1 | grep -q "invalid key" ||
+               error "Expected import to detect invalid key"
+
+       cat ${GLOBAL_YAML_FILE} > $tmp
+
+       grep -q discovery $tmp ||
+               error "Expect discovery param in global params"
+
+       sed -i 's/discovery:.*/discovery:/' $tmp ||
+               error "Failed to edit $tmp rc $?"
+
+       do_lnetctl import $tmp 2>&1 | grep -q "no value" ||
+               error "Expected import to detect missing value"
+
+       sed -i 's/discovery:/discovery: foo/' $tmp ||
+               error "Failed to edit $tmp rc $?"
+
+       do_lnetctl import $tmp 2>&1 | grep -q "invalid value" ||
+               error "Expected import to detect invalid value"
+
+       rm -f $tmp
+}
+run_test 27 "Import bad config should fail gracefully"
+
 test_99a() {
        reinit_dlc || return $?