X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=drivers%2Fxen%2Fevtchn.c;h=e8c7f09d01be8a483df94db111faec580beb032a;hb=aeb35d6b74174ed08daab84e232b456bbd89d1d9;hp=f4edd6df3df235c55aef1329cb8e17b5ae8cf9f7;hpb=1cbe06c3cf542d48eb22180163e00f91760ef8cd;p=deliverable%2Flinux.git diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index f4edd6df3df2..e8c7f09d01be 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -55,6 +55,7 @@ #include #include #include +#include #include struct per_user_data { @@ -73,8 +74,12 @@ struct per_user_data { wait_queue_head_t evtchn_wait; struct fasync_struct *evtchn_async_queue; const char *name; + + domid_t restrict_domid; }; +#define UNRESTRICTED_DOMID ((domid_t)-1) + struct user_evtchn { struct rb_node node; struct per_user_data *user; @@ -443,12 +448,16 @@ static long evtchn_ioctl(struct file *file, struct ioctl_evtchn_bind_virq bind; struct evtchn_bind_virq bind_virq; + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID) + break; + rc = -EFAULT; if (copy_from_user(&bind, uarg, sizeof(bind))) break; bind_virq.virq = bind.virq; - bind_virq.vcpu = 0; + bind_virq.vcpu = xen_vcpu_nr(0); rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq); if (rc != 0) @@ -468,6 +477,11 @@ static long evtchn_ioctl(struct file *file, if (copy_from_user(&bind, uarg, sizeof(bind))) break; + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID && + u->restrict_domid != bind.remote_domain) + break; + bind_interdomain.remote_dom = bind.remote_domain; bind_interdomain.remote_port = bind.remote_port; rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, @@ -485,6 +499,10 @@ static long evtchn_ioctl(struct file *file, struct ioctl_evtchn_bind_unbound_port bind; struct evtchn_alloc_unbound alloc_unbound; + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID) + break; + rc = -EFAULT; if (copy_from_user(&bind, uarg, sizeof(bind))) break; @@ -553,6 +571,27 @@ static long evtchn_ioctl(struct file *file, break; } + case IOCTL_EVTCHN_RESTRICT_DOMID: { + struct ioctl_evtchn_restrict_domid ierd; + + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID) + break; + + rc = -EFAULT; + if (copy_from_user(&ierd, uarg, sizeof(ierd))) + break; + + rc = -EINVAL; + if (ierd.domid == 0 || ierd.domid >= DOMID_FIRST_RESERVED) + break; + + u->restrict_domid = ierd.domid; + rc = 0; + + break; + } + default: rc = -ENOSYS; break; @@ -601,6 +640,8 @@ static int evtchn_open(struct inode *inode, struct file *filp) mutex_init(&u->ring_cons_mutex); spin_lock_init(&u->ring_prod_lock); + u->restrict_domid = UNRESTRICTED_DOMID; + filp->private_data = u; return nonseekable_open(inode, filp);