|
|
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 |
|