Skip to content

Commit 52e5070

Browse files
committed
Merge tag 'hyperv-fixes-signed-20240411' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv fixes from Wei Liu: - Some cosmetic changes (Erni Sri Satya Vennela, Li Zhijian) - Introduce hv_numa_node_to_pxm_info() (Nuno Das Neves) - Fix KVP daemon to handle IPv4 and IPv6 combination for keyfile format (Shradha Gupta) - Avoid freeing decrypted memory in a confidential VM (Rick Edgecombe and Michael Kelley) * tag 'hyperv-fixes-signed-20240411' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: Drivers: hv: vmbus: Don't free ring buffers that couldn't be re-encrypted uio_hv_generic: Don't free decrypted memory hv_netvsc: Don't free decrypted memory Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl Drivers: hv: vmbus: Leak pages if set_memory_encrypted() fails hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for keyfile format hv: vmbus: Convert sprintf() family to sysfs_emit() family mshyperv: Introduce hv_numa_node_to_pxm_info() x86/hyperv: Cosmetic changes for hv_apic.c
2 parents 00dcf5d + 30d18df commit 52e5070

File tree

11 files changed

+307
-149
lines changed

11 files changed

+307
-149
lines changed

arch/x86/hyperv/hv_apic.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static bool cpu_is_self(int cpu)
105105
* IPI implementation on Hyper-V.
106106
*/
107107
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
108-
bool exclude_self)
108+
bool exclude_self)
109109
{
110110
struct hv_send_ipi_ex *ipi_arg;
111111
unsigned long flags;
@@ -132,8 +132,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
132132
if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
133133
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
134134

135-
nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask,
136-
exclude_self ? cpu_is_self : NULL);
135+
nr_bank = cpumask_to_vpset_skip(&ipi_arg->vp_set, mask,
136+
exclude_self ? cpu_is_self : NULL);
137137

138138
/*
139139
* 'nr_bank <= 0' means some CPUs in cpumask can't be
@@ -147,15 +147,15 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
147147
}
148148

149149
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
150-
ipi_arg, NULL);
150+
ipi_arg, NULL);
151151

152152
ipi_mask_ex_done:
153153
local_irq_restore(flags);
154154
return hv_result_success(status);
155155
}
156156

157157
static bool __send_ipi_mask(const struct cpumask *mask, int vector,
158-
bool exclude_self)
158+
bool exclude_self)
159159
{
160160
int cur_cpu, vcpu, this_cpu = smp_processor_id();
161161
struct hv_send_ipi ipi_arg;
@@ -181,7 +181,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
181181
return false;
182182
}
183183

184-
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
184+
if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
185185
return false;
186186

187187
/*
@@ -218,7 +218,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
218218
}
219219

220220
status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
221-
ipi_arg.cpu_mask);
221+
ipi_arg.cpu_mask);
222222
return hv_result_success(status);
223223

224224
do_ex_hypercall:
@@ -241,7 +241,7 @@ static bool __send_ipi_one(int cpu, int vector)
241241
return false;
242242
}
243243

244-
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
244+
if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
245245
return false;
246246

247247
if (vp >= 64)

arch/x86/hyperv/hv_proc.c

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <linux/vmalloc.h>
44
#include <linux/mm.h>
55
#include <linux/clockchips.h>
6-
#include <linux/acpi.h>
76
#include <linux/hyperv.h>
87
#include <linux/slab.h>
98
#include <linux/cpuhotplug.h>
@@ -116,12 +115,11 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
116115

117116
int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
118117
{
119-
struct hv_add_logical_processor_in *input;
120-
struct hv_add_logical_processor_out *output;
118+
struct hv_input_add_logical_processor *input;
119+
struct hv_output_add_logical_processor *output;
121120
u64 status;
122121
unsigned long flags;
123122
int ret = HV_STATUS_SUCCESS;
124-
int pxm = node_to_pxm(node);
125123

126124
/*
127125
* When adding a logical processor, the hypervisor may return
@@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
137135

138136
input->lp_index = lp_index;
139137
input->apic_id = apic_id;
140-
input->flags = 0;
141-
input->proximity_domain_info.domain_id = pxm;
142-
input->proximity_domain_info.flags.reserved = 0;
143-
input->proximity_domain_info.flags.proximity_info_valid = 1;
144-
input->proximity_domain_info.flags.proximity_preferred = 1;
138+
input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
145139
status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
146140
input, output);
147141
local_irq_restore(flags);
@@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
166160
u64 status;
167161
unsigned long irq_flags;
168162
int ret = HV_STATUS_SUCCESS;
169-
int pxm = node_to_pxm(node);
170163

171164
/* Root VPs don't seem to need pages deposited */
172165
if (partition_id != hv_current_partition_id) {
@@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
185178
input->vp_index = vp_index;
186179
input->flags = flags;
187180
input->subnode_type = HvSubnodeAny;
188-
if (node != NUMA_NO_NODE) {
189-
input->proximity_domain_info.domain_id = pxm;
190-
input->proximity_domain_info.flags.reserved = 0;
191-
input->proximity_domain_info.flags.proximity_info_valid = 1;
192-
input->proximity_domain_info.flags.proximity_preferred = 1;
193-
} else {
194-
input->proximity_domain_info.as_uint64 = 0;
195-
}
181+
input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
196182
status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
197183
local_irq_restore(irq_flags);
198184

drivers/hv/channel.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ void vmbus_free_ring(struct vmbus_channel *channel)
153153
hv_ringbuffer_cleanup(&channel->inbound);
154154

155155
if (channel->ringbuffer_page) {
156-
__free_pages(channel->ringbuffer_page,
156+
/* In a CoCo VM leak the memory if it didn't get re-encrypted */
157+
if (!channel->ringbuffer_gpadlhandle.decrypted)
158+
__free_pages(channel->ringbuffer_page,
157159
get_order(channel->ringbuffer_pagecount
158160
<< PAGE_SHIFT));
159161
channel->ringbuffer_page = NULL;
@@ -436,9 +438,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
436438
(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
437439

438440
ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
439-
if (ret)
441+
if (ret) {
442+
gpadl->decrypted = false;
440443
return ret;
444+
}
441445

446+
/*
447+
* Set the "decrypted" flag to true for the set_memory_decrypted()
448+
* success case. In the failure case, the encryption state of the
449+
* memory is unknown. Leave "decrypted" as true to ensure the
450+
* memory will be leaked instead of going back on the free list.
451+
*/
452+
gpadl->decrypted = true;
442453
ret = set_memory_decrypted((unsigned long)kbuffer,
443454
PFN_UP(size));
444455
if (ret) {
@@ -527,9 +538,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
527538

528539
kfree(msginfo);
529540

530-
if (ret)
531-
set_memory_encrypted((unsigned long)kbuffer,
532-
PFN_UP(size));
541+
if (ret) {
542+
/*
543+
* If set_memory_encrypted() fails, the decrypted flag is
544+
* left as true so the memory is leaked instead of being
545+
* put back on the free list.
546+
*/
547+
if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
548+
gpadl->decrypted = false;
549+
}
533550

534551
return ret;
535552
}
@@ -850,6 +867,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad
850867
if (ret)
851868
pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
852869

870+
gpadl->decrypted = ret;
871+
853872
return ret;
854873
}
855874
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);

drivers/hv/connection.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,17 @@ int vmbus_connect(void)
237237
vmbus_connection.monitor_pages[0], 1);
238238
ret |= set_memory_decrypted((unsigned long)
239239
vmbus_connection.monitor_pages[1], 1);
240-
if (ret)
240+
if (ret) {
241+
/*
242+
* If set_memory_decrypted() fails, the encryption state
243+
* of the memory is unknown. So leak the memory instead
244+
* of risking returning decrypted memory to the free list.
245+
* For simplicity, always handle both pages the same.
246+
*/
247+
vmbus_connection.monitor_pages[0] = NULL;
248+
vmbus_connection.monitor_pages[1] = NULL;
241249
goto cleanup;
250+
}
242251

243252
/*
244253
* Set_memory_decrypted() will change the memory contents if
@@ -337,13 +346,19 @@ void vmbus_disconnect(void)
337346
vmbus_connection.int_page = NULL;
338347
}
339348

340-
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1);
341-
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1);
349+
if (vmbus_connection.monitor_pages[0]) {
350+
if (!set_memory_encrypted(
351+
(unsigned long)vmbus_connection.monitor_pages[0], 1))
352+
hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
353+
vmbus_connection.monitor_pages[0] = NULL;
354+
}
342355

343-
hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
344-
hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
345-
vmbus_connection.monitor_pages[0] = NULL;
346-
vmbus_connection.monitor_pages[1] = NULL;
356+
if (vmbus_connection.monitor_pages[1]) {
357+
if (!set_memory_encrypted(
358+
(unsigned long)vmbus_connection.monitor_pages[1], 1))
359+
hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
360+
vmbus_connection.monitor_pages[1] = NULL;
361+
}
347362
}
348363

349364
/*

0 commit comments

Comments
 (0)