From: t_jeang Date: Tue, 6 Jan 2009 12:06:04 +0000 (+0000) Subject: Add a RESTRICT ioctl to /dev/xen/evtchn, which allows an event channel X-Git-Tag: CA-13783-ipmi-fixes X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=5b57aaf12331ddaafcc10b23e67519183e5823e5;p=xenclient%2Fkernel.git Add a RESTRICT ioctl to /dev/xen/evtchn, which allows an event channel file descriptor to be restricted to only working with a particular domain. --- diff --git a/drivers/xen/evtchn/evtchn.c b/drivers/xen/evtchn/evtchn.c index 3ebdabb6..7776398b 100644 --- a/drivers/xen/evtchn/evtchn.c +++ b/drivers/xen/evtchn/evtchn.c @@ -66,8 +66,12 @@ struct per_user_data { int bind_cpu; int nr_event_wrong_delivery; + + domid_t restrict_domid; }; +#define UNRESTRICTED_DOMID ((domid_t)-1) + /* Who's bound to each port? */ static struct per_user_data *port_user[NR_EVENT_CHANNELS]; static spinlock_t port_user_lock; @@ -272,6 +276,10 @@ 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; @@ -296,6 +304,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, @@ -312,11 +325,15 @@ 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; - alloc_unbound.dom = DOMID_SELF; + alloc_unbound.dom = DOMID_SELF; alloc_unbound.remote_dom = bind.remote_domain; rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc_unbound); @@ -392,6 +409,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; @@ -439,6 +477,8 @@ static int evtchn_open(struct inode *inode, struct file *filp) mutex_init(&u->ring_cons_mutex); + u->restrict_domid = UNRESTRICTED_DOMID; + filp->private_data = u; u->bind_cpu = -1; diff --git a/include/xen/public/evtchn.h b/include/xen/public/evtchn.h index 938d4da2..e5730fd3 100644 --- a/include/xen/public/evtchn.h +++ b/include/xen/public/evtchn.h @@ -85,4 +85,17 @@ struct ioctl_evtchn_notify { #define IOCTL_EVTCHN_RESET \ _IOC(_IOC_NONE, 'E', 5, 0) +/* Restruct this file descriptor so that it can only be applied to a + * nominated domain. Once a file descriptor has been restricted it + * cannot be de-restricted, and must be closed and re-openned. Event + * channels which were bound before restricting remain bound + * afterwards, and can be notified as usual. + */ +#define IOCTL_EVTCHN_RESTRICT_DOMID \ + _IOC(_IOC_NONE, 'E', 6, sizeof(struct ioctl_evtchn_restrict_domid)) +struct ioctl_evtchn_restrict_domid { + domid_t domid; +}; + + #endif /* __LINUX_PUBLIC_EVTCHN_H__ */