[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [IA64] Check privilege level for pal/sal/efi calls.



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.