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

[Xen-devel] [PATCH 09/11] xen: Add DOMCTL to limit the number of event channels a domain may use



From: David Vrabel <dvrabel@xxxxxxxxxx>

Add XEN_DOMCTL_set_max_evtchn which may be used during domain creation to
set the maximum event channel port a domain may use.  This may be used to
limit the amount of Xen resources (global mapping space and xenheap) that
a domain may use for event channels.

A domain that does not have a limit set may use all the event channels
supported by the event channel ABI in use.

Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
Cc: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
---
 tools/flask/policy/policy/mls                |    2 +-
 tools/flask/policy/policy/modules/xen/xen.if |    2 +-
 tools/flask/policy/policy/modules/xen/xen.te |    2 +-
 xen/common/domctl.c                          |    8 ++++++++
 xen/common/event_channel.c                   |    7 ++++++-
 xen/include/public/domctl.h                  |   15 ++++++++++++++-
 xen/include/xen/sched.h                      |    1 +
 xen/xsm/flask/hooks.c                        |    3 +++
 xen/xsm/flask/policy/access_vectors          |    2 ++
 9 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/tools/flask/policy/policy/mls b/tools/flask/policy/policy/mls
index 9290a76..fb603cd 100644
--- a/tools/flask/policy/policy/mls
+++ b/tools/flask/policy/policy/mls
@@ -74,7 +74,7 @@ mlsconstrain domain { getaffinity getdomaininfo getvcpuinfo 
getvcpucontext getad
        ((l1 dom l2) or (t1 == mls_priv));
 
 # all the domain "write" ops
-mlsconstrain domain { setvcpucontext pause unpause resume create max_vcpus 
destroy setaffinity scheduler setdomainmaxmem setdomainhandle setdebugging 
hypercall settime set_target shutdown setaddrsize trigger setextvcpucontext }
+mlsconstrain domain { setvcpucontext pause unpause resume create max_vcpus 
destroy setaffinity scheduler setdomainmaxmem setdomainhandle setdebugging 
hypercall settime set_target shutdown setaddrsize trigger setextvcpucontext 
set_max_evtchn }
        ((l1 eq l2) or (t1 == mls_priv));
 
 # This is incomplete - similar constraints must be written for all classes
diff --git a/tools/flask/policy/policy/modules/xen/xen.if 
b/tools/flask/policy/policy/modules/xen/xen.if
index 97af0a8..63e40f0 100644
--- a/tools/flask/policy/policy/modules/xen/xen.if
+++ b/tools/flask/policy/policy/modules/xen/xen.if
@@ -48,7 +48,7 @@ define(`create_domain_common', `
        allow $1 $2:domain { create max_vcpus setdomainmaxmem setaddrsize
                        getdomaininfo hypercall setvcpucontext setextvcpucontext
                        getscheduler getvcpuinfo getvcpuextstate getaddrsize
-                       getaffinity setaffinity };
+                       getaffinity setaffinity set_max_evtchn };
        allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim };
        allow $1 $2:security check_context;
        allow $1 $2:shadow enable;
diff --git a/tools/flask/policy/policy/modules/xen/xen.te 
b/tools/flask/policy/policy/modules/xen/xen.te
index c89ce28..5f9de5c 100644
--- a/tools/flask/policy/policy/modules/xen/xen.te
+++ b/tools/flask/policy/policy/modules/xen/xen.te
@@ -73,7 +73,7 @@ allow dom0_t dom0_t:domain {
        getdomaininfo getvcpuinfo getvcpucontext setdomainmaxmem setdomainhandle
        setdebugging hypercall settime setaddrsize getaddrsize trigger
        getextvcpucontext setextvcpucontext getvcpuextstate setvcpuextstate
-       getpodtarget setpodtarget set_misc_info set_virq_handler
+       getpodtarget setpodtarget set_misc_info set_virq_handler set_max_evtchn
 };
 allow dom0_t dom0_t:domain2 {
        set_cpuid gettsc settsc setscheduler
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 9760d50..bffe8d8 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -863,6 +863,14 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) 
u_domctl)
     }
     break;
 
+    case XEN_DOMCTL_set_max_evtchn:
+    {
+        d->max_evtchn_port = min_t(unsigned,
+                                   op->u.set_max_evtchn.max_port,
+                                   INT_MAX);
+    }
+    break;
+
     default:
         ret = arch_do_domctl(op, d, u_domctl);
         break;
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 2c90a66..8e430e2 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -168,10 +168,14 @@ static int get_free_port(struct domain *d)
         return -EINVAL;
 
     for ( port = 0; port_is_valid(d, port); port++ )
+    {
+        if ( port > d->max_evtchn_port )
+            return -ENOSPC;
         if ( evtchn_from_port(d, port)->state == ECS_FREE )
             return port;
+    }
 
-    if ( port == d->max_evtchns )
+    if ( port == d->max_evtchns || port > d->max_evtchn_port )
         return -ENOSPC;
 
     if ( !group_from_port(d, port) )
@@ -1230,6 +1234,7 @@ void evtchn_check_pollers(struct domain *d, unsigned port)
 int evtchn_init(struct domain *d)
 {
     evtchn_2l_init(d);
+    d->max_evtchn_port = INT_MAX;
 
     d->evtchn = alloc_evtchn_bucket(d, 0);
     if ( !d->evtchn )
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 4c5b2bb..ed9155a 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -36,7 +36,7 @@
 #include "grant_table.h"
 #include "hvm/save.h"
 
-#define XEN_DOMCTL_INTERFACE_VERSION 0x00000009
+#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000a
 
 /*
  * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
@@ -852,6 +852,17 @@ struct xen_domctl_set_broken_page_p2m {
 typedef struct xen_domctl_set_broken_page_p2m xen_domctl_set_broken_page_p2m_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_broken_page_p2m_t);
 
+/*
+ * XEN_DOMCTL_set_max_evtchn: sets the maximum event channel port
+ * number the guest may use.  Use this limit the amount of resources
+ * (global mapping space, xenheap) a guest may use for event channels.
+ */
+struct xen_domctl_set_max_evtchn {
+    uint32_t max_port;
+};
+typedef struct xen_domctl_set_max_evtchn xen_domctl_set_max_evtchn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_max_evtchn_t);
+
 struct xen_domctl {
     uint32_t cmd;
 #define XEN_DOMCTL_createdomain                   1
@@ -920,6 +931,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_set_broken_page_p2m           67
 #define XEN_DOMCTL_setnodeaffinity               68
 #define XEN_DOMCTL_getnodeaffinity               69
+#define XEN_DOMCTL_set_max_evtchn                70
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -975,6 +987,7 @@ struct xen_domctl {
         struct xen_domctl_set_access_required access_required;
         struct xen_domctl_audit_p2m         audit_p2m;
         struct xen_domctl_set_virq_handler  set_virq_handler;
+        struct xen_domctl_set_max_evtchn    set_max_evtchn;
         struct xen_domctl_gdbsx_memio       gdbsx_guest_memio;
         struct xen_domctl_set_broken_page_p2m set_broken_page_p2m;
         struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index ae653e6..bca381c 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -291,6 +291,7 @@ struct domain
     struct evtchn   *evtchn;                         /* first bucket only */
     struct evtchn  **evtchn_group[NR_EVTCHN_GROUPS]; /* all other buckets */
     unsigned         max_evtchns;
+    unsigned         max_evtchn_port;
     spinlock_t       event_lock;
     const struct evtchn_port_ops *evtchn_port_ops;
     struct evtchn_fifo_domain *evtchn_fifo;
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index fa0589a..548df47 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -727,6 +727,9 @@ static int flask_domctl(struct domain *d, int cmd)
     case XEN_DOMCTL_audit_p2m:
         return current_has_perm(d, SECCLASS_HVM, HVM__AUDIT_P2M);
 
+    case XEN_DOMCTL_set_max_evtchn:
+        return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SET_MAX_EVTCHN);
+
     default:
         printk("flask_domctl: Unknown op %d\n", cmd);
         return -EPERM;
diff --git a/xen/xsm/flask/policy/access_vectors 
b/xen/xsm/flask/policy/access_vectors
index 5dfe13b..03a8e64 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -157,6 +157,8 @@ class domain
     set_misc_info
 # XEN_DOMCTL_set_virq_handler
     set_virq_handler
+# XEN_DOMCTL_set_max_evtchn
+    set_max_evtchn
 }
 
 # This is a continuation of class domain, since only 32 permissions can be
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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