瀏覽代碼

qcacmn: Add support to validate roaming cfg file

Currently host is not validating roaming cfg file
per key and value and only checking if no unpermitted
characters are present in the file before parsing.

To address this issue, parse roaming ini file
only if no unpermitted characters are present in the key
and value otherwise fall back to roaming backup ini file.
If the backup file don't pass validation criteria's
then don't parse it as well.

Change-Id: I6068d41ed67698ec60c0985151282936590b1544
CRs-Fixed: 3678910
Asutosh Mohapatra 1 年之前
父節點
當前提交
817b9dfca7
共有 1 個文件被更改,包括 95 次插入3 次删除
  1. 95 3
      qdf/src/qdf_parse.c

+ 95 - 3
qdf/src/qdf_parse.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -113,6 +113,13 @@ static QDF_STATUS qdf_ini_read_values(char **main_cursor,
 				return QDF_STATUS_SUCCESS;
 			}
 		} else if (key[0] != '\0') {
+			if (!__qdf_str_cmp(key, "END")) {
+				key[3] = '\0';
+				*section_item = 0;
+				*main_cursor = cursor;
+				*read_key = key;
+				return QDF_STATUS_SUCCESS;
+			}
 			qdf_err("Invalid *.ini syntax '%s'", key);
 			return QDF_STATUS_E_INVAL;
 		}
@@ -150,6 +157,9 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context,
 
 	while (qdf_ini_read_values(&cursor, &read_key, &read_value,
 				   &section_item) == QDF_STATUS_SUCCESS) {
+		if (!__qdf_str_cmp(read_key, "END"))
+			break;
+
 		if (!section_item) {
 			status = item_cb(context, read_key, read_value);
 			if (QDF_IS_STATUS_ERROR(status))
@@ -214,6 +224,9 @@ QDF_STATUS qdf_ini_section_parse(const char *ini_path, void *context,
 
 	while (qdf_ini_read_values(&cursor, &read_key, &read_value,
 				   &section_item) == QDF_STATUS_SUCCESS) {
+		if (!__qdf_str_cmp(read_key, "END"))
+			break;
+
 		if (section_item) {
 			if (qdf_str_cmp(read_key, section_name) == 0) {
 				section_found = 1;
@@ -255,9 +268,64 @@ QDF_STATUS qdf_ini_section_parse(const char *ini_path, void *context,
 
 qdf_export_symbol(qdf_ini_section_parse);
 
-static bool is_valid_key(char **main_cursor)
+/**
+ * qdf_validate_key() - Check if ini key is valid
+ * @key: Pointer to key
+ *
+ * Return: Return SUCCESS if key is valid else return INVALID
+ */
+static QDF_STATUS qdf_validate_key(char *key)
+{
+	int i;
+
+	for (i = 0; key[i] != '\0' ; i++) {
+		if ((key[i] >= 'a' && key[i] <= 'z') ||
+		    (key[i] >= 'A' && key[i] <= 'Z') ||
+		    (key[i] >= '0' && key[i] <= '9') ||
+		    (key[i] == '_'))
+			continue;
+		else
+			return QDF_STATUS_E_INVAL;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * qdf_validate_value() - Validate ini value
+ * @value: Pointer to ini value
+ *
+ * Return: Return SUCCESS if value is valid else return INVALID
+ */
+static QDF_STATUS qdf_validate_value(char *value)
+{
+	int i;
+
+	for (i = 0; value[i] != '\0'; i++) {
+		if ((value[i] >= '0' && value[i] <= '9') ||
+		    (value[i] >= 'A' && value[i] <= 'Z') ||
+		    (value[i] >= 'a' && value[i] <= 'z') ||
+		    value[i] == ',' || value[i] == ':' ||
+		    value[i] == '-' || value[i] == '+')
+			continue;
+		else
+			return QDF_STATUS_E_INVAL;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * qdf_check_ini_validity() - Check if inis are valid
+ * @main_cursor: Pointer to main cursor
+ *
+ * Return: Return true if all inis are valid else false
+ */
+static bool qdf_check_ini_validity(char **main_cursor)
 {
 	char *cursor = *main_cursor;
+	char *read_key;
+	char *read_value;
+	bool section_item;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	while (*cursor != '\0') {
 		unsigned char *val = (unsigned char *)cursor;
@@ -277,6 +345,7 @@ static bool is_valid_key(char **main_cursor)
 		case '-':
 		case ' ':
 		case ':':
+		case ',':
 			cursor++;
 			break;
 
@@ -289,6 +358,29 @@ static bool is_valid_key(char **main_cursor)
 			break;
 		}
 	}
+
+	cursor = *main_cursor;
+	while ((status = qdf_ini_read_values(main_cursor, &read_key,
+			&read_value, &section_item)) == QDF_STATUS_SUCCESS) {
+		if (!section_item) {
+			if (!__qdf_str_cmp(read_key, "END"))
+				return true;
+			status = qdf_validate_key(read_key);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				status = QDF_STATUS_E_INVAL;
+				goto out;
+			}
+			status = qdf_validate_value(read_value);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				status = QDF_STATUS_E_INVAL;
+				goto out;
+			}
+		}
+	}
+
+out:
+	if (QDF_IS_STATUS_ERROR(status))
+		return false;
 	return true;
 }
 
@@ -311,7 +403,7 @@ bool qdf_valid_ini_check(const char  *ini_path)
 	/* foreach line */
 	cursor = fbuf;
 
-	is_valid = is_valid_key(&cursor);
+	is_valid = qdf_check_ini_validity(&cursor);
 
 	if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path))
 		qdf_module_param_file_free(fbuf);