|
@@ -73,8 +73,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,6 +447,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;
|
|
@@ -468,6 +476,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 +498,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 +570,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 +639,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);
|