diff options
author | Michael Kelley <mikelley@microsoft.com> | 2018-08-10 23:06:11 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-11-20 18:46:31 +0100 |
commit | b0d54e40f3c44f43862e3f0952b3b0bf0984e014 (patch) | |
tree | 6379dba11447e18f0208cd80e967614264d43375 /drivers/hv/hv.c | |
parent | a1d374ea1e95aacbace98ff2b7c657b86f5bab8e (diff) | |
download | linux-stable-b0d54e40f3c44f43862e3f0952b3b0bf0984e014.tar.gz linux-stable-b0d54e40f3c44f43862e3f0952b3b0bf0984e014.tar.bz2 linux-stable-b0d54e40f3c44f43862e3f0952b3b0bf0984e014.zip |
Drivers: hv: vmbus: Fix synic per-cpu context initialization
[ Upstream commit f25a7ece08bdb1f2b3c4bbeae942682fc3a99dde ]
If hv_synic_alloc() errors out, the state of the per-cpu context
for some CPUs is unknown since the zero'ing is done as each
CPU is iterated over. In such case, hv_synic_cleanup() may try to
free memory based on uninitialized values. Fix this by zero'ing
the per-cpu context for all CPUs before doing any memory
allocations that might fail.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/hv/hv.c')
-rw-r--r-- | drivers/hv/hv.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 8e923e70e594..12bc9fa21111 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -189,6 +189,17 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu) int hv_synic_alloc(void) { int cpu; + struct hv_per_cpu_context *hv_cpu; + + /* + * First, zero all per-cpu memory areas so hv_synic_free() can + * detect what memory has been allocated and cleanup properly + * after any failures. + */ + for_each_present_cpu(cpu) { + hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); + memset(hv_cpu, 0, sizeof(*hv_cpu)); + } hv_context.hv_numa_map = kcalloc(nr_node_ids, sizeof(struct cpumask), GFP_KERNEL); @@ -198,10 +209,8 @@ int hv_synic_alloc(void) } for_each_present_cpu(cpu) { - struct hv_per_cpu_context *hv_cpu - = per_cpu_ptr(hv_context.cpu_context, cpu); + hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - memset(hv_cpu, 0, sizeof(*hv_cpu)); tasklet_init(&hv_cpu->msg_dpc, vmbus_on_msg_dpc, (unsigned long) hv_cpu); |