mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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>
This commit is contained in:
1 parent
d352a2fb4d
commit
47fcfcb75b
25 files changed
+430
-190
No files matched your search
@@ -875,6 +875,20 @@ int xc_domain_ioport_mapping(
|
||||
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
|
||||
|
||||
@@ -952,4 +952,9 @@ int xc_domain_bind_pt_isa_irq(int xc_handle,
|
||||
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 */
|
||||
@@ -96,17 +96,17 @@ static PyObject *pyxc_domain_create(XcObject *self,
|
||||
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 )
|
||||
@@ -131,6 +131,11 @@ static PyObject *pyxc_domain_create(XcObject *self,
|
||||
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);
|
||||
|
||||
out_exception:
|
||||
|
||||
@@ -170,6 +170,7 @@ XENAPI_CFG_TYPES = {
|
||||
'platform': dict,
|
||||
'tools_version': dict,
|
||||
'other_config': dict,
|
||||
'target': int,
|
||||
'security_label': str,
|
||||
'pci': str,
|
||||
}
|
||||
@@ -336,7 +337,8 @@ class XendConfig(dict):
|
||||
'vbd_refs': [],
|
||||
'vtpm_refs': [],
|
||||
'other_config': {},
|
||||
'platform': {}
|
||||
'platform': {},
|
||||
'target': 0,
|
||||
}
|
||||
|
||||
return defaults
|
||||
@@ -1585,6 +1587,9 @@ class XendConfig(dict):
|
||||
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')
|
||||
@@ -1640,7 +1640,8 @@ class XendDomainInfo:
|
||||
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():
|
||||
|
||||
@@ -521,6 +521,10 @@ gopts.var('on_xend_stop', val='ignore|shutdown|suspend',
|
||||
- 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 @@ def make_config(vals):
|
||||
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])
|
||||
|
||||
@@ -47,9 +47,6 @@ static int hvmop_set_isa_irq_level(
|
||||
if ( copy_from_guest(&op, uop, 1) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EPERM;
|
||||
|
||||
if ( op.isa_irq > 15 )
|
||||
return -EINVAL;
|
||||
|
||||
@@ -57,6 +54,10 @@ static int hvmop_set_isa_irq_level(
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto out;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
@@ -79,9 +80,6 @@ static int hvmop_set_pci_intx_level(
|
||||
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;
|
||||
|
||||
@@ -89,6 +87,10 @@ static int hvmop_set_pci_intx_level(
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto out;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
@@ -124,13 +126,15 @@ do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
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;
|
||||
|
||||
@@ -37,9 +37,6 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EPERM;
|
||||
|
||||
switch ( op->cmd )
|
||||
{
|
||||
case XEN_DOMCTL_getmemlist:
|
||||
@@ -54,6 +51,13 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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;
|
||||
|
||||
@@ -87,6 +91,12 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !IS_PRIV_FOR(current->domain, d) ) {
|
||||
ret = -EPERM;
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ds->flags & XEN_DOMAINSETUP_query) {
|
||||
/* Set flags. */
|
||||
if (is_hvm_domain(d))
|
||||
@@ -153,6 +163,12 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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))
|
||||
@@ -173,6 +189,12 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if (unlikely(d == NULL))
|
||||
break;
|
||||
|
||||
if ( !IS_PRIV_FOR(current->domain, d) ) {
|
||||
ret = -EPERM;
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
if (np == 0)
|
||||
ret = 0;
|
||||
else {
|
||||
@@ -196,6 +218,11 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 )
|
||||
goto sendtrigger_out;
|
||||
@@ -239,6 +266,10 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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)
|
||||
@@ -280,6 +311,10 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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);
|
||||
if (ret)
|
||||
@@ -341,7 +376,10 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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;
|
||||
|
||||
@@ -500,13 +500,15 @@ do_ia64_debug_op(unsigned long cmd, unsigned long domain,
|
||||
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 @@ do_ia64_debug_op(unsigned long cmd, unsigned long domain,
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
out:
|
||||
rcu_unlock_domain(d);
|
||||
return ret;
|
||||
}
|
||||
@@ -2787,10 +2787,14 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
|
||||
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])) {
|
||||
|
||||
@@ -642,6 +642,7 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
|
||||
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
|
||||
|
||||
@@ -375,6 +375,7 @@ static void __init __start_xen(void)
|
||||
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();
|
||||
|
||||
+20
-14
@@ -1740,9 +1740,6 @@ static int hvmop_set_pci_intx_level(
|
||||
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;
|
||||
|
||||
@@ -1750,6 +1747,10 @@ static int hvmop_set_pci_intx_level(
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto out;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
@@ -1787,9 +1788,6 @@ static int hvmop_set_isa_irq_level(
|
||||
if ( copy_from_guest(&op, uop, 1) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EPERM;
|
||||
|
||||
if ( op.isa_irq > 15 )
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1797,6 +1795,10 @@ static int hvmop_set_isa_irq_level(
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto out;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
@@ -1834,9 +1836,6 @@ static int hvmop_set_pci_link_route(
|
||||
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;
|
||||
|
||||
@@ -1844,6 +1843,10 @@ static int hvmop_set_pci_link_route(
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto out;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto out;
|
||||
@@ -1921,13 +1924,16 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
|
||||
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) )
|
||||
|
||||
+39
-35
@@ -2056,38 +2056,35 @@ static int set_foreigndom(domid_t domid)
|
||||
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 do_update_va_mapping_otherdomain(unsigned long va, u64 val64,
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ( unlikely(!IS_PRIV(current->domain)) )
|
||||
return -EPERM;
|
||||
|
||||
if ( !set_foreigndom(domid) )
|
||||
return -ESRCH;
|
||||
|
||||
@@ -3222,10 +3216,15 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
|
||||
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 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
|
||||
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 )
|
||||
|
||||
@@ -993,11 +993,11 @@ shadow_get_page_from_l1e(shadow_l1e_t sl1e, struct domain *d)
|
||||
// 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 "
|
||||
|
||||
@@ -959,6 +959,7 @@ void __init __start_xen(unsigned long mbi_p)
|
||||
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);
|
||||
|
||||
@@ -502,6 +502,9 @@ static void complete_domain_destroy(struct rcu_head *head)
|
||||
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);
|
||||
|
||||
+133
-40
@@ -182,9 +182,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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;
|
||||
|
||||
@@ -207,6 +204,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto svc_out;
|
||||
|
||||
ret = xsm_setvcpucontext(d);
|
||||
if ( ret )
|
||||
goto svc_out;
|
||||
@@ -258,6 +259,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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);
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
unpausedomain_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -303,16 +310,18 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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);
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
resumedomain_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -323,6 +332,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
static domid_t rover = 0;
|
||||
unsigned int domcr_flags;
|
||||
|
||||
ret = -EPERM;
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
break;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( supervisor_mode_kernel ||
|
||||
(op->u.createdomain.flags & ~XEN_DOMCTL_CDF_hvm_guest) )
|
||||
@@ -385,12 +398,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
|
||||
maxvcpu_out:
|
||||
domain_unpause(d);
|
||||
maxvcpu_out2:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
@@ -428,7 +443,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -446,6 +463,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = -EPERM;
|
||||
if ( !IS_PRIV_FOR(current->domain, d) )
|
||||
goto vcpuaffinity_out;
|
||||
|
||||
ret = xsm_vcpuaffinity(op->cmd, d);
|
||||
if ( ret )
|
||||
goto vcpuaffinity_out;
|
||||
@@ -484,6 +505,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 )
|
||||
@@ -540,6 +565,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 )
|
||||
goto getvcpucontext_out;
|
||||
@@ -600,6 +629,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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));
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
setdomainhandle_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -694,18 +735,20 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 */
|
||||
rcu_unlock_domain(d);
|
||||
ret = 0;
|
||||
setdebugging_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -723,6 +766,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 )
|
||||
goto irq_permission_out;
|
||||
@@ -752,6 +799,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
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 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
|
||||
|
||||
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;
|
||||
|
||||
|
||||
+34
-24
@@ -130,12 +130,15 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
|
||||
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 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
|
||||
out:
|
||||
spin_unlock(&d->evtchn_lock);
|
||||
|
||||
out2:
|
||||
rcu_unlock_domain(d);
|
||||
|
||||
return rc;
|
||||
@@ -197,7 +201,7 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
|
||||
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 @@ static long evtchn_status(evtchn_status_t *status)
|
||||
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 @@ static long evtchn_status(evtchn_status_t *status)
|
||||
|
||||
out:
|
||||
spin_unlock(&d->evtchn_lock);
|
||||
out2:
|
||||
rcu_unlock_domain(d);
|
||||
return rc;
|
||||
}
|
||||
@@ -782,26 +790,28 @@ static long evtchn_reset(evtchn_reset_t *r)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+28
-26
@@ -834,19 +834,19 @@ gnttab_setup_table(
|
||||
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 @@ gnttab_setup_table(
|
||||
setup_unlock_out:
|
||||
spin_unlock(&d->grant_table->lock);
|
||||
|
||||
setup_unlock_out2:
|
||||
rcu_unlock_domain(d);
|
||||
|
||||
out:
|
||||
@@ -910,27 +911,26 @@ gnttab_query_size(
|
||||
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 @@ gnttab_query_size(
|
||||
|
||||
spin_unlock(&d->grant_table->lock);
|
||||
|
||||
|
||||
query_out_unlock:
|
||||
rcu_unlock_domain(d);
|
||||
|
||||
query_out:
|
||||
|
||||
+28
-12
@@ -232,12 +232,17 @@ static long translate_gpfn_list(
|
||||
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 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
|
||||
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 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
|
||||
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 )
|
||||
|
||||
@@ -461,9 +461,6 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
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;
|
||||
@@ -473,6 +470,12 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
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 )
|
||||
{
|
||||
|
||||
@@ -554,6 +554,17 @@ struct xen_domctl_set_opt_feature {
|
||||
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 {
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -187,6 +187,8 @@ struct domain
|
||||
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 @@ static inline void vcpu_unblock(struct vcpu *v)
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
@@ -817,17 +817,19 @@ ste_pre_grant_setup (domid_t id)
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
atomic_inc(&ste_bin_pol.gt_eval_count);
|
||||
/* a) check authorization (eventually use specific capabilities) */
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
{
|
||||
printk("%s: Grant table management authorization denied ERROR!\n",
|
||||
__func__);
|
||||
return ACM_ACCESS_DENIED;
|
||||
}
|
||||
/* b) check types */
|
||||
subj = current->domain;
|
||||
obj = rcu_lock_domain_by_id(id);
|
||||
|
||||
/* a) check authorization (eventually use specific capabilities) */
|
||||
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 */
|
||||
if ( share_common_type(subj, obj) )
|
||||
{
|
||||
cache_result(subj, obj);
|
||||
|
||||