direct-io.hg

changeset 9384:1dc45879fa5c

[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@bull.net>
author awilliam@xenbuild.aw
date Mon Mar 20 09:55:32 2006 -0700 (2006-03-20)
parents ccb437f2ed4e
children 9afd25b90af4
files xen/arch/ia64/xen/hypercall.c xen/include/asm-ia64/dom_fw.h
line diff
     1.1 --- a/xen/arch/ia64/xen/hypercall.c	Mon Mar 20 09:53:17 2006 -0700
     1.2 +++ b/xen/arch/ia64/xen/hypercall.c	Mon Mar 20 09:55:32 2006 -0700
     1.3 @@ -66,13 +66,71 @@ hypercall_t ia64_hypercall_table[] =
     1.4  	(hypercall_t)do_ni_hypercall		/*  */
     1.5  	};
     1.6  
     1.7 -int
     1.8 -ia64_hypercall (struct pt_regs *regs)
     1.9 +static int
    1.10 +xen_hypercall (struct pt_regs *regs)
    1.11 +{
    1.12 +	switch (regs->r2) {
    1.13 +	    case __HYPERVISOR_dom0_op:
    1.14 +		regs->r8 = do_dom0_op(guest_handle_from_ptr(regs->r14,
    1.15 +							    dom0_op_t));
    1.16 +		break;
    1.17 +
    1.18 +	    case __HYPERVISOR_memory_op:
    1.19 +		/* we don't handle reservations; just return success */
    1.20 +		{
    1.21 +		    struct xen_memory_reservation reservation;
    1.22 +		    void *arg = (void *) regs->r15;
    1.23 +
    1.24 +		    switch(regs->r14) {
    1.25 +		    case XENMEM_increase_reservation:
    1.26 +		    case XENMEM_decrease_reservation:
    1.27 +			if (copy_from_user(&reservation, arg,
    1.28 +				sizeof(reservation)))
    1.29 +			    regs->r8 = -EFAULT;
    1.30 +			else
    1.31 +			    regs->r8 = reservation.nr_extents;
    1.32 +			break;
    1.33 +		    default:
    1.34 +			regs->r8 = do_memory_op((int) regs->r14, guest_handle_from_ptr(regs->r15, void));
    1.35 +			break;
    1.36 +		    }
    1.37 +		}
    1.38 +		break;
    1.39 +
    1.40 +	    case __HYPERVISOR_event_channel_op:
    1.41 +		regs->r8 = do_event_channel_op(guest_handle_from_ptr(regs->r14, evtchn_op_t));
    1.42 +		break;
    1.43 +
    1.44 +	    case __HYPERVISOR_grant_table_op:
    1.45 +		regs->r8 = do_grant_table_op((unsigned int) regs->r14, guest_handle_from_ptr(regs->r15, void), (unsigned int) regs->r16);
    1.46 +		break;
    1.47 +
    1.48 +	    case __HYPERVISOR_console_io:
    1.49 +		regs->r8 = do_console_io((int) regs->r14, (int) regs->r15, guest_handle_from_ptr(regs->r16, char));
    1.50 +		break;
    1.51 +
    1.52 +	    case __HYPERVISOR_xen_version:
    1.53 +		regs->r8 = do_xen_version((int) regs->r14, guest_handle_from_ptr(regs->r15, void));
    1.54 +		break;
    1.55 +
    1.56 +	    case __HYPERVISOR_multicall:
    1.57 +		regs->r8 = do_multicall(guest_handle_from_ptr(regs->r14, multicall_entry_t), (unsigned int) regs->r15);
    1.58 +		break;
    1.59 +
    1.60 +	    default:
    1.61 +		printf("unknown xen hypercall %lx\n", regs->r2);
    1.62 +		regs->r8 = do_ni_hypercall();
    1.63 +	}
    1.64 +	return 1;
    1.65 +}
    1.66 +
    1.67 +
    1.68 +static int
    1.69 +fw_hypercall (struct pt_regs *regs)
    1.70  {
    1.71  	struct vcpu *v = current;
    1.72  	struct sal_ret_values x;
    1.73  	unsigned long *tv, *tc;
    1.74 -	int pi;
    1.75  
    1.76  	switch (regs->r2) {
    1.77  	    case FW_HYPERCALL_PAL_CALL:
    1.78 @@ -87,6 +145,7 @@ ia64_hypercall (struct pt_regs *regs)
    1.79  		VCPU(v,pending_interruption) = 1;
    1.80  #endif
    1.81  		if (regs->r28 == PAL_HALT_LIGHT) {
    1.82 +			int pi;
    1.83  #define SPURIOUS_VECTOR 15
    1.84  			pi = vcpu_check_pending_interrupts(v);
    1.85  			if (pi != SPURIOUS_VECTOR) {
    1.86 @@ -165,66 +224,50 @@ ia64_hypercall (struct pt_regs *regs)
    1.87  		// FIXME: need fixes in efi.h from 2.6.9
    1.88  		regs->r8 = EFI_UNSUPPORTED;
    1.89  		break;
    1.90 -	    case 0xffff:
    1.91 -		regs->r8 = dump_privop_counts_to_user(
    1.92 -			(char *) vcpu_get_gr(v,32),
    1.93 -			(int) vcpu_get_gr(v,33));
    1.94 -		break;
    1.95 -	    case 0xfffe:
    1.96 -		regs->r8 = zero_privop_counts_to_user(
    1.97 -			(char *) vcpu_get_gr(v,32),
    1.98 -			(int) vcpu_get_gr(v,33));
    1.99 -		break;
   1.100 -	    case __HYPERVISOR_dom0_op:
   1.101 -		regs->r8 = do_dom0_op(guest_handle_from_ptr(regs->r14,
   1.102 -							    dom0_op_t));
   1.103 -		break;
   1.104 -
   1.105 -	    case __HYPERVISOR_memory_op:
   1.106 -		/* we don't handle reservations; just return success */
   1.107 -		{
   1.108 -		    struct xen_memory_reservation reservation;
   1.109 -		    void *arg = (void *) regs->r15;
   1.110 -
   1.111 -		    switch(regs->r14) {
   1.112 -		    case XENMEM_increase_reservation:
   1.113 -		    case XENMEM_decrease_reservation:
   1.114 -			if (copy_from_user(&reservation, arg,
   1.115 -				sizeof(reservation)))
   1.116 -			    regs->r8 = -EFAULT;
   1.117 -			else
   1.118 -			    regs->r8 = reservation.nr_extents;
   1.119 -			break;
   1.120 -		    default:
   1.121 -			regs->r8 = do_memory_op((int) regs->r14, guest_handle_from_ptr(regs->r15, void));
   1.122 -			break;
   1.123 -		    }
   1.124 -		}
   1.125 -		break;
   1.126 -
   1.127 -	    case __HYPERVISOR_event_channel_op:
   1.128 -		regs->r8 = do_event_channel_op(guest_handle_from_ptr(regs->r14, evtchn_op_t));
   1.129 -		break;
   1.130 -
   1.131 -	    case __HYPERVISOR_grant_table_op:
   1.132 -		regs->r8 = do_grant_table_op((unsigned int) regs->r14, guest_handle_from_ptr(regs->r15, void), (unsigned int) regs->r16);
   1.133 -		break;
   1.134 -
   1.135 -	    case __HYPERVISOR_console_io:
   1.136 -		regs->r8 = do_console_io((int) regs->r14, (int) regs->r15, guest_handle_from_ptr(regs->r16, char));
   1.137 -		break;
   1.138 -
   1.139 -	    case __HYPERVISOR_xen_version:
   1.140 -		regs->r8 = do_xen_version((int) regs->r14, guest_handle_from_ptr(regs->r15, void));
   1.141 -		break;
   1.142 -
   1.143 -	    case __HYPERVISOR_multicall:
   1.144 -		regs->r8 = do_multicall(guest_handle_from_ptr(regs->r14, multicall_entry_t), (unsigned int) regs->r15);
   1.145 -		break;
   1.146 -
   1.147  	    default:
   1.148 -		printf("unknown hypercall %lx\n", regs->r2);
   1.149 +		printf("unknown ia64 fw hypercall %lx\n", regs->r2);
   1.150  		regs->r8 = do_ni_hypercall();
   1.151  	}
   1.152  	return 1;
   1.153  }
   1.154 +
   1.155 +int
   1.156 +ia64_hypercall (struct pt_regs *regs)
   1.157 +{
   1.158 +	struct vcpu *v = current;
   1.159 +	unsigned long index = regs->r2;
   1.160 +
   1.161 +	if (index >= FW_HYPERCALL_FIRST_USER) {
   1.162 +	    switch (index) {
   1.163 +		case 0xffff:
   1.164 +			regs->r8 = dump_privop_counts_to_user(
   1.165 +				(char *) vcpu_get_gr(v,32),
   1.166 +				(int) vcpu_get_gr(v,33));
   1.167 +			break;
   1.168 +		case 0xfffe:
   1.169 +			regs->r8 = zero_privop_counts_to_user(
   1.170 +				(char *) vcpu_get_gr(v,32),
   1.171 +				(int) vcpu_get_gr(v,33));
   1.172 +			break;
   1.173 +		default:
   1.174 +			printf("unknown user xen/ia64 hypercall %lx\n", index);
   1.175 +			regs->r8 = do_ni_hypercall();
   1.176 +	    }
   1.177 +	    return 1;
   1.178 +	}
   1.179 +	else if (index >= FW_HYPERCALL_FIRST_ARCH) {
   1.180 +	    int privlvl;
   1.181 +
   1.182 +	    /* Firmware calls are only allowed in kernel.  */
   1.183 +	    privlvl = (regs->cr_ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT;
   1.184 +	    if (privlvl != 2) {
   1.185 +		/* FIXME: Return a better error value ?
   1.186 +		   Reflextion ? Illegal operation ?  */
   1.187 +		regs->r8 = -1;
   1.188 +		return 1;
   1.189 +	    }
   1.190 +	    else
   1.191 +		return fw_hypercall (regs);
   1.192 +	} else
   1.193 +	    return xen_hypercall (regs);
   1.194 +}
     2.1 --- a/xen/include/asm-ia64/dom_fw.h	Mon Mar 20 09:53:17 2006 -0700
     2.2 +++ b/xen/include/asm-ia64/dom_fw.h	Mon Mar 20 09:55:32 2006 -0700
     2.3 @@ -119,6 +119,16 @@ extern unsigned long dom_fw_setup(struct
     2.4  #define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_PADDR	FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX)
     2.5  #define FW_HYPERCALL_EFI_RESET_SYSTEM_PADDR		FW_HYPERCALL_PADDR(FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX)
     2.6  
     2.7 +/* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above
     2.8 +   are for the architecture.
     2.9 +   Note: this limit was defined by Xen/ia64 (and not by Xen).²
    2.10 +     This can be renumbered safely.
    2.11 +*/
    2.12 +#define FW_HYPERCALL_FIRST_ARCH		0x300UL
    2.13 +
    2.14 +/* Xen/ia64 user hypercalls.  Only used for debugging.  */
    2.15 +#define FW_HYPERCALL_FIRST_USER		0xff00UL
    2.16 +
    2.17  extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64);
    2.18  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);
    2.19  extern struct ia64_pal_retval pal_emulator_static (unsigned long);