diff --git a/SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch b/SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch new file mode 100644 index 0000000..fcabe51 --- /dev/null +++ b/SOURCES/0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch @@ -0,0 +1,141 @@ +From 297d6b6e56c2977fc504c61bbeeaa21296923f89 Mon Sep 17 00:00:00 2001 +From: Paul Meyer +Date: Tue, 14 Nov 2017 13:06:47 -0700 +Subject: [PATCH] hv: kvp: Avoid reading past allocated blocks from KVP file + +While reading in more than one block (50) of KVP records, the allocation +goes per block, but the reads used the total number of allocated records +(without resetting the pointer/stream). This causes the records buffer to +overrun when the refresh reads more than one block over the previous +capacity (e.g. reading more than 100 KVP records whereas the in-memory +database was empty before). + +Fix this by reading the correct number of KVP records from file each time. + +Signed-off-by: Paul Meyer +Signed-off-by: Long Li +Cc: stable@vger.kernel.org +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman +--- + tools/hv/hv_kvp_daemon.c | 70 ++++++++++-------------------------------------- + 1 file changed, 14 insertions(+), 56 deletions(-) + +diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c +index eaa3bec273c8..4c99c57736ce 100644 +--- a/tools/hv/hv_kvp_daemon.c ++++ b/tools/hv/hv_kvp_daemon.c +@@ -193,11 +193,14 @@ static void kvp_update_mem_state(int pool) + for (;;) { + readp = &record[records_read]; + records_read += fread(readp, sizeof(struct kvp_record), +- ENTRIES_PER_BLOCK * num_blocks, +- filep); ++ ENTRIES_PER_BLOCK * num_blocks - records_read, ++ filep); + + if (ferror(filep)) { +- syslog(LOG_ERR, "Failed to read file, pool: %d", pool); ++ syslog(LOG_ERR, ++ "Failed to read file, pool: %d; error: %d %s", ++ pool, errno, strerror(errno)); ++ kvp_release_lock(pool); + exit(EXIT_FAILURE); + } + +@@ -210,6 +213,7 @@ static void kvp_update_mem_state(int pool) + + if (record == NULL) { + syslog(LOG_ERR, "malloc failed"); ++ kvp_release_lock(pool); + exit(EXIT_FAILURE); + } + continue; +@@ -224,15 +228,11 @@ static void kvp_update_mem_state(int pool) + fclose(filep); + kvp_release_lock(pool); + } ++ + static int kvp_file_init(void) + { + int fd; +- FILE *filep; +- size_t records_read; + char *fname; +- struct kvp_record *record; +- struct kvp_record *readp; +- int num_blocks; + int i; + int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; + +@@ -246,61 +246,19 @@ static int kvp_file_init(void) + + for (i = 0; i < KVP_POOL_COUNT; i++) { + fname = kvp_file_info[i].fname; +- records_read = 0; +- num_blocks = 1; + sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i); + fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */); + + if (fd == -1) + return 1; + +- +- filep = fopen(fname, "re"); +- if (!filep) { +- close(fd); +- return 1; +- } +- +- record = malloc(alloc_unit * num_blocks); +- if (record == NULL) { +- fclose(filep); +- close(fd); +- return 1; +- } +- for (;;) { +- readp = &record[records_read]; +- records_read += fread(readp, sizeof(struct kvp_record), +- ENTRIES_PER_BLOCK, +- filep); +- +- if (ferror(filep)) { +- syslog(LOG_ERR, "Failed to read file, pool: %d", +- i); +- exit(EXIT_FAILURE); +- } +- +- if (!feof(filep)) { +- /* +- * We have more data to read. +- */ +- num_blocks++; +- record = realloc(record, alloc_unit * +- num_blocks); +- if (record == NULL) { +- fclose(filep); +- close(fd); +- return 1; +- } +- continue; +- } +- break; +- } + kvp_file_info[i].fd = fd; +- kvp_file_info[i].num_blocks = num_blocks; +- kvp_file_info[i].records = record; +- kvp_file_info[i].num_records = records_read; +- fclose(filep); +- ++ kvp_file_info[i].num_blocks = 1; ++ kvp_file_info[i].records = malloc(alloc_unit); ++ if (kvp_file_info[i].records == NULL) ++ return 1; ++ kvp_file_info[i].num_records = 0; ++ kvp_update_mem_state(i); + } + + return 0; +-- +2.14.3 + diff --git a/SOURCES/hypervkvpd.service b/SOURCES/hypervkvpd.service index 4ecfd62..d8bfdf3 100644 --- a/SOURCES/hypervkvpd.service +++ b/SOURCES/hypervkvpd.service @@ -1,6 +1,7 @@ [Unit] Description=Hyper-V KVP daemon BindsTo=sys-devices-virtual-misc-vmbus\x21hv_kvp.device +After=network.target [Service] Type=simple diff --git a/SPECS/hyperv-daemons.spec b/SPECS/hyperv-daemons.spec index 7167541..ebbbf31 100644 --- a/SPECS/hyperv-daemons.spec +++ b/SPECS/hyperv-daemons.spec @@ -13,7 +13,7 @@ Name: hyperv-daemons Version: 0 -Release: 0.30%{?snapver}%{?dist} +Release: 0.32%{?snapver}%{?dist} Summary: HyperV daemons suite Group: System Environment/Daemons @@ -52,6 +52,8 @@ Source302: bondvf.sh Patch0: hypervkvpd-0-corrected_paths_to_external_scripts.patch # rhbz#872566 Patch1: hypervkvpd-0-long_file_names_from_readdir.patch +# rhbz#1529745 +Patch2: 0001-hv-kvp-Avoid-reading-past-allocated-blocks-from-KVP-.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) # HyperV is available only on x86 architectures @@ -154,6 +156,7 @@ cp -pvL %{SOURCE201} hypervfcopyd.service %patch0 -p1 -b .external_scripts %patch1 -p1 -b .long_names +%patch2 -p3 -b .kvp_past_allocated %build # HYPERV KVP DAEMON @@ -291,6 +294,12 @@ fi %{_datarootdir}/hyperv-tools %changelog +* Wed Jan 03 2018 Vitaly Kuznetsov - 0-0.32.20161211git +- Include 'Avoid reading past allocated blocks from KVP file' fix (#1529745) + +* Mon Dec 11 2017 Eduardo Otubo - 0-0.31.20161211git +- Start KVP daemon after network is setup (#1377550) + * Thu Jan 19 2017 Vitaly Kuznetsov - 0-0.30.20161211git - Use '-gt' instead of '>' to do the right comparison (#1414822) - hyperv-tools subpackage added (#1378710)