# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 1dc45879fa5c925ef73eef76ab07a5b11e28e574
# Parent ccb437f2ed4e801cd7ecf2d87743b6d68ebe0d01
[IA64] Check privilege level for pal/sal/efi calls.
Previously a user was able to reset the machine.
Signed-off-by: Tristan Gingold <tristan.gingold@xxxxxxxx>
diff -r ccb437f2ed4e -r 1dc45879fa5c xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c Mon Mar 20 16:53:17 2006
+++ b/xen/arch/ia64/xen/hypercall.c Mon Mar 20 16:55:32 2006
@@ -66,13 +66,71 @@
(hypercall_t)do_ni_hypercall /* */
};
-int
-ia64_hypercall (struct pt_regs *regs)
+static int
+xen_hypercall (struct pt_regs *regs)
+{
+ switch (regs->r2) {
+ case __HYPERVISOR_dom0_op:
+ regs->r8 = do_dom0_op(guest_handle_from_ptr(regs->r14,
+ dom0_op_t));
+ break;
+
+ case __HYPERVISOR_memory_op:
+ /* we don't handle reservations; just return success */
+ {
+ struct xen_memory_reservation reservation;
+ void *arg = (void *) regs->r15;
+
+ switch(regs->r14) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ if (copy_from_user(&reservation, arg,
+ sizeof(reservation)))
+ regs->r8 = -EFAULT;
+ else
+ regs->r8 = reservation.nr_extents;
+ break;
+ default:
+ regs->r8 = do_memory_op((int) regs->r14,
guest_handle_from_ptr(regs->r15, void));
+ break;
+ }
+ }
+ break;
+
+ case __HYPERVISOR_event_channel_op:
+ regs->r8 = do_event_channel_op(guest_handle_from_ptr(regs->r14,
evtchn_op_t));
+ break;
+
+ case __HYPERVISOR_grant_table_op:
+ regs->r8 = do_grant_table_op((unsigned int) regs->r14,
guest_handle_from_ptr(regs->r15, void), (unsigned int) regs->r16);
+ break;
+
+ case __HYPERVISOR_console_io:
+ regs->r8 = do_console_io((int) regs->r14, (int) regs->r15,
guest_handle_from_ptr(regs->r16, char));
+ break;
+
+ case __HYPERVISOR_xen_version:
+ regs->r8 = do_xen_version((int) regs->r14,
guest_handle_from_ptr(regs->r15, void));
+ break;
+
+ case __HYPERVISOR_multicall:
+ regs->r8 = do_multicall(guest_handle_from_ptr(regs->r14,
multicall_entry_t), (unsigned int) regs->r15);
+ break;
+
+ default:
+ printf("unknown xen hypercall %lx\n", regs->r2);
+ regs->r8 = do_ni_hypercall();
+ }
+ return 1;
+}
+
+
+static int
+fw_hypercall (struct pt_regs *regs)
{
struct vcpu *v = current;
struct sal_ret_values x;
unsigned long *tv, *tc;
- int pi;
switch (regs->r2) {
case FW_HYPERCALL_PAL_CALL:
@@ -87,6 +145,7 @@
VCPU(v,pending_interruption) = 1;
#endif
if (regs->r28 == PAL_HALT_LIGHT) {
+ int pi;
#define SPURIOUS_VECTOR 15
pi = vcpu_check_pending_interrupts(v);
if (pi != SPURIOUS_VECTOR) {
@@ -165,66 +224,50 @@
// FIXME: need fixes in efi.h from 2.6.9
regs->r8 = EFI_UNSUPPORTED;
break;
- case 0xffff:
- regs->r8 = dump_privop_counts_to_user(
- (char *) vcpu_get_gr(v,32),
- (int) vcpu_get_gr(v,33));
- break;
- case 0xfffe:
- regs->r8 = zero_privop_counts_to_user(
- (char *) vcpu_get_gr(v,32),
- (int) vcpu_get_gr(v,33));
- break;
- case __HYPERVISOR_dom0_op:
- regs->r8 = do_dom0_op(guest_handle_from_ptr(regs->r14,
- dom0_op_t));
- break;
-
- case __HYPERVISOR_memory_op:
- /* we don't handle reservations; just return success */
- {
- struct xen_memory_reservation reservation;
- void *arg = (void *) regs->r15;
-
- switch(regs->r14) {
- case XENMEM_increase_reservation:
- case XENMEM_decrease_reservation:
- if (copy_from_user(&reservation, arg,
- sizeof(reservation)))
- regs->r8 = -EFAULT;
- else
- regs->r8 = reservation.nr_extents;
- break;
- default:
- regs->r8 = do_memory_op((int) regs->r14,
guest_handle_from_ptr(regs->r15, void));
- break;
- }
- }
- break;
-
- case __HYPERVISOR_event_channel_op:
- regs->r8 = do_event_channel_op(guest_handle_from_ptr(regs->r14,
evtchn_op_t));
- break;
-
- case __HYPERVISOR_grant_table_op:
- regs->r8 = do_grant_table_op((unsigned int) regs->r14,
guest_handle_from_ptr(regs->r15, void), (unsigned int) regs->r16);
- break;
-
- case __HYPERVISOR_console_io:
- regs->r8 = do_console_io((int) regs->r14, (int) regs->r15,
guest_handle_from_ptr(regs->r16, char));
- break;
-
- case __HYPERVISOR_xen_version:
- regs->r8 = do_xen_version((int) regs->r14,
guest_handle_from_ptr(regs->r15, void));
- break;
-
- case __HYPERVISOR_multicall:
- regs->r8 = do_multicall(guest_handle_from_ptr(regs->r14,
multicall_entry_t), (unsigned int) regs->r15);
- break;
-
default:
- printf("unknown hypercall %lx\n", regs->r2);
+ printf("unknown ia64 fw hypercall %lx\n", regs->r2);
regs->r8 = do_ni_hypercall();
}
return 1;
}
+
+int
+ia64_hypercall (struct pt_regs *regs)
+{
+ struct vcpu *v = current;
+ unsigned long index = regs->r2;
+
+ if (index >= FW_HYPERCALL_FIRST_USER) {
+ switch (index) {
+ case 0xffff:
+ regs->r8 = dump_privop_counts_to_user(
+ (char *) vcpu_get_gr(v,32),
+ (int) vcpu_get_gr(v,33));
+ break;
+ case 0xfffe:
+ regs->r8 = zero_privop_counts_to_user(
+ (char *) vcpu_get_gr(v,32),
+ (int) vcpu_get_gr(v,33));
+ break;
+ default:
+ printf("unknown user xen/ia64 hypercall %lx\n", index);
+ regs->r8 = do_ni_hypercall();
+ }
+ return 1;
+ }
+ else if (index >= FW_HYPERCALL_FIRST_ARCH) {
+ int privlvl;
+
+ /* Firmware calls are only allowed in kernel. */
+ privlvl = (regs->cr_ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT;
+ if (privlvl != 2) {
+ /* FIXME: Return a better error value ?
+ Reflextion ? Illegal operation ? */
+ regs->r8 = -1;
+ return 1;
+ }
+ else
+ return fw_hypercall (regs);
+ } else
+ return xen_hypercall (regs);
+}
diff -r ccb437f2ed4e -r 1dc45879fa5c xen/include/asm-ia64/dom_fw.h
--- a/xen/include/asm-ia64/dom_fw.h Mon Mar 20 16:53:17 2006
+++ b/xen/include/asm-ia64/dom_fw.h Mon Mar 20 16:55:32 2006
@@ -119,6 +119,16 @@
#define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_PADDR
FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX)
#define FW_HYPERCALL_EFI_RESET_SYSTEM_PADDR
FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX)
+/* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above
+ are for the architecture.
+ Note: this limit was defined by Xen/ia64 (and not by Xen).²
+ This can be renumbered safely.
+*/
+#define FW_HYPERCALL_FIRST_ARCH 0x300UL
+
+/* Xen/ia64 user hypercalls. Only used for debugging. */
+#define FW_HYPERCALL_FIRST_USER 0xff00UL
+
extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64);
extern struct sal_ret_values sal_emulator (long index, unsigned long in1,
unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5,
unsigned long in6, unsigned long in7);
extern struct ia64_pal_retval pal_emulator_static (unsigned long);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|