All of lore.kernel.org
 help / color / mirror / Atom feed
From: Samuel Thibault <samuel.thibault@eu.citrix.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH] New XEN_DOMCTL_set_target and IS_PRIV_FOR
Date: Wed, 23 Jan 2008 11:55:29 +0000	[thread overview]
Message-ID: <20080123115529.GA5188@implementation.uk.xensource.com> (raw)

New XEN_DOMCTL_set_target
Stubdomains (and probably other domain disagregation elements too) need
to be able to tinker with another domain.  This adds IS_PRIV_FOR that
extends IS_PRIV by allowing domains to have privileges over a given
"target" domain.  XEN_DOMCTL_set_target permits to set this "target".  A
new 'target' configuration option makes the domain builder use it.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>

diff -r bcae9d2cc2f8 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/tools/libxc/xc_domain.c	Wed Jan 23 11:36:15 2008 +0000
@@ -875,6 +875,20 @@
     return do_domctl(xc_handle, &domctl);
 }
 
+int xc_domain_set_target(
+    int xc_handle,
+    uint32_t domid,
+    uint32_t target)
+{
+    DECLARE_DOMCTL;
+
+    domctl.cmd = XEN_DOMCTL_set_target;
+    domctl.domain = domid;
+    domctl.u.set_target.target = target;
+
+    return do_domctl(xc_handle, &domctl);
+}
+
 /*
  * Local variables:
  * mode: C
--- a/tools/libxc/xenctrl.h	Wed Jan 23 11:21:35 2008 +0000
+++ b/tools/libxc/xenctrl.h	Wed Jan 23 11:36:15 2008 +0000
@@ -952,4 +952,9 @@
                               uint32_t domid,
                               uint8_t machine_irq);
 
+/* Set the target domain */
+int xc_domain_set_target(int xc_handle,
+                         uint32_t domid,
+                         uint32_t target);
+
 #endif /* XENCTRL_H */
--- a/tools/python/xen/lowlevel/xc/xc.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/tools/python/xen/lowlevel/xc/xc.c	Wed Jan 23 11:36:15 2008 +0000
@@ -96,17 +96,17 @@
                                     PyObject *args,
                                     PyObject *kwds)
 {
-    uint32_t dom = 0, ssidref = 0, flags = 0;
+    uint32_t dom = 0, ssidref = 0, flags = 0, target = 0;
     int      ret, i, hvm = 0;
     PyObject *pyhandle = NULL;
     xen_domain_handle_t handle = { 
         0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
         0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef };
 
-    static char *kwd_list[] = { "domid", "ssidref", "handle", "hvm", NULL };
+    static char *kwd_list[] = { "domid", "ssidref", "handle", "hvm", "target", NULL };
 
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiOi", kwd_list,
-                                      &dom, &ssidref, &pyhandle, &hvm))
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiOii", kwd_list,
+				      &dom, &ssidref, &pyhandle, &hvm, &target))
         return NULL;
 
     if ( pyhandle != NULL )
@@ -130,6 +130,11 @@
     if ( (ret = xc_domain_create(self->xc_handle, ssidref,
                                  handle, flags, &dom)) < 0 )
         return pyxc_error_to_exception();
+
+    if ( target )
+        if ( (ret = xc_domain_set_target(self->xc_handle, dom, target)) < 0 )
+            return pyxc_error_to_exception();
+
 
     return PyInt_FromLong(dom);
 
--- a/tools/python/xen/xend/XendConfig.py	Wed Jan 23 11:21:35 2008 +0000
+++ b/tools/python/xen/xend/XendConfig.py	Wed Jan 23 11:36:15 2008 +0000
@@ -170,6 +170,7 @@
     'platform': dict,
     'tools_version': dict,
     'other_config': dict,
+    'target': int,
     'security_label': str,
     'pci': str,
 }
@@ -336,7 +337,8 @@
             'vbd_refs': [],
             'vtpm_refs': [],
             'other_config': {},
-            'platform': {}
+            'platform': {},
+            'target': 0,
         }
         
         return defaults
@@ -1585,6 +1587,9 @@
     def is_hvm(self):
         return self['HVM_boot_policy'] != ''
 
+    def target(self):
+	return self['target']
+
     def image_type(self):
         stored_type = self['platform'].get('image_type')
         return stored_type or (self.is_hvm() and 'hvm' or 'linux')
--- a/tools/python/xen/xend/XendDomainInfo.py	Wed Jan 23 11:21:35 2008 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py	Wed Jan 23 11:36:15 2008 +0000
@@ -1640,7 +1640,8 @@
                 domid = 0,
                 ssidref = ssidref,
                 handle = uuid.fromString(self.info['uuid']),
-                hvm = int(hvm))
+                hvm = int(hvm),
+                target = self.info.target())
         except Exception, e:
             # may get here if due to ACM the operation is not permitted
             if security.on():
--- a/tools/python/xen/xm/create.py	Wed Jan 23 11:21:35 2008 +0000
+++ b/tools/python/xen/xm/create.py	Wed Jan 23 11:36:15 2008 +0000
@@ -521,6 +521,10 @@
           - suspend:        Domain is suspended;
           """)
 
+gopts.var('target', val='TARGET',
+          fn=set_int, default=0,
+          use="Set domain target.")
+
 def err(msg):
     """Print an error to stderr and exit.
     """
@@ -748,7 +752,7 @@
     map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
                    'restart', 'on_poweroff',
                    'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
-                   'on_xend_start', 'on_xend_stop'])
+                   'on_xend_start', 'on_xend_stop', 'target'])
 
     if vals.uuid is not None:
         config.append(['uuid', vals.uuid])
--- a/xen/arch/ia64/vmx/vmx_hypercall.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c	Wed Jan 23 11:36:15 2008 +0000
@@ -47,15 +47,16 @@
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( op.isa_irq > 15 )
         return -EINVAL;
 
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
+
+    rc = -EPERM;
+    if ( !IS_PRIV_FOR(current->domain, d) )
+        goto out;
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
@@ -79,15 +80,16 @@
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) )
         return -EINVAL;
 
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
+
+    rc = -EPERM;
+    if ( !IS_PRIV_FOR(current->domain, d) )
+        goto out;
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
@@ -124,13 +126,15 @@
         if (a.domid == DOMID_SELF) {
             d = rcu_lock_current_domain();
         }
-        else if (IS_PRIV(current->domain)) {
+        else {
             d = rcu_lock_domain_by_id(a.domid);
             if (d == NULL)
                 return -ESRCH;
+            if (!IS_PRIV_FOR(current->domain, d)) {
+                rcu_unlock_domain(d);
+                return -EPERM;
+            }
         }
-        else
-            return -EPERM;
 
         if (op == HVMOP_set_param) {
             struct vmx_ioreq_page *iorp;
--- a/xen/arch/ia64/xen/dom0_ops.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/ia64/xen/dom0_ops.c	Wed Jan 23 11:36:15 2008 +0000
@@ -37,9 +37,6 @@
 {
     long ret = 0;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     switch ( op->cmd )
     {
     case XEN_DOMCTL_getmemlist:
@@ -54,6 +51,13 @@
             ret = -EINVAL;
             break;
         }
+
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            ret = -EPERM;
+            rcu_unlock_domain(d);
+            break;
+        }
+
         for (i = 0 ; i < nr_pages ; i++) {
             pte_t *pte;
 
@@ -84,6 +88,12 @@
 
         if ( d == NULL) {
             ret = -EINVAL;
+            break;
+        }
+
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            ret = -EPERM;
+            rcu_unlock_domain(d);
             break;
         }
 
@@ -153,6 +163,12 @@
         d = rcu_lock_domain_by_id(op->domain);
         if ( d != NULL )
         {
+            if ( !IS_PRIV_FOR(current->domain, d) ) {
+                ret = -EPERM;
+                rcu_unlock_domain(d);
+                break;
+            }
+
             ret = shadow_mode_control(d, &op->u.shadow_op);
             rcu_unlock_domain(d);
             if (copy_to_guest(u_domctl, op, 1))
@@ -172,6 +188,12 @@
         d = rcu_lock_domain_by_id(op->domain);
         if (unlikely(d == NULL))
             break;
+
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            ret = -EPERM;
+            rcu_unlock_domain(d);
+            break;
+        }
 
         if (np == 0)
             ret = 0;
@@ -195,6 +217,11 @@
         d = rcu_lock_domain_by_id(op->domain);
         if ( d == NULL )
             break;
+
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            goto sendtrigger_out;
+        }
 
         ret = -EINVAL;
         if ( op->u.sendtrigger.vcpu >= MAX_VIRT_CPUS )
@@ -239,6 +266,10 @@
         if (d == NULL)
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto sethvmcontext_out;
+
 #ifdef CONFIG_X86
         ret = xsm_hvmcontext(d, op->cmd);
         if (ret)
@@ -279,6 +310,10 @@
         d = rcu_lock_domain_by_id(op->domain);
         if (d == NULL)
             break;
+
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto gethvmcontext_out;
 
 #ifdef CONFIG_X86
         ret = xsm_hvmcontext(d, op->cmd);
@@ -341,7 +376,10 @@
             break;
         }
 
-        ret = domain_opt_feature(d, optf);
+        ret = -EPERM;
+        if ( IS_PRIV_FOR(current->domain, d) )
+            ret = domain_opt_feature(d, optf);
+
         rcu_unlock_domain(d);
     }
     break;
--- a/xen/arch/ia64/xen/hypercall.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/ia64/xen/hypercall.c	Wed Jan 23 11:36:15 2008 +0000
@@ -500,13 +500,15 @@
     struct domain *d;
     long ret = 0;
 
-    if (!IS_PRIV(current->domain))
-        return -EPERM;
     if (copy_from_guest(op, u_debug_op, 1))
         return -EFAULT;
     d = rcu_lock_domain_by_id(domain);
     if (d == NULL)
         return -ESRCH;
+    if (!IS_PRIV_FOR(current->domain, d)) {
+        ret = -EPERM;
+        goto out;
+    }
 
     switch (cmd) {
     case XEN_IA64_DEBUG_OP_SET_FLAGS:
@@ -520,6 +522,7 @@
     default:
         ret = -ENOSYS;
     }
+out:
     rcu_unlock_domain(d);
     return ret;
 }
--- a/xen/arch/ia64/xen/mm.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/ia64/xen/mm.c	Wed Jan 23 11:36:15 2008 +0000
@@ -2787,10 +2787,14 @@
 
         if (xatp.domid == DOMID_SELF)
             d = rcu_lock_current_domain();
-        else if (!IS_PRIV(current->domain))
-            return -EPERM;
-        else if ((d = rcu_lock_domain_by_id(xatp.domid)) == NULL)
-            return -ESRCH;
+        else {
+            if ((d = rcu_lock_domain_by_id(xatp.domid)) == NULL)
+                return -ESRCH;
+            if (!IS_PRIV_FOR(current->domain,d)) {
+                rcu_lock_domain(d);
+                return -EPERM;
+            }
+        }
 
         /* This hypercall is used for VT-i domain only */
         if (!VMX_DOMAIN(d->vcpu[0])) {
--- a/xen/arch/ia64/xen/xensetup.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/ia64/xen/xensetup.c	Wed Jan 23 11:36:15 2008 +0000
@@ -642,6 +642,7 @@
         panic("Cannot allocate dom0 vcpu 0\n");
 
     dom0->is_privileged = 1;
+    dom0->target = NULL;
 
     /*
      * We're going to setup domain0 using the module(s) that we stashed safely
--- a/xen/arch/powerpc/setup.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/powerpc/setup.c	Wed Jan 23 11:36:15 2008 +0000
@@ -375,6 +375,7 @@
     dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
 
     dom0->is_privileged = 1;
+    dom0->target = NULL;
 
     /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
     local_irq_enable();
--- a/xen/arch/x86/hvm/hvm.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/x86/hvm/hvm.c	Wed Jan 23 11:36:15 2008 +0000
@@ -1740,15 +1740,16 @@
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) )
         return -EINVAL;
 
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
+
+    rc = -EPERM;
+    if ( !IS_PRIV_FOR(current->domain, d) )
+        goto out;
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
@@ -1787,15 +1788,16 @@
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( op.isa_irq > 15 )
         return -EINVAL;
 
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
+
+    rc = -EPERM;
+    if ( !IS_PRIV_FOR(current->domain, d) )
+        goto out;
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
@@ -1834,15 +1836,16 @@
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( (op.link > 3) || (op.isa_irq > 15) )
         return -EINVAL;
 
     d = rcu_lock_domain_by_id(op.domid);
     if ( d == NULL )
         return -ESRCH;
+
+    rc = -EPERM;
+    if ( !IS_PRIV_FOR(current->domain, d) )
+        goto out;
 
     rc = -EINVAL;
     if ( !is_hvm_domain(d) )
@@ -1921,13 +1924,16 @@
 
         if ( a.domid == DOMID_SELF )
             d = rcu_lock_current_domain();
-        else if ( IS_PRIV(current->domain) )
+        else {
             d = rcu_lock_domain_by_id(a.domid);
-        else
-            return -EPERM;
+            if ( d == NULL )
+                return -ESRCH;
+            if ( !IS_PRIV_FOR(current->domain, d) ) {
+                rc = -EPERM;
+                goto param_fail;
+            }
+        }
 
-        if ( d == NULL )
-            return -ESRCH;
 
         rc = -EINVAL;
         if ( !is_hvm_domain(d) )
--- a/xen/arch/x86/mm.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/x86/mm.c	Wed Jan 23 11:36:15 2008 +0000
@@ -2056,38 +2056,35 @@
         MEM_LOG("Cannot mix foreign mappings with translated domains");
         okay = 0;
     }
-    else if ( !IS_PRIV(d) )
+    else switch ( domid )
     {
-        switch ( domid )
-        {
-        case DOMID_IO:
-            info->foreign = rcu_lock_domain(dom_io);
-            break;
-        default:
+    case DOMID_IO:
+        info->foreign = rcu_lock_domain(dom_io);
+        break;
+    case DOMID_XEN:
+        if (!IS_PRIV(d)) {
             MEM_LOG("Cannot set foreign dom");
             okay = 0;
             break;
         }
-    }
-    else
-    {
-        info->foreign = e = rcu_lock_domain_by_id(domid);
+        info->foreign = rcu_lock_domain(dom_xen);
+        break;
+    default:
+        e = rcu_lock_domain_by_id(domid);
         if ( e == NULL )
         {
-            switch ( domid )
-            {
-            case DOMID_XEN:
-                info->foreign = rcu_lock_domain(dom_xen);
-                break;
-            case DOMID_IO:
-                info->foreign = rcu_lock_domain(dom_io);
-                break;
-            default:
-                MEM_LOG("Unknown domain '%u'", domid);
-                okay = 0;
-                break;
-            }
+            MEM_LOG("Unknown domain '%u'", domid);
+            okay = 0;
+            break;
         }
+        if (!IS_PRIV_FOR(d, e)) {
+            MEM_LOG("Cannot set foreign dom");
+            okay = 0;
+            rcu_unlock_domain(e);
+            break;
+        }
+        info->foreign = e;
+        break;
     }
 
  out:
@@ -3043,9 +3040,6 @@
 {
     int rc;
 
-    if ( unlikely(!IS_PRIV(current->domain)) )
-        return -EPERM;
-
     if ( !set_foreigndom(domid) )
         return -ESRCH;
 
@@ -3222,10 +3216,15 @@
 
         if ( xatp.domid == DOMID_SELF )
             d = rcu_lock_current_domain();
-        else if ( !IS_PRIV(current->domain) )
-            return -EPERM;
-        else if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
-            return -ESRCH;
+        else {
+            d = rcu_lock_domain_by_id(xatp.domid);
+            if ( d == NULL )
+                return -ESRCH;
+            if ( !IS_PRIV_FOR(current->domain, d) ) {
+                rcu_unlock_domain(d);
+                return -EPERM;
+            }
+        }
 
         if ( xsm_add_to_physmap(current->domain, d) )
         {
@@ -3313,10 +3312,15 @@
 
         if ( fmap.domid == DOMID_SELF )
             d = rcu_lock_current_domain();
-        else if ( !IS_PRIV(current->domain) )
-            return -EPERM;
-        else if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
-            return -ESRCH;
+        else {
+            d = rcu_lock_domain_by_id(fmap.domid);
+            if ( d == NULL )
+                return -ESRCH;
+            if ( !IS_PRIV_FOR(current->domain, d) ) {
+                rcu_unlock_domain(d);
+                return -EPERM;
+            }
+        }
 
         rc = xsm_domain_memory_map(d);
         if ( rc )
--- a/xen/arch/x86/mm/shadow/multi.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c	Wed Jan 23 11:36:15 2008 +0000
@@ -993,11 +993,11 @@
     // not own, we let it succeed anyway.
     //
     if ( unlikely(!res) &&
-         IS_PRIV(d) &&
          !shadow_mode_translate(d) &&
          mfn_valid(mfn = shadow_l1e_get_mfn(sl1e)) &&
          (owner = page_get_owner(mfn_to_page(mfn))) &&
-         (d != owner) )
+         (d != owner) &&
+         IS_PRIV_FOR(d, owner))
     {
         res = get_page_from_l1e(sl1e, owner);
         SHADOW_PRINTK("privileged domain %d installs map of mfn %05lx "
--- a/xen/arch/x86/setup.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/arch/x86/setup.c	Wed Jan 23 11:36:15 2008 +0000
@@ -959,6 +959,7 @@
         panic("Error creating domain 0\n");
 
     dom0->is_privileged = 1;
+    dom0->target = NULL;
 
     /* Grab the DOM0 command line. */
     cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
--- a/xen/common/domain.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/common/domain.c	Wed Jan 23 11:36:15 2008 +0000
@@ -502,6 +502,9 @@
         if ( (v = d->vcpu[i]) != NULL )
             free_vcpu_struct(v);
 
+    if (d->target)
+        put_domain(d->target);
+
     free_domain(d);
 
     send_guest_global_virq(dom0, VIRQ_DOM_EXC);
--- a/xen/common/domctl.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/common/domctl.c	Wed Jan 23 11:36:15 2008 +0000
@@ -182,9 +182,6 @@
     struct xen_domctl curop, *op = &curop;
     static DEFINE_SPINLOCK(domctl_lock);
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( copy_from_guest(op, u_domctl, 1) )
         return -EFAULT;
 
@@ -206,6 +203,10 @@
         ret = -ESRCH;
         if ( d == NULL )
             break;
+
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto svc_out;
 
         ret = xsm_setvcpucontext(d);
         if ( ret )
@@ -258,6 +259,10 @@
         ret = -ESRCH;
         if ( d != NULL )
         {
+            ret = -EPERM;
+            if ( !IS_PRIV_FOR(current->domain, d) )
+                goto pausedomain_out;
+
             ret = xsm_pausedomain(d);
             if ( ret )
                 goto pausedomain_out;
@@ -282,16 +287,18 @@
         if ( d == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto unpausedomain_out;
+
         ret = xsm_unpausedomain(d);
         if ( ret )
-        {
-            rcu_unlock_domain(d);
-            break;
-        }
+            goto unpausedomain_out;
 
         domain_unpause_by_systemcontroller(d);
+        ret = 0;
+unpausedomain_out:
         rcu_unlock_domain(d);
-        ret = 0;
     }
     break;
 
@@ -303,16 +310,18 @@
         if ( d == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto resumedomain_out;
+
         ret = xsm_resumedomain(d);
         if ( ret )
-        {
-            rcu_unlock_domain(d);
-            break;
-        }
+            goto resumedomain_out;
 
         domain_resume(d);
+        ret = 0;
+resumedomain_out:
         rcu_unlock_domain(d);
-        ret = 0;
     }
     break;
 
@@ -322,6 +331,10 @@
         domid_t        dom;
         static domid_t rover = 0;
         unsigned int domcr_flags;
+
+        ret = -EPERM;
+        if ( !IS_PRIV(current->domain) )
+            break;
 
         ret = -EINVAL;
         if ( supervisor_mode_kernel ||
@@ -385,12 +398,13 @@
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto maxvcpu_out2;
+
         ret = xsm_max_vcpus(d);
         if ( ret )
-        {
-            rcu_unlock_domain(d);
-            break;
-        }
+            goto maxvcpu_out2;
 
         /* Needed, for example, to ensure writable p.t. state is synced. */
         domain_pause(d);
@@ -418,6 +432,7 @@
 
     maxvcpu_out:
         domain_unpause(d);
+    maxvcpu_out2:
         rcu_unlock_domain(d);
     }
     break;
@@ -428,7 +443,9 @@
         ret = -ESRCH;
         if ( d != NULL )
         {
-            ret = xsm_destroydomain(d) ? : domain_kill(d);
+            ret = -EPERM;
+            if ( IS_PRIV_FOR(current->domain, d) )
+                ret = xsm_destroydomain(d) ? : domain_kill(d);
             rcu_unlock_domain(d);
         }
     }
@@ -445,6 +462,10 @@
         ret = -ESRCH;
         if ( d == NULL )
             break;
+
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto vcpuaffinity_out;
 
         ret = xsm_vcpuaffinity(op->cmd, d);
         if ( ret )
@@ -484,6 +505,10 @@
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto scheduler_op_out;
+
         ret = xsm_scheduler(d);
         if ( ret )
             goto scheduler_op_out;
@@ -505,7 +530,7 @@
         rcu_read_lock(&domlist_read_lock);
 
         for_each_domain ( d )
-            if ( d->domain_id >= dom )
+            if ( d->domain_id >= dom && IS_PRIV_FOR(current->domain, d))
                 break;
 
         if ( d == NULL )
@@ -539,6 +564,10 @@
         ret = -ESRCH;
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
+
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto getvcpucontext_out;
 
         ret = xsm_getvcpucontext(d);
         if ( ret )
@@ -600,6 +629,10 @@
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto getvcpuinfo_out;
+
         ret = xsm_getvcpuinfo(d);
         if ( ret )
             goto getvcpuinfo_out;
@@ -639,6 +672,10 @@
         if ( d == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto max_mem_out;
+
         ret = xsm_setdomainmaxmem(d);
         if ( ret )
             goto max_mem_out;
@@ -655,6 +692,8 @@
             d->max_pages = new_max;
             ret = 0;
         }
+        else
+            printk("new max %ld, tot pages %d\n", new_max, d->tot_pages);
         spin_unlock(&d->page_alloc_lock);
 
     max_mem_out:
@@ -671,17 +710,19 @@
         if ( d == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto setdomainhandle_out;
+
         ret = xsm_setdomainhandle(d);
         if ( ret )
-        {
-            rcu_unlock_domain(d);
-            break;
-        }
+            goto setdomainhandle_out;
 
         memcpy(d->handle, op->u.setdomainhandle.handle,
                sizeof(xen_domain_handle_t));
+        ret = 0;
+setdomainhandle_out:
         rcu_unlock_domain(d);
-        ret = 0;
     }
     break;
 
@@ -694,18 +735,20 @@
         if ( d == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto setdebugging_out;
+
         ret = xsm_setdebugging(d);
         if ( ret )
-        {
-            rcu_unlock_domain(d);
-            break;
-        }
+            goto setdebugging_out;
 
         domain_pause(d);
         d->debugger_attached = !!op->u.setdebugging.enable;
         domain_unpause(d); /* causes guest to latch new status */
+        ret = 0;
+setdebugging_out:
         rcu_unlock_domain(d);
-        ret = 0;
     }
     break;
 
@@ -722,6 +765,10 @@
         d = rcu_lock_domain_by_id(op->domain);
         if ( d == NULL )
             break;
+
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto irq_permission_out;
 
         ret = xsm_irq_permission(d, pirq, op->u.irq_permission.allow_access);
         if ( ret )
@@ -752,6 +799,10 @@
         if ( d == NULL )
             break;
 
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto iomem_permission_out;
+
         ret = xsm_iomem_permission(d, mfn, op->u.iomem_permission.allow_access);
         if ( ret )
             goto iomem_permission_out;
@@ -772,19 +823,61 @@
 
         ret = -ESRCH;
         d = rcu_lock_domain_by_id(op->domain);
-        if ( d != NULL )
-        {
-            ret = xsm_domain_settime(d);
-            if ( ret )
-            {
-                rcu_unlock_domain(d);
-                break;
-            }
+        if ( d == NULL )
+            break;
 
-            d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
-            rcu_unlock_domain(d);
-            ret = 0;
+        ret = -EPERM;
+        if ( !IS_PRIV_FOR(current->domain, d) )
+            goto settimeoffset_out;
+
+        ret = xsm_domain_settime(d);
+        if ( ret )
+            goto settimeoffset_out;
+
+        d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
+
+        ret = 0;
+settimeoffset_out:
+        rcu_unlock_domain(d);
+    }
+    break;
+
+    case XEN_DOMCTL_set_target:
+    {
+        struct domain *d, *e;
+
+        ret = -ESRCH;
+        d = rcu_lock_domain_by_id(op->domain);
+        if ( d == NULL )
+            break;
+
+        ret = -EPERM;
+        if (!IS_PRIV_FOR(current->domain, d))
+            goto set_target_out;
+
+        ret = -ESRCH;
+        e = get_domain_by_id(op->u.set_target.target);
+        if ( e == NULL )
+            goto set_target_out;
+
+        if ( d == e ) {
+            ret = -EINVAL;
+            put_domain(e);
+            goto set_target_out;
         }
+
+        if (!IS_PRIV_FOR(current->domain, e)) {
+            ret = -EPERM;
+            put_domain(e);
+            goto set_target_out;
+        }
+
+        d->target = e;
+        /* and we keep the reference on e, released when destroying d */
+        ret = 0;
+
+set_target_out:
+        rcu_unlock_domain(d);
     }
     break;
 
--- a/xen/common/event_channel.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/common/event_channel.c	Wed Jan 23 11:36:15 2008 +0000
@@ -130,12 +130,15 @@
     long           rc;
 
     if ( dom == DOMID_SELF )
-        dom = current->domain->domain_id;
-    else if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
-    if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
-        return -ESRCH;
+        d = current->domain;
+    else {
+        if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
+            return -ESRCH;
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            rc = -EPERM;
+            goto out2;
+        }
+    }
 
     spin_lock(&d->evtchn_lock);
 
@@ -156,6 +159,7 @@
  out:
     spin_unlock(&d->evtchn_lock);
 
+ out2:
     rcu_unlock_domain(d);
 
     return rc;
@@ -197,7 +201,7 @@
         ERROR_EXIT_DOM(-EINVAL, rd);
     rchn = evtchn_from_port(rd, rport);
     if ( (rchn->state != ECS_UNBOUND) ||
-         (rchn->u.unbound.remote_domid != ld->domain_id) )
+            (rchn->u.unbound.remote_domid != ld->domain_id && !IS_PRIV_FOR(ld, rd)))
         ERROR_EXIT_DOM(-EINVAL, rd);
 
     rc = xsm_evtchn_interdomain(ld, lchn, rd, rchn);
@@ -628,12 +632,15 @@
     long             rc = 0;
 
     if ( dom == DOMID_SELF )
-        dom = current->domain->domain_id;
-    else if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
-    if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
-        return -ESRCH;
+        d = current->domain;
+    else {
+        if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
+            return -ESRCH;
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            rc = -EPERM;
+            goto out2;
+        }
+    }
 
     spin_lock(&d->evtchn_lock);
 
@@ -684,6 +691,7 @@
 
  out:
     spin_unlock(&d->evtchn_lock);
+ out2:
     rcu_unlock_domain(d);
     return rc;
 }
@@ -782,26 +790,28 @@
     int rc;
 
     if ( dom == DOMID_SELF )
-        dom = current->domain->domain_id;
-    else if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
-    if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
-        return -ESRCH;
+        d = current->domain;
+    else {
+        if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
+            return -ESRCH;
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            rc = -EPERM;
+            goto out;
+        }
+    }
 
     rc = xsm_evtchn_reset(current->domain, d);
     if ( rc )
-    {
-        rcu_unlock_domain(d);
-        return rc;
-    }
+        goto out;
 
     for ( i = 0; port_is_valid(d, i); i++ )
         (void)__evtchn_close(d, i);
 
+    rc = 0;
+out:
     rcu_unlock_domain(d);
 
-    return 0;
+    return rc;
 }
 
 
--- a/xen/common/grant_table.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/common/grant_table.c	Wed Jan 23 11:36:15 2008 +0000
@@ -834,19 +834,19 @@
     dom = op.dom;
     if ( dom == DOMID_SELF )
     {
-        dom = current->domain->domain_id;
+        d = current->domain;
     }
-    else if ( unlikely(!IS_PRIV(current->domain)) )
-    {
-        op.status = GNTST_permission_denied;
-        goto out;
-    }
-
-    if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) )
-    {
-        gdprintk(XENLOG_INFO, "Bad domid %d.\n", dom);
-        op.status = GNTST_bad_domain;
-        goto out;
+    else {
+        if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) )
+        {
+            gdprintk(XENLOG_INFO, "Bad domid %d.\n", dom);
+            op.status = GNTST_bad_domain;
+            goto out;
+        }
+        if ( unlikely(!IS_PRIV_FOR(current->domain, d)) ) {
+            op.status = GNTST_permission_denied;
+            goto setup_unlock_out2;
+        }
     }
 
     if ( xsm_grant_setup(current->domain, d) )
@@ -880,6 +880,7 @@
  setup_unlock_out:
     spin_unlock(&d->grant_table->lock);
 
+ setup_unlock_out2:
     rcu_unlock_domain(d);
 
  out:
@@ -910,27 +911,26 @@
     dom = op.dom;
     if ( dom == DOMID_SELF )
     {
-        dom = current->domain->domain_id;
+        d = current->domain;
     }
-    else if ( unlikely(!IS_PRIV(current->domain)) )
-    {
-        op.status = GNTST_permission_denied;
-        goto query_out;
-    }
-
-    if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) )
-    {
-        gdprintk(XENLOG_INFO, "Bad domid %d.\n", dom);
-        op.status = GNTST_bad_domain;
-        goto query_out;
+    else {
+        if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) )
+        {
+            gdprintk(XENLOG_INFO, "Bad domid %d.\n", dom);
+            op.status = GNTST_bad_domain;
+            goto query_out;
+        }
+        if ( unlikely(!IS_PRIV_FOR(current->domain, d)) ) {
+            op.status = GNTST_permission_denied;
+            goto query_out_unlock;
+        }
     }
 
     rc = xsm_grant_query_size(current->domain, d);
     if ( rc )
     {
-        rcu_unlock_domain(d);
         op.status = GNTST_permission_denied;
-        goto query_out;
+        goto query_out_unlock;
     }
 
     spin_lock(&d->grant_table->lock);
@@ -941,6 +941,8 @@
 
     spin_unlock(&d->grant_table->lock);
 
+ 
+ query_out_unlock:
     rcu_unlock_domain(d);
 
  query_out:
--- a/xen/common/memory.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/common/memory.c	Wed Jan 23 11:36:15 2008 +0000
@@ -232,12 +232,17 @@
         return -EFAULT;
 
     if ( op.domid == DOMID_SELF )
-        op.domid = current->domain->domain_id;
-    else if ( !IS_PRIV(current->domain) )
-        return -EPERM;
+        d = current->domain;
+    else {
+        d = rcu_lock_domain_by_id(op.domid);
+        if ( d == NULL )
+            return -ESRCH;
+        if ( !IS_PRIV_FOR(current->domain, d) ) {
+            rcu_unlock_domain(d);
+            return -EPERM;
+        }
+    }
 
-    if ( (d = rcu_lock_domain_by_id(op.domid)) == NULL )
-        return -ESRCH;
 
     if ( !paging_mode_translate(d) )
     {
@@ -535,9 +540,15 @@
 
         if ( likely(reservation.domid == DOMID_SELF) )
             d = current->domain;
-        else if ( !IS_PRIV(current->domain) ||
-                  ((d = rcu_lock_domain_by_id(reservation.domid)) == NULL) )
-            return start_extent;
+        else {
+            d = rcu_lock_domain_by_id(reservation.domid);
+            if ( d == NULL)
+                return start_extent;
+            if ( !IS_PRIV_FOR(current->domain, d) ) {
+                rcu_unlock_domain(d);
+                return start_extent;
+            }
+        }
         args.domain = d;
 
         rc = xsm_memory_adjust_reservation(current->domain, d);
@@ -589,10 +600,15 @@
 
         if ( likely(domid == DOMID_SELF) )
             d = current->domain;
-        else if ( !IS_PRIV(current->domain) )
-            return -EPERM;
-        else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
-            return -ESRCH;
+        else {
+            d = rcu_lock_domain_by_id(domid);
+            if ( d == NULL )
+                return -ESRCH;
+            if ( !IS_PRIV_FOR(current->domain, d) ) {
+                rcu_unlock_domain(d);
+                return -EPERM;
+            }
+        }
 
         rc = xsm_memory_stat_reservation(current->domain, d);
         if ( rc )
--- a/xen/common/schedule.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/common/schedule.c	Wed Jan 23 11:36:15 2008 +0000
@@ -461,9 +461,6 @@
         struct domain *d;
         struct sched_remote_shutdown sched_remote_shutdown;
 
-        if ( !IS_PRIV(current->domain) )
-            return -EPERM;
-
         ret = -EFAULT;
         if ( copy_from_guest(&sched_remote_shutdown, arg, 1) )
             break;
@@ -472,6 +469,12 @@
         d = rcu_lock_domain_by_id(sched_remote_shutdown.domain_id);
         if ( d == NULL )
             break;
+
+        if ( !IS_PRIV_FOR(current->domain, d) )
+        {
+            rcu_unlock_domain(d);
+            return -EPERM;
+        }
 
         ret = xsm_schedop_shutdown(current->domain, d);
         if ( ret )
--- a/xen/include/public/domctl.h	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/include/public/domctl.h	Wed Jan 23 11:36:15 2008 +0000
@@ -554,6 +554,17 @@
 typedef struct xen_domctl_set_opt_feature xen_domctl_set_opt_feature_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_opt_feature_t);
 
+/*
+ * Set the target domain for a domain
+ */
+#define XEN_DOMCTL_set_target    46
+struct xen_domctl_set_target {
+    domid_t target;
+};
+typedef struct xen_domctl_set_target xen_domctl_set_target_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t);
+
+
 struct xen_domctl {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -590,6 +601,7 @@
         struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr;
         struct xen_domctl_ext_vcpucontext   ext_vcpucontext;
         struct xen_domctl_set_opt_feature   set_opt_feature;
+        struct xen_domctl_set_target        set_target;
         uint8_t                             pad[128];
     } u;
 };
--- a/xen/include/xen/sched.h	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/include/xen/sched.h	Wed Jan 23 11:36:15 2008 +0000
@@ -187,6 +187,8 @@
     bool_t           is_hvm;
     /* Is this guest fully privileged (aka dom0)? */
     bool_t           is_privileged;
+    /* Which guest this guest has privileges on */
+    struct domain   *target;
     /* Is this guest being debugged by dom0? */
     bool_t           debugger_attached;
     /* Are any VCPUs polling event channels (SCHEDOP_poll)? */
@@ -493,6 +495,7 @@
 }
 
 #define IS_PRIV(_d) ((_d)->is_privileged)
+#define IS_PRIV_FOR(_d, _t) (IS_PRIV(_d) || ((_d)->target && (_d)->target == (_t)))
 
 #ifndef IS_COMPAT
 #define IS_COMPAT(d) 0
--- a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c	Wed Jan 23 11:21:35 2008 +0000
+++ b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c	Wed Jan 23 11:36:15 2008 +0000
@@ -817,17 +817,19 @@
         return ACM_ACCESS_PERMITTED;
     }
     atomic_inc(&ste_bin_pol.gt_eval_count);
+    subj = current->domain;
+    obj = rcu_lock_domain_by_id(id);
+
     /* a) check authorization (eventually use specific capabilities) */
-    if ( !IS_PRIV(current->domain) )
+    if ( obj && !IS_PRIV_FOR(current->domain, obj) )
     {
         printk("%s: Grant table management authorization denied ERROR!\n",
                __func__);
+        rcu_unlock_domain(obj);
         return ACM_ACCESS_DENIED;
     }
+
     /* b) check types */
-    subj = current->domain;
-    obj = rcu_lock_domain_by_id(id);
-
     if ( share_common_type(subj, obj) )
     {
         cache_result(subj, obj);

         reply	other threads:[~2008-01-23 11:55 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-23 12:06 [PATCH] New XS_SET_TARGET Samuel Thibault
2008-01-23 11:55 ` Samuel Thibault [this message]
2008-01-23 14:28   ` [PATCH] New XEN_DOMCTL_set_target and IS_PRIV_FOR John Levon
2008-01-23 14:36     ` Samuel Thibault
2008-01-23 14:29 ` [PATCH] New XS_SET_TARGET John Levon
2008-01-23 14:36   ` Keir Fraser
2008-01-23 14:42     ` John Levon
2008-01-23 14:46       ` Keir Fraser

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080123115529.GA5188@implementation.uk.xensource.com \
    --to=samuel.thibault@eu.citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.