[pve-devel] [PATCH cluster] pmxcfs: get config properties: ensure we do not read after the config

Thomas Lamprecht t.lamprecht at proxmox.com
Thu Aug 29 14:45:08 CEST 2019


pmxcfs files need to be treated as blobs, while we can have some
assumptions on certain files, like the $vmid.conf ones, we should
still cope with problematic files.
Especially, the files may not end with \0, so always ensure that we
read at most file-size bytes.

Replace strtok_r, which assumes that the data is NUL terminated, and
use memchr, with logic ensuring that we never read over the size
returned by memdb_read.

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---
 data/src/status.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/data/src/status.c b/data/src/status.c
index e437476..1dfde53 100644
--- a/data/src/status.c
+++ b/data/src/status.c
@@ -801,15 +801,21 @@ cfs_create_vmlist_msg(GString *str)
 // currently we only look at the current configuration in place, i.e., *no*
 // snapshort and *no* pending changes
 static char *
-_get_property_value(char *conf, const char *prop, int prop_len)
+_get_property_value(char *conf, int conf_size, const char *prop, int prop_len)
 {
-	char *line = NULL, *temp = NULL;
+	char *line = conf;
+	int remaining_size;
+
+	char *next_newline = memchr(conf, '\n', conf_size);
+	if (next_newline == NULL) {
+		return NULL; // valid property lines end with \n, but none in the config
+	}
+	*next_newline = '\0';
 
-	line = strtok_r(conf, "\n", &temp);
 	while (line != NULL) {
 		if (!line[0]) goto next;
 
-		// snapshot or pending section start and nothing found yet
+		// snapshot or pending section start, but nothing found yet -> not found
 		if (line[0] == '[') return NULL;
 		// properties start with /^[a-z]/, so continue early if not
 		if (line[0] < 'a' || line[0] > 'z') goto next;
@@ -832,7 +838,16 @@ _get_property_value(char *conf, const char *prop, int prop_len)
 			return v_start;
 		}
 next:
-		line = strtok_r(NULL, "\n", &temp);
+		remaining_size = conf_size - (int) (next_newline - conf);
+		if (remaining_size <= 1 || remaining_size <= prop_len) {
+			return NULL;
+		}
+		line = next_newline + 1;
+		next_newline = memchr(line, '\n', remaining_size);
+		if (next_newline == NULL) {
+			return NULL; // valid property lines end with \n, but none in the config
+		}
+		*next_newline = '\0';
 	}
 
 	return NULL; // not found
@@ -884,7 +899,7 @@ cfs_create_guest_conf_property_msg(GString *str, memdb_t *memdb, const char *pro
 		if (tmp == NULL) goto err;
 		if (size <= prop_len) goto ret;
 
-		char *val = _get_property_value(tmp, prop, prop_len);
+		char *val = _get_property_value(tmp, size, prop, prop_len);
 		if (val == NULL) goto ret;
 
 		g_string_append_printf(str, "\"%u\":{", vmid);
@@ -907,7 +922,7 @@ cfs_create_guest_conf_property_msg(GString *str, memdb_t *memdb, const char *pro
 			int size = memdb_read(memdb, path->str, &tmp);
 			if (tmp == NULL || size <= prop_len) continue;
 
-			char *val = _get_property_value(tmp, prop, prop_len);
+			char *val = _get_property_value(tmp, size, prop, prop_len);
 			if (val == NULL) continue;
 
 			if (!first) g_string_append_printf(str, ",\n");
-- 
2.20.1




More information about the pve-devel mailing list