| From a29fc3936943a9efbd88bd306f829ff7f50ebd99 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 10 Aug 2018 23:06:11 +0000 |
| Subject: Drivers: hv: vmbus: Fix synic per-cpu context initialization |
| |
| From: Michael Kelley <mikelley@microsoft.com> |
| |
| [ 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> |
| --- |
| drivers/hv/hv.c | 15 ++++++++++++--- |
| 1 file changed, 12 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c |
| index 8e923e70e5945..12bc9fa211117 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); |
| |
| -- |
| 2.20.1 |
| |