Blame SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch

712bc0
From 297d6b6e56c2977fc504c61bbeeaa21296923f89 Mon Sep 17 00:00:00 2001
712bc0
From: Paul Meyer <Paul.Meyer@microsoft.com>
712bc0
Date: Tue, 14 Nov 2017 13:06:47 -0700
712bc0
Subject: [PATCH] hv: kvp: Avoid reading past allocated blocks from KVP file
712bc0
712bc0
While reading in more than one block (50) of KVP records, the allocation
712bc0
goes per block, but the reads used the total number of allocated records
712bc0
(without resetting the pointer/stream). This causes the records buffer to
712bc0
overrun when the refresh reads more than one block over the previous
712bc0
capacity (e.g. reading more than 100 KVP records whereas the in-memory
712bc0
database was empty before).
712bc0
712bc0
Fix this by reading the correct number of KVP records from file each time.
712bc0
712bc0
Signed-off-by: Paul Meyer <Paul.Meyer@microsoft.com>
712bc0
Signed-off-by: Long Li <longli@microsoft.com>
712bc0
Cc: stable@vger.kernel.org
712bc0
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
712bc0
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
712bc0
---
712bc0
 tools/hv/hv_kvp_daemon.c | 70 ++++++++++--------------------------------------
712bc0
 1 file changed, 14 insertions(+), 56 deletions(-)
712bc0
712bc0
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
712bc0
index eaa3bec273c8..4c99c57736ce 100644
712bc0
--- a/tools/hv/hv_kvp_daemon.c
712bc0
+++ b/tools/hv/hv_kvp_daemon.c
712bc0
@@ -193,11 +193,14 @@ static void kvp_update_mem_state(int pool)
712bc0
 	for (;;) {
712bc0
 		readp = &record[records_read];
712bc0
 		records_read += fread(readp, sizeof(struct kvp_record),
712bc0
-					ENTRIES_PER_BLOCK * num_blocks,
712bc0
-					filep);
712bc0
+				ENTRIES_PER_BLOCK * num_blocks - records_read,
712bc0
+				filep);
712bc0
 
712bc0
 		if (ferror(filep)) {
712bc0
-			syslog(LOG_ERR, "Failed to read file, pool: %d", pool);
712bc0
+			syslog(LOG_ERR,
712bc0
+				"Failed to read file, pool: %d; error: %d %s",
712bc0
+				 pool, errno, strerror(errno));
712bc0
+			kvp_release_lock(pool);
712bc0
 			exit(EXIT_FAILURE);
712bc0
 		}
712bc0
 
712bc0
@@ -210,6 +213,7 @@ static void kvp_update_mem_state(int pool)
712bc0
 
712bc0
 			if (record == NULL) {
712bc0
 				syslog(LOG_ERR, "malloc failed");
712bc0
+				kvp_release_lock(pool);
712bc0
 				exit(EXIT_FAILURE);
712bc0
 			}
712bc0
 			continue;
712bc0
@@ -224,15 +228,11 @@ static void kvp_update_mem_state(int pool)
712bc0
 	fclose(filep);
712bc0
 	kvp_release_lock(pool);
712bc0
 }
712bc0
+
712bc0
 static int kvp_file_init(void)
712bc0
 {
712bc0
 	int  fd;
712bc0
-	FILE *filep;
712bc0
-	size_t records_read;
712bc0
 	char *fname;
712bc0
-	struct kvp_record *record;
712bc0
-	struct kvp_record *readp;
712bc0
-	int num_blocks;
712bc0
 	int i;
712bc0
 	int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
712bc0
 
712bc0
@@ -246,61 +246,19 @@ static int kvp_file_init(void)
712bc0
 
712bc0
 	for (i = 0; i < KVP_POOL_COUNT; i++) {
712bc0
 		fname = kvp_file_info[i].fname;
712bc0
-		records_read = 0;
712bc0
-		num_blocks = 1;
712bc0
 		sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i);
712bc0
 		fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */);
712bc0
 
712bc0
 		if (fd == -1)
712bc0
 			return 1;
712bc0
 
712bc0
-
712bc0
-		filep = fopen(fname, "re");
712bc0
-		if (!filep) {
712bc0
-			close(fd);
712bc0
-			return 1;
712bc0
-		}
712bc0
-
712bc0
-		record = malloc(alloc_unit * num_blocks);
712bc0
-		if (record == NULL) {
712bc0
-			fclose(filep);
712bc0
-			close(fd);
712bc0
-			return 1;
712bc0
-		}
712bc0
-		for (;;) {
712bc0
-			readp = &record[records_read];
712bc0
-			records_read += fread(readp, sizeof(struct kvp_record),
712bc0
-					ENTRIES_PER_BLOCK,
712bc0
-					filep);
712bc0
-
712bc0
-			if (ferror(filep)) {
712bc0
-				syslog(LOG_ERR, "Failed to read file, pool: %d",
712bc0
-				       i);
712bc0
-				exit(EXIT_FAILURE);
712bc0
-			}
712bc0
-
712bc0
-			if (!feof(filep)) {
712bc0
-				/*
712bc0
-				 * We have more data to read.
712bc0
-				 */
712bc0
-				num_blocks++;
712bc0
-				record = realloc(record, alloc_unit *
712bc0
-						num_blocks);
712bc0
-				if (record == NULL) {
712bc0
-					fclose(filep);
712bc0
-					close(fd);
712bc0
-					return 1;
712bc0
-				}
712bc0
-				continue;
712bc0
-			}
712bc0
-			break;
712bc0
-		}
712bc0
 		kvp_file_info[i].fd = fd;
712bc0
-		kvp_file_info[i].num_blocks = num_blocks;
712bc0
-		kvp_file_info[i].records = record;
712bc0
-		kvp_file_info[i].num_records = records_read;
712bc0
-		fclose(filep);
712bc0
-
712bc0
+		kvp_file_info[i].num_blocks = 1;
712bc0
+		kvp_file_info[i].records = malloc(alloc_unit);
712bc0
+		if (kvp_file_info[i].records == NULL)
712bc0
+			return 1;
712bc0
+		kvp_file_info[i].num_records = 0;
712bc0
+		kvp_update_mem_state(i);
712bc0
 	}
712bc0
 
712bc0
 	return 0;
712bc0
-- 
712bc0
2.14.3
712bc0