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@xxxxxxxxxxxxx>
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);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|