-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
xen/hypercall: fix hypercall fallback code for very old hypervisors
While copying the argument structures in HYPERVISOR_event_channel_op() and HYPERVISOR_physdev_op() into the local variable is sufficiently safe even if the actual structure is smaller than the container one, copying back eventual output values the same way isn't: This may collide with on-stack variables (particularly "rc") which may change between the first and second memcpy() (i.e. the second memcpy() could discard that change). Move the fallback code into out-of-line functions, and handle all of the operations known by this old a hypervisor individually: Some don't require copying back anything at all, and for the rest use the individual argument structures' sizes rather than the container's. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> [v2: Reduce #define/#undef usage in HYPERVISOR_physdev_op_compat().] [v3: Fix compile errors when modules use said hypercalls] [v4: Add xen_ prefix to the HYPERCALL_..] [v5: Alter the name and only EXPORT_SYMBOL_GPL one of them] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
- Loading branch information
Jan Beulich
authored and
Konrad Rzeszutek Wilk
committed
Nov 4, 2012
1 parent
95a7d76
commit cf47a83
Showing
3 changed files
with
88 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include <linux/kernel.h> | ||
#include <linux/string.h> | ||
#include <linux/bug.h> | ||
#include <linux/export.h> | ||
#include <asm/hypervisor.h> | ||
#include <asm/xen/hypercall.h> | ||
|
||
int xen_event_channel_op_compat(int cmd, void *arg) | ||
{ | ||
struct evtchn_op op; | ||
int rc; | ||
|
||
op.cmd = cmd; | ||
memcpy(&op.u, arg, sizeof(op.u)); | ||
rc = _hypercall1(int, event_channel_op_compat, &op); | ||
|
||
switch (cmd) { | ||
case EVTCHNOP_close: | ||
case EVTCHNOP_send: | ||
case EVTCHNOP_bind_vcpu: | ||
case EVTCHNOP_unmask: | ||
/* no output */ | ||
break; | ||
|
||
#define COPY_BACK(eop) \ | ||
case EVTCHNOP_##eop: \ | ||
memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \ | ||
break | ||
|
||
COPY_BACK(bind_interdomain); | ||
COPY_BACK(bind_virq); | ||
COPY_BACK(bind_pirq); | ||
COPY_BACK(status); | ||
COPY_BACK(alloc_unbound); | ||
COPY_BACK(bind_ipi); | ||
#undef COPY_BACK | ||
|
||
default: | ||
WARN_ON(rc != -ENOSYS); | ||
break; | ||
} | ||
|
||
return rc; | ||
} | ||
EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); | ||
|
||
int HYPERVISOR_physdev_op_compat(int cmd, void *arg) | ||
{ | ||
struct physdev_op op; | ||
int rc; | ||
|
||
op.cmd = cmd; | ||
memcpy(&op.u, arg, sizeof(op.u)); | ||
rc = _hypercall1(int, physdev_op_compat, &op); | ||
|
||
switch (cmd) { | ||
case PHYSDEVOP_IRQ_UNMASK_NOTIFY: | ||
case PHYSDEVOP_set_iopl: | ||
case PHYSDEVOP_set_iobitmap: | ||
case PHYSDEVOP_apic_write: | ||
/* no output */ | ||
break; | ||
|
||
#define COPY_BACK(pop, fld) \ | ||
case PHYSDEVOP_##pop: \ | ||
memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \ | ||
break | ||
|
||
COPY_BACK(irq_status_query, irq_status_query); | ||
COPY_BACK(apic_read, apic_op); | ||
COPY_BACK(ASSIGN_VECTOR, irq_op); | ||
#undef COPY_BACK | ||
|
||
default: | ||
WARN_ON(rc != -ENOSYS); | ||
break; | ||
} | ||
|
||
return rc; | ||
} |