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

Wolfgang Bumiller w.bumiller at proxmox.com
Fri Aug 30 10:14:45 CEST 2019


applied with the following fixup commit we talked about off-list:

---8<---
>From c22040264ebe7b5b8b1dcd16c1af8d174600b1ea Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 30 Aug 2019 10:09:46 +0200
Subject: [PATCH cluster] pmxcfs: cleanup remaining_size calculation

using an end-pointer it's a bit more readable and gets rid
of an (int) cast

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 data/src/status.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/data/src/status.c b/data/src/status.c
index 1dfde53..e9983b7 100644
--- a/data/src/status.c
+++ b/data/src/status.c
@@ -803,8 +803,9 @@ cfs_create_vmlist_msg(GString *str)
 static char *
 _get_property_value(char *conf, int conf_size, const char *prop, int prop_len)
 {
+	const char *const conf_end = conf + conf_size;
 	char *line = conf;
-	int remaining_size;
+	size_t remaining_size;
 
 	char *next_newline = memchr(conf, '\n', conf_size);
 	if (next_newline == NULL) {
@@ -838,11 +839,11 @@ _get_property_value(char *conf, int conf_size, const char *prop, int prop_len)
 			return v_start;
 		}
 next:
-		remaining_size = conf_size - (int) (next_newline - conf);
-		if (remaining_size <= 1 || remaining_size <= prop_len) {
+		line = next_newline + 1;
+		remaining_size = conf_end - line;
+		if (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
-- 
2.20.1

---8<---

On Thu, Aug 29, 2019 at 02:45:08PM +0200, Thomas Lamprecht wrote:
> 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