Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 00/18] RFC: Merge IS_PRIV checks into XSM hooks
Since this series changes a lot of code accessible to guests, I think it''s better to let people comment on it now, even if it won''t go in until 4.3. Overall, it should not change the behavior of Xen when XSM is not enabled; however, in some cases, the exact errors that are returned will be different because security checks have been moved below validity checks. Also, once applied, newly introduced domctls and sysctls will not automatically be guarded by IS_PRIV checks - they will need to add their own permission checking code. Background: The Xen hypervisor has two basic access control function calls: IS_PRIV and the xsm_* functions. Most privileged operations currently require that both checks succeed, and many times the checks are at different locations in the code. When performing dom0 disaggregation, many of the functions normally protected with IS_PRIV are handled by domains other than dom0. This requires either making all such disaggregated domains privileged, or allowing certain operations to be performed without an IS_PRIV check. Because the privileged bit also short-circuits the IS_PRIV_FOR check, and some IS_PRIV calls do not currently have an accompanying XSM call, this series implements the second option. Once applied, most IS_PRIV checks are isolated in the newly introduced xen/include/xsm/dummy.h header. The remaining checks cover a few areas that need further examining or that have reason to remain: 1. Overriding the IRQ and IO memory access checks (arch/x86/domctl.c). These overrides should not be needed, as dom0 should have access without needing the override. 2. Allow MAP_PIRQ_TYPE_GSI to ignore domain_pirq_to_irq negative return 3. PIRQ operations by HVM domains (TODO add hooks) 4. The hack for device model framebuffers in get_page_from_l1e 5. Installing maps of non-owned pages in shadow_get_page_from_l1e 6. PCI configuration space (arch/x86/traps.c). Allowing a PV Linux domU to access the PCI configuration space is a good way to crash the system as it reconfigures PCI devices during boot, so this needs to remain to get a working system when FLASK is in permissive mode. 7. Various MSR accesses (arch/x86/traps.c) 8. ARM architecture - not touched at all in these patches. The rcu_lock_target_domain_by_id and rcu_lock_remote_target_domain_by_id functions are removed by this series because they act as wrappers around IS_PRIV_FOR; their callers have been changed to use XSM checks instead. Miscellaneous updates to FLASK: [PATCH 01/18] xsm/flask: remove inherited class attributes [PATCH 02/18] xsm/flask: remove unneeded create_sid field [PATCH 03/18] xsm/flask: add domain relabel support [PATCH 04/18] libxl: introduce XSM relabel on build [PATCH 05/18] flask/policy: Add domain relabel example Preparatory: [PATCH 06/18] xsm, arch/x86: add distinct XSM hooks for map/unmap [PATCH 07/18] arch/x86: add missing XSM checks to XENPF_ commands [PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id [PATCH 09/18] xsm/flask: Add checks on the domain performing set_target Refactor checks into existing XSM hooks: [PATCH 10/18] xsm: Add IS_PRIV checks to dummy XSM module [PATCH 11/18] xen: use XSM instead of IS_PRIV where duplicated Clean up remaining IS_PRIV calls (1): [PATCH 12/18] xsm: Add missing domctl and mem_sharing hooks [PATCH 13/18] tmem: Add access control check FLASK updates to allow acting as a proper IS_PRIV replacement: [PATCH 14/18] xsm: remove unneeded xsm_call macro [PATCH 15/18] xsm/flask: add distinct SIDs for self/target access Clean up remaining IS_PRIV calls (2): [PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks [PATCH 17/18] xen: Add XSM hook for XENMEM_exchange [PATCH 18/18] xen: remove rcu_lock_target_domain_by_id
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 01/18] xsm/flask: remove inherited class attributes
The ability to declare common permission blocks shared across multiple classes is not currently used in Xen. Currently, support for this feature is broken in the header generation scripts, and it is not expected that this feature will be used in the future, so remove the dead code. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/Makefile | 2 +- tools/flask/policy/policy/flask/access_vectors | 17 +---- tools/flask/policy/policy/flask/mkaccess_vector.sh | 89 ---------------------- xen/xsm/flask/avc.c | 27 ------- xen/xsm/flask/include/av_inherit.h | 1 - xen/xsm/flask/include/avc_ss.h | 8 -- xen/xsm/flask/include/common_perm_to_string.h | 1 - xen/xsm/flask/ss/services.c | 54 +------------ 8 files changed, 4 insertions(+), 195 deletions(-) delete mode 100644 xen/xsm/flask/include/av_inherit.h delete mode 100644 xen/xsm/flask/include/common_perm_to_string.h diff --git a/tools/flask/policy/policy/flask/Makefile b/tools/flask/policy/policy/flask/Makefile index 970b9fe..5f57e88 100644 --- a/tools/flask/policy/policy/flask/Makefile +++ b/tools/flask/policy/policy/flask/Makefile @@ -14,7 +14,7 @@ FLASK_H_DEPEND = security_classes initial_sids AV_H_DEPEND = access_vectors FLASK_H_FILES = class_to_string.h flask.h initial_sid_to_string.h -AV_H_FILES = av_inherit.h common_perm_to_string.h av_perm_to_string.h av_permissions.h +AV_H_FILES = av_perm_to_string.h av_permissions.h ALL_H_FILES = $(FLASK_H_FILES) $(AV_H_FILES) all: $(ALL_H_FILES) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 5901911..a884312 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -1,22 +1,7 @@ # -# Define common prefixes for access vectors -# -# common common_name { permission_name ... } - -# -# Define a common prefix for file access vectors. -# - - -# # Define the access vectors. # -# class class_name [ inherits common_name ] { permission_name ... } - - -# -# Define the access vector interpretation for file-related objects. -# +# class class_name { permission_name ... } class xen { diff --git a/tools/flask/policy/policy/flask/mkaccess_vector.sh b/tools/flask/policy/policy/flask/mkaccess_vector.sh index b5da734..43a60a7 100644 --- a/tools/flask/policy/policy/flask/mkaccess_vector.sh +++ b/tools/flask/policy/policy/flask/mkaccess_vector.sh @@ -10,50 +10,21 @@ shift # output files av_permissions="av_permissions.h" -av_inherit="av_inherit.h" -common_perm_to_string="common_perm_to_string.h" av_perm_to_string="av_perm_to_string.h" cat $* | $awk " BEGIN { outfile = \"$av_permissions\" - inheritfile = \"$av_inherit\" - cpermfile = \"$common_perm_to_string\" avpermfile = \"$av_perm_to_string\" "'' nextstate = "COMMON_OR_AV"; printf("/* This file is automatically generated. Do not edit. */\n") > outfile; - printf("/* This file is automatically generated. Do not edit. */\n") > inheritfile; - printf("/* This file is automatically generated. Do not edit. */\n") > cpermfile; printf("/* This file is automatically generated. Do not edit. */\n") > avpermfile; ; } /^[ \t]*#/ { next; } -$1 == "common" { - if (nextstate != "COMMON_OR_AV") - { - printf("Parse error: Unexpected COMMON definition on line %d\n", NR); - next; - } - - if ($2 in common_defined) - { - printf("Duplicate COMMON definition for %s on line %d.\n", $2, NR); - next; - } - common_defined[$2] = 1; - - tclass = $2; - common_name = $2; - permission = 1; - - printf("TB_(common_%s_perm_to_string)\n", $2) > cpermfile; - - nextstate = "COMMON-OPENBRACKET"; - next; - } $1 == "class" { if (nextstate != "COMMON_OR_AV" && nextstate != "CLASS_OR_CLASS-OPENBRACKET") @@ -71,62 +42,11 @@ $1 == "class" { } av_defined[tclass] = 1; - inherits = ""; permission = 1; nextstate = "INHERITS_OR_CLASS-OPENBRACKET"; next; } -$1 == "inherits" { - if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET") - { - printf("Parse error: Unexpected INHERITS definition on line %d\n", NR); - next; - } - - if (!($2 in common_defined)) - { - printf("COMMON %s is not defined (line %d).\n", $2, NR); - next; - } - - inherits = $2; - permission = common_base[$2]; - - for (combined in common_perms) - { - split(combined,separate, SUBSEP); - if (separate[1] == inherits) - { - inherited_perms[common_perms[combined]] = separate[2]; - } - } - - j = 1; - for (i in inherited_perms) { - ind[j] = i + 0; - j++; - } - n = asort(ind); - for (i = 1; i <= n; i++) { - perm = inherited_perms[ind[i]]; - printf("#define %s__%s", toupper(tclass), toupper(perm)) > outfile; - spaces = 40 - (length(perm) + length(tclass)); - if (spaces < 1) - spaces = 1; - for (j = 0; j < spaces; j++) - printf(" ") > outfile; - printf("0x%08xUL\n", ind[i]) > outfile; - } - printf("\n") > outfile; - for (i in ind) delete ind[i]; - for (i in inherited_perms) delete inherited_perms[i]; - - printf(" S_(SECCLASS_%s, %s, 0x%08xUL)\n", toupper(tclass), inherits, permission) > inheritfile; - - nextstate = "CLASS_OR_CLASS-OPENBRACKET"; - next; - } $1 == "{" { if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET" && nextstate != "CLASS_OR_CLASS-OPENBRACKET" && @@ -177,15 +97,6 @@ $1 == "{" { av_perms[tclass,$1] = permission; - if (inherits != "") - { - if ((inherits,$1) in common_perms) - { - printf("Permission %s in %s on line %d conflicts with common permission.\n", $1, tclass, inherits, NR); - next; - } - } - printf("#define %s__%s", toupper(tclass), toupper($1)) > outfile; printf(" S_(SECCLASS_%s, %s__%s, \"%s\")\n", toupper(tclass), toupper(tclass), toupper($1), $1) > avpermfile; diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c index 44240a9..1bfeef2 100644 --- a/xen/xsm/flask/avc.c +++ b/xen/xsm/flask/avc.c @@ -45,28 +45,11 @@ static const char *class_to_string[] = { #undef S_ }; -#define TB_(s) static const char * s [] = { -#define TE_(s) }; -#define S_(s) s, -#include "common_perm_to_string.h" -#undef TB_ -#undef TE_ -#undef S_ - -static const struct av_inherit av_inherit[] = { -#define S_(c, i, b) { .tclass = c, .common_pts = common_##i##_perm_to_string, \ - .common_base = b }, -#include "av_inherit.h" -#undef S_ -}; - const struct selinux_class_perm selinux_class_perm = { .av_perm_to_string = av_perm_to_string, .av_pts_len = ARRAY_SIZE(av_perm_to_string), .class_to_string = class_to_string, .cts_len = ARRAY_SIZE(class_to_string), - .av_inherit = av_inherit, - .av_inherit_len = ARRAY_SIZE(av_inherit) }; #define AVC_CACHE_SLOTS 512 @@ -191,16 +174,6 @@ static void avc_dump_av(struct avc_dump_buf *buf, u16 tclass, u32 av) return; } - for ( i = 0; i < ARRAY_SIZE(av_inherit); i++ ) - { - if (av_inherit[i].tclass == tclass) - { - common_pts = av_inherit[i].common_pts; - common_base = av_inherit[i].common_base; - break; - } - } - avc_printk(buf, " {"); i = 0; perm = 1; diff --git a/xen/xsm/flask/include/av_inherit.h b/xen/xsm/flask/include/av_inherit.h deleted file mode 100644 index 321ffe7..0000000 --- a/xen/xsm/flask/include/av_inherit.h +++ /dev/null @@ -1 +0,0 @@ -/* This file is automatically generated. Do not edit. */ diff --git a/xen/xsm/flask/include/avc_ss.h b/xen/xsm/flask/include/avc_ss.h index ea4e98c..a3d7d1e 100644 --- a/xen/xsm/flask/include/avc_ss.h +++ b/xen/xsm/flask/include/avc_ss.h @@ -16,19 +16,11 @@ struct av_perm_to_string { const char *name; }; -struct av_inherit { - const char **common_pts; - u32 common_base; - u16 tclass; -}; - struct selinux_class_perm { const struct av_perm_to_string *av_perm_to_string; u32 av_pts_len; u32 cts_len; const char **class_to_string; - const struct av_inherit *av_inherit; - u32 av_inherit_len; }; extern const struct selinux_class_perm selinux_class_perm; diff --git a/xen/xsm/flask/include/common_perm_to_string.h b/xen/xsm/flask/include/common_perm_to_string.h deleted file mode 100644 index 321ffe7..0000000 --- a/xen/xsm/flask/include/common_perm_to_string.h +++ /dev/null @@ -1 +0,0 @@ -/* This file is automatically generated. Do not edit. */ diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index 363f586..1bf3b0c 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -1167,10 +1167,10 @@ int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) */ static int validate_classes(struct policydb *p) { - int i, j; + int i; struct class_datum *cladatum; struct perm_datum *perdatum; - u32 nprim, tmp, common_pts_len, perm_val, pol_val; + u32 nprim, perm_val, pol_val; u16 class_val; const struct selinux_class_perm *kdefs = &selinux_class_perm; const char *def_class, *def_perm, *pol_class; @@ -1233,56 +1233,6 @@ static int validate_classes(struct policydb *p) return -EINVAL; } } - for ( i = 0; i < kdefs->av_inherit_len; i++ ) - { - class_val = kdefs->av_inherit[i].tclass; - if ( class_val > p->p_classes.nprim ) - continue; - pol_class = p->p_class_val_to_name[class_val-1]; - cladatum = hashtab_search(p->p_classes.table, pol_class); - BUG_ON( !cladatum ); - if ( !cladatum->comdatum ) - { - printk(KERN_ERR - "Flask: class %s should have an inherits clause but does not\n", - pol_class); - return -EINVAL; - } - tmp = kdefs->av_inherit[i].common_base; - common_pts_len = 0; - while ( !(tmp & 0x01) ) - { - common_pts_len++; - tmp >>= 1; - } - perms = &cladatum->comdatum->permissions; - for ( j = 0; j < common_pts_len; j++ ) - { - def_perm = kdefs->av_inherit[i].common_pts[j]; - if ( j >= perms->nprim ) - { - printk(KERN_INFO - "Flask: permission %s in class %s not defined in policy\n", - def_perm, pol_class); - return -EINVAL; - } - perdatum = hashtab_search(perms->table, def_perm); - if ( perdatum == NULL ) - { - printk(KERN_ERR - "Flask: permission %s in class %s not found in policy\n", - def_perm, pol_class); - return -EINVAL; - } - if ( perdatum->value != j + 1 ) - { - printk(KERN_ERR - "Flask: permission %s in class %s has incorrect value\n", - def_perm, pol_class); - return -EINVAL; - } - } - } return 0; } -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 02/18] xsm/flask: remove unneeded create_sid field
This field was only used to populate the ssid of dom0, which can be handled explicitly in the domain creation hook. This also removes the unnecessary permission check on the creation of dom0. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.te | 2 -- xen/xsm/flask/hooks.c | 23 ++++++++++------------- xen/xsm/flask/include/objsec.h | 1 - 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 29885c4..3d2e351 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -52,8 +52,6 @@ type device_t, resource_type; # Rules required to boot the hypervisor and dom0 # ################################################################################ -allow xen_t dom0_t:domain { create }; - allow dom0_t xen_t:xen { kexec readapic writeapic mtrr_read mtrr_add mtrr_del scheduler physinfo heap quirk readconsole writeconsole settime microcode cpupool_op sched_op }; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 62771bf..9262d34 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -111,12 +111,10 @@ static int flask_domain_alloc_security(struct domain *d) if ( is_idle_domain(d) ) { dsec->sid = SECINITSID_XEN; - dsec->create_sid = SECINITSID_DOM0; } else { dsec->sid = SECINITSID_UNLABELED; - dsec->create_sid = SECSID_NULL; } d->ssid = dsec; @@ -549,25 +547,24 @@ static int flask_domain_create(struct domain *d, u32 ssidref) int rc; struct domain_security_struct *dsec1; struct domain_security_struct *dsec2; + static int dom0_created = 0; dsec1 = current->domain->ssid; + dsec2 = d->ssid; - if ( dsec1->create_sid == SECSID_NULL ) - dsec1->create_sid = ssidref; + if ( is_idle_domain(current->domain) && !dom0_created ) + { + dsec2->sid = SECINITSID_DOM0; + dom0_created = 1; + return 0; + } - rc = avc_has_perm(dsec1->sid, dsec1->create_sid, SECCLASS_DOMAIN, + rc = avc_has_perm(dsec1->sid, ssidref, SECCLASS_DOMAIN, DOMAIN__CREATE, NULL); if ( rc ) - { - dsec1->create_sid = SECSID_NULL; return rc; - } - - dsec2 = d->ssid; - dsec2->sid = dsec1->create_sid; - dsec1->create_sid = SECSID_NULL; - dsec2->create_sid = SECSID_NULL; + dsec2->sid = ssidref; return rc; } diff --git a/xen/xsm/flask/include/objsec.h b/xen/xsm/flask/include/objsec.h index df5baee..4ff52be 100644 --- a/xen/xsm/flask/include/objsec.h +++ b/xen/xsm/flask/include/objsec.h @@ -19,7 +19,6 @@ struct domain_security_struct { u32 sid; /* current SID */ - u32 create_sid; }; struct evtchn_security_struct { -- 1.7.11.2
This adds the ability to change a domain''s XSM label after creation. The new label will be used for all future access checks; however, existing event channels and memory mappings will remain valid even if their creation would be denied by the new label. With appropriate security policy and hooks in the domain builder, this can be used to create domains that the domain builder does not have access to after building. It can also be used to allow a domain to drop privileges - for example, prior to launching a user-supplied kernel loaded by a pv-grub stubdom. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 7 ++++ tools/flask/policy/policy/flask/security_classes | 1 + tools/flask/policy/policy/modules/xen/xen.te | 2 +- xen/include/public/xsm/flask_op.h | 8 ++++ xen/xsm/flask/flask_op.c | 49 ++++++++++++++++++++++++ xen/xsm/flask/include/av_perm_to_string.h | 3 ++ xen/xsm/flask/include/av_permissions.h | 4 ++ xen/xsm/flask/include/class_to_string.h | 1 + xen/xsm/flask/include/flask.h | 15 ++++---- 9 files changed, 82 insertions(+), 8 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index a884312..c7e29ab 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -73,6 +73,13 @@ class domain set_virq_handler } +class domain2 +{ + relabelfrom + relabelto + relabelself +} + class hvm { sethvmc diff --git a/tools/flask/policy/policy/flask/security_classes b/tools/flask/policy/policy/flask/security_classes index 2ca35d2..ef134a7 100644 --- a/tools/flask/policy/policy/flask/security_classes +++ b/tools/flask/policy/policy/flask/security_classes @@ -9,6 +9,7 @@ class xen class domain +class domain2 class hvm class mmu class resource diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 3d2e351..f9bc061 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -169,7 +169,7 @@ delegate_devices(dom0_t, domU_t) ################################################################################ # Domains must be declared using domain_type -neverallow * ~domain_type:domain create; +neverallow * ~domain_type:domain { create transition }; # Resources must be declared using resource_type neverallow * ~resource_type:resource use; diff --git a/xen/include/public/xsm/flask_op.h b/xen/include/public/xsm/flask_op.h index 1a251c9..233de81 100644 --- a/xen/include/public/xsm/flask_op.h +++ b/xen/include/public/xsm/flask_op.h @@ -142,6 +142,12 @@ struct xen_flask_peersid { uint32_t sid; }; +struct xen_flask_relabel { + /* IN */ + uint32_t domid; + uint32_t sid; +}; + struct xen_flask_op { uint32_t cmd; #define FLASK_LOAD 1 @@ -167,6 +173,7 @@ struct xen_flask_op { #define FLASK_ADD_OCONTEXT 21 #define FLASK_DEL_OCONTEXT 22 #define FLASK_GET_PEER_SID 23 +#define FLASK_RELABEL_DOMAIN 24 uint32_t interface_version; /* XEN_FLASK_INTERFACE_VERSION */ union { struct xen_flask_load load; @@ -185,6 +192,7 @@ struct xen_flask_op { /* FLASK_ADD_OCONTEXT, FLASK_DEL_OCONTEXT */ struct xen_flask_ocontext ocontext; struct xen_flask_peersid peersid; + struct xen_flask_relabel relabel; } u; }; typedef struct xen_flask_op xen_flask_op_t; diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c index bd4db37..9c0a087 100644 --- a/xen/xsm/flask/flask_op.c +++ b/xen/xsm/flask/flask_op.c @@ -573,6 +573,51 @@ static int flask_get_peer_sid(struct xen_flask_peersid *arg) return rv; } +static int flask_relabel_domain(struct xen_flask_relabel *arg) +{ + int rc; + struct domain *d; + struct domain_security_struct *csec = current->domain->ssid; + struct domain_security_struct *dsec; + struct avc_audit_data ad; + AVC_AUDIT_DATA_INIT(&ad, NONE); + + d = rcu_lock_domain_by_id(arg->domid); + if ( d == NULL ) + return -ESRCH; + + ad.sdom = current->domain; + ad.tdom = d; + dsec = d->ssid; + + if ( arg->domid == DOMID_SELF ) + { + rc = avc_has_perm(dsec->sid, arg->sid, SECCLASS_DOMAIN2, DOMAIN2__RELABELSELF, &ad); + if ( rc ) + goto out; + } + else + { + rc = avc_has_perm(csec->sid, dsec->sid, SECCLASS_DOMAIN2, DOMAIN2__RELABELFROM, &ad); + if ( rc ) + goto out; + + rc = avc_has_perm(csec->sid, arg->sid, SECCLASS_DOMAIN2, DOMAIN2__RELABELTO, &ad); + if ( rc ) + goto out; + } + + rc = avc_has_perm(dsec->sid, arg->sid, SECCLASS_DOMAIN, DOMAIN__TRANSITION, &ad); + if ( rc ) + goto out; + + dsec->sid = arg->sid; + + out: + rcu_unlock_domain(d); + return rc; +} + long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op) { xen_flask_op_t op; @@ -680,6 +725,10 @@ long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op) rv = flask_get_peer_sid(&op.u.peersid); break; + case FLASK_RELABEL_DOMAIN: + rv = flask_relabel_domain(&op.u.relabel); + break; + default: rv = -ENOSYS; } diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 17a1c36..e7e2058 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -61,6 +61,9 @@ S_(SECCLASS_DOMAIN, DOMAIN__SETPODTARGET, "setpodtarget") S_(SECCLASS_DOMAIN, DOMAIN__SET_MISC_INFO, "set_misc_info") S_(SECCLASS_DOMAIN, DOMAIN__SET_VIRQ_HANDLER, "set_virq_handler") + S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELFROM, "relabelfrom") + S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELTO, "relabelto") + S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELSELF, "relabelself") S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc") S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc") S_(SECCLASS_HVM, HVM__SETPARAM, "setparam") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index 42eaf81..cb1c5dc 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -63,6 +63,10 @@ #define DOMAIN__SET_MISC_INFO 0x40000000UL #define DOMAIN__SET_VIRQ_HANDLER 0x80000000UL +#define DOMAIN2__RELABELFROM 0x00000001UL +#define DOMAIN2__RELABELTO 0x00000002UL +#define DOMAIN2__RELABELSELF 0x00000004UL + #define HVM__SETHVMC 0x00000001UL #define HVM__GETHVMC 0x00000002UL #define HVM__SETPARAM 0x00000004UL diff --git a/xen/xsm/flask/include/class_to_string.h b/xen/xsm/flask/include/class_to_string.h index ab55700..7716645 100644 --- a/xen/xsm/flask/include/class_to_string.h +++ b/xen/xsm/flask/include/class_to_string.h @@ -5,6 +5,7 @@ S_("null") S_("xen") S_("domain") + S_("domain2") S_("hvm") S_("mmu") S_("resource") diff --git a/xen/xsm/flask/include/flask.h b/xen/xsm/flask/include/flask.h index 6d29c5a..3bff998 100644 --- a/xen/xsm/flask/include/flask.h +++ b/xen/xsm/flask/include/flask.h @@ -7,13 +7,14 @@ */ #define SECCLASS_XEN 1 #define SECCLASS_DOMAIN 2 -#define SECCLASS_HVM 3 -#define SECCLASS_MMU 4 -#define SECCLASS_RESOURCE 5 -#define SECCLASS_SHADOW 6 -#define SECCLASS_EVENT 7 -#define SECCLASS_GRANT 8 -#define SECCLASS_SECURITY 9 +#define SECCLASS_DOMAIN2 3 +#define SECCLASS_HVM 4 +#define SECCLASS_MMU 5 +#define SECCLASS_RESOURCE 6 +#define SECCLASS_SHADOW 7 +#define SECCLASS_EVENT 8 +#define SECCLASS_GRANT 9 +#define SECCLASS_SECURITY 10 /* * Security identifier indices for initial entities -- 1.7.11.2
Allow a domain to be built under one security label and run using a different label. This can be used to prevent the domain builder or control domain from having the ability to access a guest domain''s memory via map_foreign_range except during the build process where this is required. Note: this does not provide complete protection from a malicious dom0; mappings created during the build process may persist after the relabel, and could be used to indirectly access the guest''s memory. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/libxc/xc_flask.c | 10 ++++++++++ tools/libxc/xenctrl.h | 1 + tools/libxl/libxl_create.c | 4 ++++ tools/libxl/libxl_types.idl | 1 + tools/libxl/xl_cmdimpl.c | 20 +++++++++++++++++++- 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tools/libxc/xc_flask.c b/tools/libxc/xc_flask.c index 80c5a2d..face1e0 100644 --- a/tools/libxc/xc_flask.c +++ b/tools/libxc/xc_flask.c @@ -422,6 +422,16 @@ int xc_flask_setavc_threshold(xc_interface *xch, int threshold) return xc_flask_op(xch, &op); } +int xc_flask_relabel_domain(xc_interface *xch, int domid, uint32_t sid) +{ + DECLARE_FLASK_OP; + op.cmd = FLASK_RELABEL_DOMAIN; + op.u.relabel.domid = domid; + op.u.relabel.sid = sid; + + return xc_flask_op(xch, &op); +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 91fbb02..2ac74d9 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -2152,6 +2152,7 @@ int xc_flask_policyvers(xc_interface *xc_handle); int xc_flask_avc_hashstats(xc_interface *xc_handle, char *buf, int size); int xc_flask_getavc_threshold(xc_interface *xc_handle); int xc_flask_setavc_threshold(xc_interface *xc_handle, int threshold); +int xc_flask_relabel_domain(xc_interface *xch, int domid, uint32_t sid); struct elf_binary; void xc_elf_set_logfile(xc_interface *xch, struct elf_binary *elf, diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index aafacd8..3c227e6 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -1100,6 +1100,10 @@ static void domcreate_complete(libxl__egc *egc, int rc) { STATE_AO_GC(dcs->ao); + libxl_domain_config *const d_config = dcs->guest_config; + + if (!rc && d_config->b_info.exec_ssidref) + rc = xc_flask_relabel_domain(CTX->xch, dcs->guest_domid, d_config->b_info.exec_ssidref); if (rc) { if (dcs->guest_domid) { diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index daa8c79..eb2668f 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -257,6 +257,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("video_memkb", MemKB), ("shadow_memkb", MemKB), ("rtc_timeoffset", uint32), + ("exec_ssidref", uint32), ("localtime", libxl_defbool), ("disable_migrate", libxl_defbool), ("cpuid", libxl_cpuid_policy_list), diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index a7dc340..a63ef57 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -582,16 +582,34 @@ static void parse_config_data(const char *config_source, exit(1); } - if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) { + if (!xlu_cfg_get_string (config, "init_seclabel", &buf, 0)) { e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf), &c_info->ssidref); if (e) { if (errno == ENOSYS) { + fprintf(stderr, "XSM Disabled: init_seclabel not supported\n"); + } else { + fprintf(stderr, "Invalid init_seclabel: %s\n", buf); + exit(1); + } + } + } + + if (!xlu_cfg_get_string (config, "seclabel", &buf, 0)) { + uint32_t ssidref; + e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf), + &ssidref); + if (e) { + if (errno == ENOSYS) { fprintf(stderr, "XSM Disabled: seclabel not supported\n"); } else { fprintf(stderr, "Invalid seclabel: %s\n", buf); exit(1); } + } else if (c_info->ssidref) { + b_info->exec_ssidref = ssidref; + } else { + c_info->ssidref = ssidref; } } -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 05/18] flask/policy: Add domain relabel example
This adds the nomigrate_t type to the example FLASK policy which allows domains to be created that dom0 cannot access after building. Example domain configuration snippet: seclabel=''customer_1:vm_r:nomigrate_t'' init_seclabel=''customer_1:vm_r:nomigrate_t_building'' Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/misc/xsm-flask.txt | 2 + tools/flask/policy/policy/modules/xen/xen.if | 56 +++++++++++++++++++++------- tools/flask/policy/policy/modules/xen/xen.te | 10 +++++ 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt index 6b0d327..0778a28 100644 --- a/docs/misc/xsm-flask.txt +++ b/docs/misc/xsm-flask.txt @@ -60,6 +60,8 @@ that can be used without dom0 disaggregation. The main types for domUs are: - domU_t is a domain that can communicate with any other domU_t - isolated_domU_t can only communicate with dom0 - prot_domU_t is a domain type whose creation can be disabled with a boolean + - nomigrate_t is a domain that must be created via the nomigrate_t_building + type, and whose memory cannot be read by dom0 once created HVM domains with stubdomain device models use two types (one per domain): - domHVM_t is an HVM domain that uses a stubdomain device model diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index 87ef165..4de99c8 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -9,24 +9,47 @@ # Declare a type as a domain type, and allow basic domain setup define(`declare_domain'', ` type $1, domain_type`''ifelse(`$#'', `1'', `'', `,shift($@)''); + type $1_channel, event_type; + type_transition $1 domain_type:event $1_channel; allow $1 $1:grant { query setup }; allow $1 $1:mmu { adjust physmap map_read map_write stat pinpage }; allow $1 $1:hvm { getparam setparam }; '') -# create_domain(priv, target) -# Allow a domain to be created -define(`create_domain'', ` +# declare_build_label(type) +# Declare a paired _building type for the given domain type +define(`declare_build_label'', ` + type $1_building, domain_type; + type_transition $1_building domain_type:event $1_channel; + allow $1_building $1 : domain transition; +'') + +define(`create_domain_common'', ` allow $1 $2:domain { create max_vcpus setdomainmaxmem setaddrsize - getdomaininfo hypercall setvcpucontext scheduler - unpause getvcpuinfo getvcpuextstate getaddrsize - getvcpuaffinity }; + getdomaininfo hypercall setvcpucontext setextvcpucontext + scheduler getvcpuinfo getvcpuextstate getaddrsize + getvcpuaffinity setvcpuaffinity }; allow $1 $2:security check_context; allow $1 $2:shadow enable; allow $1 $2:mmu {map_read map_write adjust memorymap physmap pinpage}; allow $1 $2:grant setup; - allow $1 $2:hvm { cacheattr getparam hvmctl irqlevel pciroute setparam pcilevel trackdirtyvram }; - allow $1 $2_$1_channel:event create; + allow $1 $2:hvm { cacheattr getparam hvmctl irqlevel pciroute sethvmc setparam pcilevel trackdirtyvram }; +'') + +# create_domain(priv, target) +# Allow a domain to be created directly +define(`create_domain'', ` + create_domain_common($1, $2) + allow $1 $2_channel:event create; +'') + +# create_domain_build_label(priv, target) +# Allow a domain to be created via its domain build label +define(`create_domain_build_label'', ` + create_domain_common($1, $2_building) + allow $1 $2_channel:event create; + allow $1 $2_building:domain2 relabelfrom; + allow $1 $2:domain2 relabelto; '') # manage_domain(priv, target) @@ -37,6 +60,15 @@ define(`manage_domain'', ` setvcpuaffinity setdomainmaxmem }; '') +# migrate_domain_out(priv, target) +# Allow creation of a snapshot or migration image from a domain +# (inbound migration is the same as domain creation) +define(`migrate_domain_out'', ` + allow $1 $2:hvm { gethvmc getparam irqlevel }; + allow $1 $2:mmu { stat pageinfo map_read }; + allow $1 $2:domain { getaddrsize getvcpucontext getextvcpucontext getvcpuextstate pause destroy }; +'') + ################################################################################ # # Inter-domain communication @@ -47,8 +79,6 @@ define(`manage_domain'', ` # This allows an event channel to be created from domains with labels # <source> to <dest> and will label it <chan-label> define(`create_channel'', ` - type $3, event_type; - type_transition $1 $2:event $3; allow $1 $3:event { create send status }; allow $3 $2:event { bind }; '') @@ -56,8 +86,8 @@ define(`create_channel'', ` # domain_event_comms(dom1, dom2) # Allow two domain types to communicate using event channels define(`domain_event_comms'', ` - create_channel($1, $2, $1_$2_channel) - create_channel($2, $1, $2_$1_channel) + create_channel($1, $2, $1_channel) + create_channel($2, $1, $2_channel) '') # domain_comms(dom1, dom2) @@ -72,7 +102,7 @@ define(`domain_comms'', ` # Allow a domain types to communicate with others of its type using grants # and event channels (this includes event channels to DOMID_SELF) define(`domain_self_comms'', ` - create_channel($1, $1, $1_self_channel) + create_channel($1, $1, $1_channel) allow $1 $1:grant { map_read map_write copy unmap }; '') diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index f9bc061..40c4c0a 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -90,6 +90,7 @@ create_domain(dom0_t, isolated_domU_t) manage_domain(dom0_t, isolated_domU_t) domain_comms(dom0_t, isolated_domU_t) +# Declare a boolean that denies creation of prot_domU_t domains gen_bool(prot_doms_locked, false) declare_domain(prot_domU_t) if (!prot_doms_locked) { @@ -111,6 +112,15 @@ manage_domain(dom0_t, dm_dom_t) domain_comms(dom0_t, dm_dom_t) device_model(dm_dom_t, domHVM_t) +# nomigrate_t must be built via the nomigrate_t_building label; once built, +# dom0 cannot read its memory. +declare_domain(nomigrate_t) +declare_build_label(nomigrate_t) +create_domain_build_label(dom0_t, nomigrate_t) +manage_domain(dom0_t, nomigrate_t) +domain_comms(dom0_t, nomigrate_t) +domain_self_comms(nomigrate_t) + ############################################################################### # # Device delegation -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 06/18] xsm, arch/x86: add distinct XSM hooks for map/unmap
The xsm_iomem_permission and xsm_ioport_permission hooks are intended to be called by the domain builder, while the calls in arch/x86/domctl.c which control mapping are also performed by the device model. Because of this, they should not use the same XSM hooks. This also adds a missing XSM hook in the unbind IRQ domctl. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/domctl.c | 8 ++++++-- xen/arch/x86/physdev.c | 2 +- xen/include/xsm/xsm.h | 25 ++++++++++++++++++++++--- xen/xsm/dummy.c | 20 +++++++++++++++++++- xen/xsm/flask/hooks.c | 42 ++++++++++++++++++++---------------------- 5 files changed, 68 insertions(+), 29 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 135ea6e..3cb4d97 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -800,6 +800,10 @@ long arch_do_domctl( !irq_access_permitted(current->domain, bind->machine_irq) ) goto unbind_out; + ret = xsm_unbind_pt_irq(d, bind); + if ( ret ) + goto unbind_out; + if ( iommu_enabled ) { spin_lock(&pcidevs_lock); @@ -837,7 +841,7 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) ) break; - ret = xsm_iomem_permission(d, mfn, mfn + nr_mfns - 1, add); + ret = xsm_iomem_mapping(d, mfn, mfn + nr_mfns - 1, add); if ( ret ) { rcu_unlock_domain(d); break; @@ -899,7 +903,7 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) ) break; - ret = xsm_ioport_permission(d, fmp, fmp + np - 1, add); + ret = xsm_ioport_mapping(d, fmp, fmp + np - 1, add); if ( ret ) { rcu_unlock_domain(d); break; diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index b0458fd..e434ff4 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -239,7 +239,7 @@ int physdev_unmap_pirq(domid_t domid, int pirq) if ( !IS_PRIV_FOR(current->domain, d) ) goto free_domain; - ret = xsm_irq_permission(d, domain_pirq_to_irq(d, pirq), 0); + ret = xsm_unmap_domain_pirq(d, domain_pirq_to_irq(d, pirq)); if ( ret ) goto free_domain; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index bef79df..0434c05 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -117,8 +117,10 @@ struct xsm_operations { char *(*show_irq_sid) (int irq); int (*map_domain_pirq) (struct domain *d, int irq, void *data); + int (*unmap_domain_pirq) (struct domain *d, int irq); int (*irq_permission) (struct domain *d, int pirq, uint8_t allow); int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow); + int (*iomem_mapping) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow); int (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access); int (*get_device_group) (uint32_t machine_bdf); @@ -177,11 +179,12 @@ struct xsm_operations { int (*add_to_physmap) (struct domain *d1, struct domain *d2); int (*sendtrigger) (struct domain *d); int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind); - int (*unbind_pt_irq) (struct domain *d); + int (*unbind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind); int (*pin_mem_cacheattr) (struct domain *d); int (*ext_vcpucontext) (struct domain *d, uint32_t cmd); int (*vcpuextstate) (struct domain *d, uint32_t cmd); int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow); + int (*ioport_mapping) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow); #endif }; @@ -495,6 +498,11 @@ static inline int xsm_map_domain_pirq (struct domain *d, int irq, void *data) return xsm_call(map_domain_pirq(d, irq, data)); } +static inline int xsm_unmap_domain_pirq (struct domain *d, int irq) +{ + return xsm_call(unmap_domain_pirq(d, irq)); +} + static inline int xsm_irq_permission (struct domain *d, int pirq, uint8_t allow) { return xsm_call(irq_permission(d, pirq, allow)); @@ -505,6 +513,11 @@ static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e return xsm_call(iomem_permission(d, s, e, allow)); } +static inline int xsm_iomem_mapping (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) +{ + return xsm_call(iomem_mapping(d, s, e, allow)); +} + static inline int xsm_pci_config_permission (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) { return xsm_call(pci_config_permission(d, machine_bdf, start, end, access)); @@ -780,9 +793,10 @@ static inline int xsm_bind_pt_irq(struct domain *d, return xsm_call(bind_pt_irq(d, bind)); } -static inline int xsm_unbind_pt_irq(struct domain *d) +static inline int xsm_unbind_pt_irq(struct domain *d, + struct xen_domctl_bind_pt_irq *bind) { - return xsm_call(unbind_pt_irq(d)); + return xsm_call(unbind_pt_irq(d, bind)); } static inline int xsm_pin_mem_cacheattr(struct domain *d) @@ -803,6 +817,11 @@ static inline int xsm_ioport_permission (struct domain *d, uint32_t s, uint32_t { return xsm_call(ioport_permission(d, s, e, allow)); } + +static inline int xsm_ioport_mapping (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) +{ + return xsm_call(ioport_mapping(d, s, e, allow)); +} #endif /* CONFIG_X86 */ extern struct xsm_operations dummy_xsm_ops; diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 5d35342..fd075c7 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -395,6 +395,11 @@ static int dummy_map_domain_pirq (struct domain *d, int irq, void *data) return 0; } +static int dummy_unmap_domain_pirq (struct domain *d, int irq) +{ + return 0; +} + static int dummy_irq_permission (struct domain *d, int pirq, uint8_t allow) { return 0; @@ -405,6 +410,11 @@ static int dummy_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uin return 0; } +static int dummy_iomem_mapping (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) +{ + return 0; +} + static int dummy_pci_config_permission (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) @@ -585,7 +595,7 @@ static int dummy_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b return 0; } -static int dummy_unbind_pt_irq (struct domain *d) +static int dummy_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) { return 0; } @@ -609,6 +619,11 @@ static int dummy_ioport_permission (struct domain *d, uint32_t s, uint32_t e, ui { return 0; } + +static int dummy_ioport_mapping (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) +{ + return 0; +} #endif struct xsm_operations dummy_xsm_ops; @@ -693,8 +708,10 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, show_irq_sid); set_to_dummy_if_null(ops, map_domain_pirq); + set_to_dummy_if_null(ops, unmap_domain_pirq); set_to_dummy_if_null(ops, irq_permission); set_to_dummy_if_null(ops, iomem_permission); + set_to_dummy_if_null(ops, iomem_mapping); set_to_dummy_if_null(ops, pci_config_permission); set_to_dummy_if_null(ops, get_device_group); @@ -757,5 +774,6 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, ext_vcpucontext); set_to_dummy_if_null(ops, vcpuextstate); set_to_dummy_if_null(ops, ioport_permission); + set_to_dummy_if_null(ops, ioport_mapping); #endif } diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 9262d34..5923710 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -781,43 +781,40 @@ static int flask_map_domain_pirq (struct domain *d, int irq, void *data) return rc; } -static int flask_irq_permission (struct domain *d, int irq, uint8_t access) +static int flask_unmap_domain_pirq (struct domain *d, int irq) { - u32 perm; - u32 rsid; + u32 sid; int rc = -EPERM; - struct domain_security_struct *ssec, *tsec; + struct domain_security_struct *ssec; struct avc_audit_data ad; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, - resource_to_perm(access)); - + rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE); if ( rc ) return rc; - if ( access ) - perm = RESOURCE__ADD_IRQ; - else - perm = RESOURCE__REMOVE_IRQ; - ssec = current->domain->ssid; - tsec = d->ssid; - rc = get_irq_sid(irq, &rsid, &ad); - if ( rc ) - return rc; - - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); + if ( irq >= nr_irqs_gsi ) { + /* TODO support for MSI here */ + return 0; + } else { + rc = get_irq_sid(irq, &sid, &ad); + } if ( rc ) return rc; - if ( access ) - rc = avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, - RESOURCE__USE, &ad); + rc = avc_has_perm(ssec->sid, sid, SECCLASS_RESOURCE, RESOURCE__REMOVE_IRQ, &ad); return rc; } +static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) +{ + /* the PIRQ number is not useful; real IRQ is checked during mapping */ + return domain_has_perm(current->domain, d, SECCLASS_RESOURCE, + resource_to_perm(access)); +} + struct iomem_has_perm_data { struct domain_security_struct *ssec, *tsec; u32 perm; @@ -1507,7 +1504,7 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } -static int flask_unbind_pt_irq (struct domain *d) +static int flask_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) { return domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE); } @@ -1627,6 +1624,7 @@ static struct xsm_operations flask_ops = { .show_irq_sid = flask_show_irq_sid, .map_domain_pirq = flask_map_domain_pirq, + .unmap_domain_pirq = flask_unmap_domain_pirq, .irq_permission = flask_irq_permission, .iomem_permission = flask_iomem_permission, .pci_config_permission = flask_pci_config_permission, -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 07/18] arch/x86: add missing XSM checks to XENPF_ commands
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.te | 4 ++-- xen/arch/x86/platform_hypercall.c | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 40c4c0a..1162153 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -53,8 +53,8 @@ type device_t, resource_type; # ################################################################################ allow dom0_t xen_t:xen { kexec readapic writeapic mtrr_read mtrr_add mtrr_del - scheduler physinfo heap quirk readconsole writeconsole settime - microcode cpupool_op sched_op }; + scheduler physinfo heap quirk readconsole writeconsole settime getcpuinfo + microcode cpupool_op sched_op pm_op }; allow dom0_t xen_t:mmu { memorymap }; allow dom0_t security_t:security { check_context compute_av compute_create compute_member load_policy compute_relabel compute_user setenforce diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index 88880b0..c049db7 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -501,6 +501,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) { struct xenpf_pcpu_version *ver = &op->u.pcpu_version; + ret = xsm_getcpuinfo(); + if ( ret ) + break; + if ( !get_cpu_maps() ) { ret = -EBUSY; @@ -618,6 +622,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) { uint32_t idle_nums; + ret = xsm_pm_op(); + if ( ret ) + break; + switch(op->u.core_parking.type) { case XEN_CORE_PARKING_SET: -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id
Callers that want to prevent use of DOMID_SELF already need to ensure the calling domain does not pass its own domain ID. This removes the need for the caller to manually support DOMID_SELF, which many already do. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/common/domain.c | 3 +++ xen/common/event_channel.c | 3 --- xen/common/grant_table.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xen/common/domain.c b/xen/common/domain.c index 4c5d241..dbbc414 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -400,6 +400,9 @@ struct domain *rcu_lock_domain_by_id(domid_t dom) { struct domain *d = NULL; + if ( dom == DOMID_SELF ) + return rcu_lock_current_domain(); + rcu_read_lock(&domlist_read_lock); for ( d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]); diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 53777f8..988d3ce 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -201,9 +201,6 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind) domid_t rdom = bind->remote_dom; long rc; - if ( rdom == DOMID_SELF ) - rdom = current->domain->domain_id; - if ( (rd = rcu_lock_domain_by_id(rdom)) == NULL ) return -ESRCH; diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 9961e83..fbea67c 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -715,7 +715,7 @@ __gnttab_map_grant_ref( TRACE_1D(TRC_MEM_PAGE_GRANT_MAP, op->dom); mt = &maptrack_entry(lgt, handle); - mt->domid = op->dom; + mt->domid = rd->domain_id; mt->ref = op->ref; mt->flags = op->flags; -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 09/18] xsm/flask: Add checks on the domain performing the set_target operation
The existing domain__set_target check only verifies that the source and target domains can be associated. We also need to check that the privileged domain making this association is allowed to do so. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 2 ++ xen/xsm/flask/hooks.c | 7 +++++++ xen/xsm/flask/include/av_perm_to_string.h | 2 ++ xen/xsm/flask/include/av_permissions.h | 2 ++ 4 files changed, 13 insertions(+) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index c7e29ab..11d02da 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -78,6 +78,8 @@ class domain2 relabelfrom relabelto relabelself + make_priv_for + set_as_target } class hvm diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 5923710..f8aff14 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -637,6 +637,13 @@ static int flask_domain_settime(struct domain *d) static int flask_set_target(struct domain *d, struct domain *e) { + int rc; + rc = domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__MAKE_PRIV_FOR); + if ( rc ) + return rc; + rc = domain_has_perm(current->domain, e, SECCLASS_DOMAIN2, DOMAIN2__SET_AS_TARGET); + if ( rc ) + return rc; return domain_has_perm(d, e, SECCLASS_DOMAIN, DOMAIN__SET_TARGET); } diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index e7e2058..10f8e80 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -64,6 +64,8 @@ S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELFROM, "relabelfrom") S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELTO, "relabelto") S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELSELF, "relabelself") + S_(SECCLASS_DOMAIN2, DOMAIN2__MAKE_PRIV_FOR, "make_priv_for") + S_(SECCLASS_DOMAIN2, DOMAIN2__SET_AS_TARGET, "set_as_target") S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc") S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc") S_(SECCLASS_HVM, HVM__SETPARAM, "setparam") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index cb1c5dc..f7cfee1 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -66,6 +66,8 @@ #define DOMAIN2__RELABELFROM 0x00000001UL #define DOMAIN2__RELABELTO 0x00000002UL #define DOMAIN2__RELABELSELF 0x00000004UL +#define DOMAIN2__MAKE_PRIV_FOR 0x00000008UL +#define DOMAIN2__SET_AS_TARGET 0x00000010UL #define HVM__SETHVMC 0x00000001UL #define HVM__GETHVMC 0x00000002UL -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 10/18] xsm: Add IS_PRIV checks to dummy XSM module
This patch copies IS_PRIV checks into the dummy XSM hooks and makes the dummy hooks the default implementation instead of always returning zero. This patch should not change any functionality regardless of the state of XSM_ENABLE; these newly introduced duplicate checks will be resolved in the next patch. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/include/xsm/dummy.h | 822 ++++++++++++++++++++++++++++++++++++++++++++++++ xen/include/xsm/xsm.h | 52 ++- xen/xsm/dummy.c | 617 +----------------------------------- xen/xsm/xsm_core.c | 2 +- 4 files changed, 848 insertions(+), 645 deletions(-) create mode 100644 xen/include/xsm/dummy.h diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h new file mode 100644 index 0000000..0d849cc --- /dev/null +++ b/xen/include/xsm/dummy.h @@ -0,0 +1,822 @@ +/* + * Default XSM hooks - IS_PRIV and IS_PRIV_FOR checks + * + * Author: Daniel De Graaf <dgdegra@tyhco.nsa.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <xen/sched.h> +#include <xsm/xsm.h> + +static XSM_DEFAULT(void, security_domaininfo)(struct domain *d, + struct xen_domctl_getdomaininfo *info) +{ + return; +} + +static XSM_DEFAULT(int, setvcpucontext)(struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, pausedomain) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, unpausedomain) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resumedomain) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, domain_create)(struct domain *d, u32 ssidref) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, max_vcpus)(struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, destroydomain) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, vcpuaffinity) (int cmd, struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, scheduler) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getdomaininfo) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getvcpucontext) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getvcpuinfo) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, domain_settime) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, set_target) (struct domain *d, struct domain *e) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, domctl)(struct domain *d, int cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, set_virq_handler)(struct domain *d, uint32_t virq) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, tbufcontrol) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, readconsole) (uint32_t clear) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, sched_id) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, setdomainmaxmem) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, setdomainhandle) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, setdebugging) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, perfcontrol) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, debug_keys) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getcpuinfo) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, get_pmstat) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, setpminfo) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, pm_op) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, do_mca) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, availheap) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, alloc_security_domain) (struct domain *d) +{ + return 0; +} + +static XSM_DEFAULT(void, free_security_domain) (struct domain *d) +{ + return; +} + +static XSM_DEFAULT(int, grant_mapref) (struct domain *d1, struct domain *d2, + uint32_t flags) +{ + return 0; +} + +static XSM_DEFAULT(int, grant_unmapref) (struct domain *d1, struct domain *d2) +{ + return 0; +} + +static XSM_DEFAULT(int, grant_setup) (struct domain *d1, struct domain *d2) +{ + if ( d1 != d2 && !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, grant_transfer) (struct domain *d1, struct domain *d2) +{ + return 0; +} + +static XSM_DEFAULT(int, grant_copy) (struct domain *d1, struct domain *d2) +{ + return 0; +} + +static XSM_DEFAULT(int, grant_query_size) (struct domain *d1, struct domain *d2) +{ + if ( d1 != d2 && !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, memory_adjust_reservation) (struct domain *d1, + struct domain *d2) +{ + if ( d1 != d2 && !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, memory_stat_reservation) (struct domain *d1, struct domain *d2) +{ + if ( !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, console_io) (struct domain *d, int cmd) +{ + return 0; +} + +static XSM_DEFAULT(int, profile) (struct domain *d, int op) +{ + return 0; +} + +static XSM_DEFAULT(int, kexec) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, schedop_shutdown) (struct domain *d1, struct domain *d2) +{ + if ( !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, memory_pin_page)(struct domain *d, struct page_info *page) +{ + return 0; +} + +static XSM_DEFAULT(int, evtchn_unbound) (struct domain *d, struct evtchn *chn, + domid_t id2) +{ + if ( current->domain != d && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, evtchn_interdomain) (struct domain *d1, struct evtchn + *chan1, struct domain *d2, struct evtchn *chan2) +{ + return 0; +} + +static XSM_DEFAULT(void, evtchn_close_post) (struct evtchn *chn) +{ + return; +} + +static XSM_DEFAULT(int, evtchn_send) (struct domain *d, struct evtchn *chn) +{ + return 0; +} + +static XSM_DEFAULT(int, evtchn_status) (struct domain *d, struct evtchn *chn) +{ + if ( current->domain != d && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, evtchn_reset) (struct domain *d1, struct domain *d2) +{ + if ( d1 != d2 && !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, alloc_security_evtchn) (struct evtchn *chn) +{ + return 0; +} + +static XSM_DEFAULT(void, free_security_evtchn) (struct evtchn *chn) +{ + return; +} + +static XSM_DEFAULT(char *, show_security_evtchn) (struct domain *d, const struct evtchn *chn) +{ + return NULL; +} + +static XSM_DEFAULT(int, get_pod_target)(struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, set_pod_target)(struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, get_device_group) (uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, test_assign_device) (uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, assign_device) (struct domain *d, uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, deassign_device) (struct domain *d, uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_plug_core) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_unplug_core) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_plug_pci) (uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_unplug_pci) (uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_setup_pci) (uint32_t machine_bdf) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_setup_gsi) (int gsi) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, resource_setup_misc) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, page_offline) (uint32_t cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, lockprof) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, cpupool_op) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, sched_op) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(long, __do_xsm_op)(XEN_GUEST_HANDLE(xsm_op_t) op) +{ + return -ENOSYS; +} + +static XSM_DEFAULT(char *, show_irq_sid) (int irq) +{ + return NULL; +} + +static XSM_DEFAULT(int, map_domain_pirq) (struct domain *d, int irq, void *data) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, unmap_domain_pirq) (struct domain *d, int irq) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, irq_permission) (struct domain *d, int pirq, uint8_t allow) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, iomem_mapping) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, pci_config_permission) (struct domain *d, uint32_t machine_bdf, + uint16_t start, uint16_t end, + uint8_t access) +{ + if ( !IS_PRIV(d) ) + return -EPERM; + return 0; +} + +#ifdef CONFIG_X86 +static XSM_DEFAULT(int, shadow_control) (struct domain *d, uint32_t op) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getpageframeinfo) (struct page_info *page) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getmemlist) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hypercall_init) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hvmcontext) (struct domain *d, uint32_t cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, address_size) (struct domain *d, uint32_t cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, machine_address_size) (struct domain *d, uint32_t cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hvm_param) (struct domain *d, unsigned long op) +{ + if ( current->domain != d && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hvm_set_pci_intx_level) (struct domain *d) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hvm_set_isa_irq_level) (struct domain *d) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hvm_set_pci_link_route) (struct domain *d) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, hvm_inject_msi) (struct domain *d) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, mem_event) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, mem_sharing) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, apic) (struct domain *d, int cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, xen_settime) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, memtype) (uint32_t access) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, microcode) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, physinfo) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, platform_quirk) (uint32_t quirk) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, firmware_info) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, efi_call) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, acpi_sleep) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, change_freq) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, getidletime) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, machine_memory_map) (void) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, domain_memory_map) (struct domain *d) +{ + if ( current->domain != d && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, mmu_normal_update) (struct domain *d, struct domain *t, + struct domain *f, intpte_t fpte) +{ + return 0; +} + +static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, unsigned long mfn) +{ + return 0; +} + +static XSM_DEFAULT(int, update_va_mapping) (struct domain *d, struct domain *f, + l1_pgentry_t pte) +{ + return 0; +} + +static XSM_DEFAULT(int, add_to_physmap) (struct domain *d1, struct domain *d2) +{ + if ( d1 != d2 && !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, remove_from_physmap) (struct domain *d1, struct domain *d2) +{ + if ( d1 != d2 && !IS_PRIV_FOR(d1, d2) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, sendtrigger) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, unbind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, pin_mem_cacheattr) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, ext_vcpucontext) (struct domain *d, uint32_t cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, vcpuextstate) (struct domain *d, uint32_t cmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, ioport_mapping) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + +#endif diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 0434c05..1a9f35b 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -21,11 +21,7 @@ typedef void xsm_op_t; DEFINE_XEN_GUEST_HANDLE(xsm_op_t); -#ifdef XSM_ENABLE - #define xsm_call(fn) xsm_ops->fn -#else - #define xsm_call(fn) 0 -#endif +#define xsm_call(fn) xsm_ops->fn /* policy magic number (defined by XSM_MAGIC) */ typedef u32 xsm_magic_t; @@ -188,8 +184,6 @@ struct xsm_operations { #endif }; -#endif - extern struct xsm_operations *xsm_ops; static inline void xsm_security_domaininfo (struct domain *d, @@ -598,32 +592,11 @@ static inline int xsm_sched_op(void) return xsm_call(sched_op()); } -static inline long __do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) +static inline long xsm___do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) { -#ifdef XSM_ENABLE return xsm_ops->__do_xsm_op(op); -#else - return -ENOSYS; -#endif } -#ifdef XSM_ENABLE -extern int xsm_init(unsigned long *module_map, const multiboot_info_t *mbi, - void *(*bootstrap_map)(const module_t *)); -extern int xsm_policy_init(unsigned long *module_map, - const multiboot_info_t *mbi, - void *(*bootstrap_map)(const module_t *)); -extern int register_xsm(struct xsm_operations *ops); -extern int unregister_xsm(struct xsm_operations *ops); -#else -static inline int xsm_init (unsigned long *module_map, - const multiboot_info_t *mbi, - void *(*bootstrap_map)(const module_t *)) -{ - return 0; -} -#endif - #ifdef CONFIG_X86 static inline int xsm_shadow_control (struct domain *d, uint32_t op) { @@ -824,7 +797,28 @@ static inline int xsm_ioport_mapping (struct domain *d, uint32_t s, uint32_t e, } #endif /* CONFIG_X86 */ +extern int xsm_init(unsigned long *module_map, const multiboot_info_t *mbi, + void *(*bootstrap_map)(const module_t *)); +extern int xsm_policy_init(unsigned long *module_map, + const multiboot_info_t *mbi, + void *(*bootstrap_map)(const module_t *)); +extern int register_xsm(struct xsm_operations *ops); +extern int unregister_xsm(struct xsm_operations *ops); + extern struct xsm_operations dummy_xsm_ops; extern void xsm_fixup_ops(struct xsm_operations *ops); +#else /* XSM_ENABLE */ + +#define XSM_DEFAULT(type, name) inline type xsm_ ## name +#include <xsm/dummy.h> + +static inline int xsm_init (unsigned long *module_map, + const multiboot_info_t *mbi, + void *(*bootstrap_map)(const module_t *)) +{ + return 0; +} +#endif /* XSM_ENABLE */ + #endif /* __XSM_H */ diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index fd075c7..af532b8 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -10,621 +10,8 @@ * as published by the Free Software Foundation. */ -#include <xen/sched.h> -#include <xsm/xsm.h> - -static void dummy_security_domaininfo(struct domain *d, - struct xen_domctl_getdomaininfo *info) -{ - return; -} - -static int dummy_setvcpucontext(struct domain *d) -{ - return 0; -} - -static int dummy_pausedomain (struct domain *d) -{ - return 0; -} - -static int dummy_unpausedomain (struct domain *d) -{ - return 0; -} - -static int dummy_resumedomain (struct domain *d) -{ - return 0; -} - -static int dummy_domain_create(struct domain *d, u32 ssidref) -{ - return 0; -} - -static int dummy_max_vcpus(struct domain *d) -{ - return 0; -} - -static int dummy_destroydomain (struct domain *d) -{ - return 0; -} - -static int dummy_vcpuaffinity (int cmd, struct domain *d) -{ - return 0; -} - -static int dummy_scheduler (struct domain *d) -{ - return 0; -} - -static int dummy_getdomaininfo (struct domain *d) -{ - if ( !IS_PRIV(current->domain) ) - return -EPERM; - return 0; -} - -static int dummy_getvcpucontext (struct domain *d) -{ - return 0; -} - -static int dummy_getvcpuinfo (struct domain *d) -{ - return 0; -} - -static int dummy_domain_settime (struct domain *d) -{ - return 0; -} - -static int dummy_set_target (struct domain *d, struct domain *e) -{ - return 0; -} - -static int dummy_domctl(struct domain *d, int cmd) -{ - return 0; -} - -static int dummy_set_virq_handler(struct domain *d, uint32_t virq) -{ - return 0; -} - -static int dummy_tbufcontrol (void) -{ - return 0; -} - -static int dummy_readconsole (uint32_t clear) -{ - return 0; -} - -static int dummy_sched_id (void) -{ - return 0; -} - -static int dummy_setdomainmaxmem (struct domain *d) -{ - return 0; -} - -static int dummy_setdomainhandle (struct domain *d) -{ - return 0; -} - -static int dummy_setdebugging (struct domain *d) -{ - return 0; -} - -static int dummy_perfcontrol (void) -{ - return 0; -} - -static int dummy_debug_keys (void) -{ - return 0; -} - -static int dummy_getcpuinfo (void) -{ - return 0; -} - -static int dummy_get_pmstat (void) -{ - return 0; -} - -static int dummy_setpminfo (void) -{ - return 0; -} - -static int dummy_pm_op (void) -{ - return 0; -} - -static int dummy_do_mca (void) -{ - return 0; -} - -static int dummy_availheap (void) -{ - return 0; -} - -static int dummy_alloc_security_domain (struct domain *d) -{ - return 0; -} - -static void dummy_free_security_domain (struct domain *d) -{ - return; -} - -static int dummy_grant_mapref (struct domain *d1, struct domain *d2, - uint32_t flags) -{ - return 0; -} - -static int dummy_grant_unmapref (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_grant_setup (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_grant_transfer (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_grant_copy (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_grant_query_size (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_memory_adjust_reservation (struct domain *d1, - struct domain *d2) -{ - return 0; -} - -static int dummy_memory_stat_reservation (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_console_io (struct domain *d, int cmd) -{ - return 0; -} - -static int dummy_profile (struct domain *d, int op) -{ - return 0; -} - -static int dummy_kexec (void) -{ - return 0; -} - -static int dummy_schedop_shutdown (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_memory_pin_page(struct domain *d, struct page_info *page) -{ - return 0; -} - -static int dummy_evtchn_unbound (struct domain *d, struct evtchn *chn, - domid_t id2) -{ - return 0; -} - -static int dummy_evtchn_interdomain (struct domain *d1, struct evtchn - *chan1, struct domain *d2, struct evtchn *chan2) -{ - return 0; -} - -static void dummy_evtchn_close_post (struct evtchn *chn) -{ - return; -} - -static int dummy_evtchn_send (struct domain *d, struct evtchn *chn) -{ - return 0; -} - -static int dummy_evtchn_status (struct domain *d, struct evtchn *chn) -{ - return 0; -} - -static int dummy_evtchn_reset (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_alloc_security_evtchn (struct evtchn *chn) -{ - return 0; -} - -static void dummy_free_security_evtchn (struct evtchn *chn) -{ - return; -} - -static char *dummy_show_security_evtchn (struct domain *d, const struct evtchn *chn) -{ - return NULL; -} - -static int dummy_get_pod_target(struct domain *d) -{ - return 0; -} - -static int dummy_set_pod_target(struct domain *d) -{ - return 0; -} - -static int dummy_get_device_group (uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_test_assign_device (uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_assign_device (struct domain *d, uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_deassign_device (struct domain *d, uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_resource_plug_core (void) -{ - return 0; -} - -static int dummy_resource_unplug_core (void) -{ - return 0; -} - -static int dummy_resource_plug_pci (uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_resource_unplug_pci (uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_resource_setup_pci (uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_resource_setup_gsi (int gsi) -{ - return 0; -} - -static int dummy_resource_setup_misc (void) -{ - return 0; -} - -static int dummy_page_offline (uint32_t cmd) -{ - return 0; -} - -static int dummy_lockprof (void) -{ - return 0; -} - -static int dummy_cpupool_op (void) -{ - return 0; -} - -static int dummy_sched_op (void) -{ - return 0; -} - -static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op) -{ - return -ENOSYS; -} - -static char *dummy_show_irq_sid (int irq) -{ - return NULL; -} - -static int dummy_map_domain_pirq (struct domain *d, int irq, void *data) -{ - return 0; -} - -static int dummy_unmap_domain_pirq (struct domain *d, int irq) -{ - return 0; -} - -static int dummy_irq_permission (struct domain *d, int pirq, uint8_t allow) -{ - return 0; -} - -static int dummy_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) -{ - return 0; -} - -static int dummy_iomem_mapping (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) -{ - return 0; -} - -static int dummy_pci_config_permission (struct domain *d, uint32_t machine_bdf, - uint16_t start, uint16_t end, - uint8_t access) -{ - return 0; -} - -#ifdef CONFIG_X86 -static int dummy_shadow_control (struct domain *d, uint32_t op) -{ - return 0; -} - -static int dummy_getpageframeinfo (struct page_info *page) -{ - return 0; -} - -static int dummy_getmemlist (struct domain *d) -{ - return 0; -} - -static int dummy_hypercall_init (struct domain *d) -{ - return 0; -} - -static int dummy_hvmcontext (struct domain *d, uint32_t cmd) -{ - return 0; -} - -static int dummy_address_size (struct domain *d, uint32_t cmd) -{ - return 0; -} - -static int dummy_machine_address_size (struct domain *d, uint32_t cmd) -{ - return 0; -} - -static int dummy_hvm_param (struct domain *d, unsigned long op) -{ - return 0; -} - -static int dummy_hvm_set_pci_intx_level (struct domain *d) -{ - return 0; -} - -static int dummy_hvm_set_isa_irq_level (struct domain *d) -{ - return 0; -} - -static int dummy_hvm_set_pci_link_route (struct domain *d) -{ - return 0; -} - -static int dummy_hvm_inject_msi (struct domain *d) -{ - return 0; -} - -static int dummy_mem_event (struct domain *d) -{ - return 0; -} - -static int dummy_mem_sharing (struct domain *d) -{ - return 0; -} - -static int dummy_apic (struct domain *d, int cmd) -{ - return 0; -} - -static int dummy_xen_settime (void) -{ - return 0; -} - -static int dummy_memtype (uint32_t access) -{ - return 0; -} - -static int dummy_microcode (void) -{ - return 0; -} - -static int dummy_physinfo (void) -{ - return 0; -} - -static int dummy_platform_quirk (uint32_t quirk) -{ - return 0; -} - -static int dummy_firmware_info (void) -{ - return 0; -} - -static int dummy_efi_call(void) -{ - return 0; -} - -static int dummy_acpi_sleep (void) -{ - return 0; -} - -static int dummy_change_freq (void) -{ - return 0; -} - -static int dummy_getidletime (void) -{ - return 0; -} - -static int dummy_machine_memory_map (void) -{ - return 0; -} - -static int dummy_domain_memory_map (struct domain *d) -{ - return 0; -} - -static int dummy_mmu_normal_update (struct domain *d, struct domain *t, - struct domain *f, intpte_t fpte) -{ - return 0; -} - -static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn) -{ - return 0; -} - -static int dummy_update_va_mapping (struct domain *d, struct domain *f, - l1_pgentry_t pte) -{ - return 0; -} - -static int dummy_add_to_physmap (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_remove_from_physmap (struct domain *d1, struct domain *d2) -{ - return 0; -} - -static int dummy_sendtrigger (struct domain *d) -{ - return 0; -} - -static int dummy_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) -{ - return 0; -} - -static int dummy_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) -{ - return 0; -} - -static int dummy_pin_mem_cacheattr (struct domain *d) -{ - return 0; -} - -static int dummy_ext_vcpucontext (struct domain *d, uint32_t cmd) -{ - return 0; -} - -static int dummy_vcpuextstate (struct domain *d, uint32_t cmd) -{ - return 0; -} - -static int dummy_ioport_permission (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) -{ - return 0; -} - -static int dummy_ioport_mapping (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) -{ - return 0; -} -#endif +#define XSM_DEFAULT(type, name) type dummy_ ## name +#include <xsm/dummy.h> struct xsm_operations dummy_xsm_ops; diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c index 96c8669..c4c85c0 100644 --- a/xen/xsm/xsm_core.c +++ b/xen/xsm/xsm_core.c @@ -113,7 +113,7 @@ int unregister_xsm(struct xsm_operations *ops) long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) { - return __do_xsm_op(op); + return xsm___do_xsm_op(op); } -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 11/18] xen: use XSM instead of IS_PRIV where duplicated
The Xen hypervisor has two basic access control function calls: IS_PRIV and the xsm_* functions. Most privileged operations currently require that both checks succeed, and many times the checks are at different locations in the code. This patch eliminates the explicit and implicit IS_PRIV checks that are duplicated in XSM hooks. When XSM_ENABLE is not defined or when the dummy XSM module is used, this patch should not change any functionality. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/acpi/power.c | 2 +- xen/arch/x86/cpu/mcheck/mce.c | 3 -- xen/arch/x86/domctl.c | 25 ++++++++-- xen/arch/x86/hvm/hvm.c | 96 +++++++++++++++++++-------------------- xen/arch/x86/irq.c | 3 +- xen/arch/x86/mm.c | 25 ++++------ xen/arch/x86/physdev.c | 54 ---------------------- xen/arch/x86/platform_hypercall.c | 3 -- xen/common/domctl.c | 33 ++------------ xen/common/event_channel.c | 18 ++++---- xen/common/grant_table.c | 70 ++++++++-------------------- xen/common/kexec.c | 3 -- xen/common/memory.c | 29 ++++-------- xen/common/schedule.c | 6 --- xen/common/sysctl.c | 3 -- 15 files changed, 119 insertions(+), 254 deletions(-) diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c index 9e1f989..c7b37ef 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -238,7 +238,7 @@ static long enter_state_helper(void *data) */ int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep) { - if ( !IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt_blk.address ) + if ( !acpi_sinfo.pm1a_cnt_blk.address ) return -EPERM; /* Sanity check */ diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c index ed76131..4176bae 100644 --- a/xen/arch/x86/cpu/mcheck/mce.c +++ b/xen/arch/x86/cpu/mcheck/mce.c @@ -1381,9 +1381,6 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u_xen_mc) struct xen_mc_msrinject *mc_msrinject; struct xen_mc_mceinject *mc_mceinject; - if (!IS_PRIV(v->domain) ) - return x86_mcerr(NULL, -EPERM); - ret = xsm_do_mca(); if ( ret ) return x86_mcerr(NULL, ret); diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 3cb4d97..bcb5b2d 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -54,6 +54,26 @@ long arch_do_domctl( switch ( domctl->cmd ) { + /* TODO: the following do not have XSM hooks yet */ + case XEN_DOMCTL_set_cpuid: + case XEN_DOMCTL_suppress_spurious_page_faults: + case XEN_DOMCTL_debug_op: + case XEN_DOMCTL_gettscinfo: + case XEN_DOMCTL_settscinfo: + case XEN_DOMCTL_audit_p2m: + case XEN_DOMCTL_gdbsx_guestmemio: + case XEN_DOMCTL_gdbsx_pausevcpu: + case XEN_DOMCTL_gdbsx_unpausevcpu: + case XEN_DOMCTL_gdbsx_domstatus: + /* getpageframeinfo[23] will leak XEN_DOMCTL_PFINFO_XTAB on target GFNs */ + case XEN_DOMCTL_getpageframeinfo2: + case XEN_DOMCTL_getpageframeinfo3: + if ( !IS_PRIV(current->domain) ) + return -EPERM; + } + + switch ( domctl->cmd ) + { case XEN_DOMCTL_shadow_op: { @@ -795,11 +815,6 @@ long arch_do_domctl( break; bind = &(domctl->u.bind_pt_irq); - ret = -EPERM; - if ( !IS_PRIV(current->domain) && - !irq_access_permitted(current->domain, bind->machine_irq) ) - goto unbind_out; - ret = xsm_unbind_pt_irq(d, bind); if ( ret ) goto unbind_out; diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 22c136b..bec9e57 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3366,12 +3366,12 @@ static int hvmop_set_pci_intx_level( if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) ) return -EINVAL; - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(op.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto out; rc = xsm_hvm_set_pci_intx_level(d); @@ -3531,12 +3531,12 @@ static int hvmop_set_isa_irq_level( if ( op.isa_irq > 15 ) return -EINVAL; - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(op.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto out; rc = xsm_hvm_set_isa_irq_level(d); @@ -3575,12 +3575,12 @@ static int hvmop_set_pci_link_route( if ( (op.link > 3) || (op.isa_irq > 15) ) return -EINVAL; - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(op.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto out; rc = xsm_hvm_set_pci_link_route(d); @@ -3605,9 +3605,9 @@ static int hvmop_inject_msi( if ( copy_from_guest(&op, uop, 1) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(op.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; if ( !is_hvm_domain(d) ) @@ -3702,9 +3702,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( a.index >= HVM_NR_PARAMS ) return -EINVAL; - rc = rcu_lock_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; if ( !is_hvm_domain(d) ) @@ -3948,12 +3948,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto param_fail2; rc = xsm_hvm_param(d, op); @@ -3987,12 +3987,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto param_fail3; rc = xsm_hvm_param(d, op); @@ -4037,9 +4037,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = xsm_hvm_param(d, op); if ( rc ) @@ -4084,12 +4084,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto param_fail4; rc = xsm_hvm_param(d, op); @@ -4163,12 +4163,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto param_fail5; rc = xsm_hvm_param(d, op); @@ -4198,12 +4198,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto param_fail6; rc = xsm_hvm_param(d, op); @@ -4234,9 +4234,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&a, arg, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(a.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(a.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; if ( !is_hvm_domain(d) || !paging_mode_shadow(d) ) @@ -4288,12 +4288,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&tr, arg, 1 ) ) return -EFAULT; - rc = rcu_lock_remote_target_domain_by_id(tr.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(tr.domid); + if ( d == NULL ) + return -ESRCH; rc = -EINVAL; - if ( !is_hvm_domain(d) ) + if ( d == current->domain || !is_hvm_domain(d) ) goto param_fail8; rc = xsm_hvm_param(d, op); diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 78a02e3..33ce710 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -1853,8 +1853,7 @@ int map_domain_pirq( ASSERT(spin_is_locked(&d->event_lock)); if ( !IS_PRIV(current->domain) && - !(IS_PRIV_FOR(current->domain, d) && - irq_access_permitted(current->domain, pirq))) + !irq_access_permitted(current->domain, pirq)) return -EPERM; if ( pirq < 0 || pirq >= d->nr_pirqs || irq < 0 || irq >= nr_irqs ) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 9338575..1b352df 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4673,9 +4673,9 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&xatp, arg, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(xatp.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(xatp.domid); + if ( d == NULL ) + return -ESRCH; if ( xsm_add_to_physmap(current->domain, d) ) { @@ -4712,9 +4712,9 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) if ( fmap.map.nr_entries > E820MAX ) return -EINVAL; - rc = rcu_lock_target_domain_by_id(fmap.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(fmap.domid); + if ( d == NULL ) + return -ESRCH; rc = xsm_domain_memory_map(d); if ( rc ) @@ -4790,9 +4790,6 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) XEN_GUEST_HANDLE(e820entry_t) buffer; unsigned int i; - if ( !IS_PRIV(current->domain) ) - return -EINVAL; - rc = xsm_machine_memory_map(); if ( rc ) return rc; @@ -4868,16 +4865,12 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) struct domain *d; struct p2m_domain *p2m; - /* Support DOMID_SELF? */ - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( copy_from_guest(&target, arg, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(target.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(target.domid); + if ( d == NULL ) + return -ESRCH; if ( op == XENMEM_set_pod_target ) rc = xsm_set_pod_target(d); diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index e434ff4..0841a7a 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -106,12 +106,6 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p, goto free_domain; } - if ( !IS_PRIV_FOR(current->domain, d) ) - { - ret = -EPERM; - goto free_domain; - } - /* Verify or get irq. */ switch ( type ) { @@ -235,10 +229,6 @@ int physdev_unmap_pirq(domid_t domid, int pirq) goto free_domain; } - ret = -EPERM; - if ( !IS_PRIV_FOR(current->domain, d) ) - goto free_domain; - ret = xsm_unmap_domain_pirq(d, domain_pirq_to_irq(d, pirq)); if ( ret ) goto free_domain; @@ -430,9 +420,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) ret = -EFAULT; if ( copy_from_guest(&apic, arg, 1) != 0 ) break; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; ret = xsm_apic(v->domain, cmd); if ( ret ) break; @@ -447,9 +434,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) ret = -EFAULT; if ( copy_from_guest(&apic, arg, 1) != 0 ) break; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; ret = xsm_apic(v->domain, cmd); if ( ret ) break; @@ -464,10 +448,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&irq_op, arg, 1) != 0 ) break; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; - /* Vector is only used by hypervisor, and dom0 shouldn''t touch it in its world, return irq_op.irq as the vecotr, and make this hypercall dummy, and also defer the vector @@ -514,9 +494,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) case PHYSDEVOP_manage_pci_add: { struct physdev_manage_pci manage_pci; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; ret = -EFAULT; if ( copy_from_guest(&manage_pci, arg, 1) != 0 ) break; @@ -527,9 +504,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) case PHYSDEVOP_manage_pci_remove: { struct physdev_manage_pci manage_pci; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; ret = -EFAULT; if ( copy_from_guest(&manage_pci, arg, 1) != 0 ) break; @@ -542,10 +516,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) struct physdev_manage_pci_ext manage_pci_ext; struct pci_dev_info pdev_info; - ret = -EPERM; - if ( !IS_PRIV(current->domain) ) - break; - ret = -EFAULT; if ( copy_from_guest(&manage_pci_ext, arg, 1) != 0 ) break; @@ -568,10 +538,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) struct physdev_pci_device_add add; struct pci_dev_info pdev_info; - ret = -EPERM; - if ( !IS_PRIV(current->domain) ) - break; - ret = -EFAULT; if ( copy_from_guest(&add, arg, 1) != 0 ) break; @@ -592,10 +558,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) case PHYSDEVOP_pci_device_remove: { struct physdev_pci_device dev; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; - ret = -EFAULT; if ( copy_from_guest(&dev, arg, 1) != 0 ) break; @@ -608,10 +570,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) case PHYSDEVOP_pci_mmcfg_reserved: { struct physdev_pci_mmcfg_reserved info; - ret = -EPERM; - if ( !IS_PRIV(current->domain) ) - break; - ret = xsm_resource_setup_misc(); if ( ret ) break; @@ -630,10 +588,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) struct physdev_restore_msi restore_msi; struct pci_dev *pdev; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; - ret = -EFAULT; if ( copy_from_guest(&restore_msi, arg, 1) != 0 ) break; @@ -649,10 +603,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) struct physdev_pci_device dev; struct pci_dev *pdev; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; - ret = -EFAULT; if ( copy_from_guest(&dev, arg, 1) != 0 ) break; @@ -667,10 +617,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) case PHYSDEVOP_setup_gsi: { struct physdev_setup_gsi setup_gsi; - ret = -EPERM; - if ( !IS_PRIV(v->domain) ) - break; - ret = -EFAULT; if ( copy_from_guest(&setup_gsi, arg, 1) != 0 ) break; diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index c049db7..f3304a2 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -65,9 +65,6 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) ret_t ret = 0; struct xen_platform_op curop, *op = &curop; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( copy_from_guest(op, u_xenpf_op, 1) ) return -EFAULT; diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 7ca6b08..db152b1 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -249,33 +249,6 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION ) return -EACCES; - switch ( op->cmd ) - { - case XEN_DOMCTL_ioport_mapping: - case XEN_DOMCTL_memory_mapping: - case XEN_DOMCTL_bind_pt_irq: - case XEN_DOMCTL_unbind_pt_irq: { - struct domain *d; - bool_t is_priv = IS_PRIV(current->domain); - if ( !is_priv && ((d = rcu_lock_domain_by_id(op->domain)) != NULL) ) - { - is_priv = IS_PRIV_FOR(current->domain, d); - rcu_unlock_domain(d); - } - if ( !is_priv ) - return -EPERM; - break; - } -#ifdef XSM_ENABLE - case XEN_DOMCTL_getdomaininfo: - break; -#endif - default: - if ( !IS_PRIV(current->domain) ) - return -EPERM; - break; - } - if ( !domctl_lock_acquire() ) return hypercall_create_continuation( __HYPERVISOR_domctl, "h", u_domctl); @@ -889,10 +862,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) if ( d == NULL ) break; - if ( pirq >= d->nr_pirqs ) - ret = -EINVAL; - else if ( xsm_irq_permission(d, pirq, allow) ) + if ( xsm_irq_permission(d, pirq, allow) ) ret = -EPERM; + else if ( pirq >= d->nr_pirqs ) + ret = -EINVAL; else if ( allow ) ret = irq_permit_access(d, pirq); else diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 988d3ce..625748b 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -165,9 +165,9 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc) domid_t dom = alloc->dom; long rc; - rc = rcu_lock_target_domain_by_id(dom, &d); - if ( rc ) - return rc; + d = rcu_lock_domain_by_id(dom); + if ( d == NULL ) + return -ESRCH; spin_lock(&d->event_lock); @@ -795,9 +795,9 @@ static long evtchn_status(evtchn_status_t *status) struct evtchn *chn; long rc = 0; - rc = rcu_lock_target_domain_by_id(dom, &d); - if ( rc ) - return rc; + d = rcu_lock_domain_by_id(dom); + if ( d == NULL ) + return -ESRCH; spin_lock(&d->event_lock); @@ -947,9 +947,9 @@ static long evtchn_reset(evtchn_reset_t *r) struct domain *d; int i, rc; - rc = rcu_lock_target_domain_by_id(dom, &d); - if ( rc ) - return rc; + d = rcu_lock_domain_by_id(dom); + if ( d == NULL ) + return -ESRCH; rc = xsm_evtchn_reset(current->domain, d); if ( rc ) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index fbea67c..5760937 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -1261,7 +1261,6 @@ gnttab_setup_table( struct grant_table *gt; int i; unsigned long gmfn; - domid_t dom; if ( count != 1 ) return -EINVAL; @@ -1281,25 +1280,12 @@ gnttab_setup_table( goto out1; } - dom = op.dom; - if ( dom == DOMID_SELF ) + d = rcu_lock_domain_by_id(op.dom); + if ( d == NULL ) { - d = rcu_lock_current_domain(); - } - 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 out1; - } - - if ( unlikely(!IS_PRIV_FOR(current->domain, d)) ) - { - op.status = GNTST_permission_denied; - goto out2; - } + gdprintk(XENLOG_INFO, "Bad domid %d.\n", op.dom); + op.status = GNTST_bad_domain; + goto out2; } if ( xsm_grant_setup(current->domain, d) ) @@ -1352,7 +1338,6 @@ gnttab_query_size( { struct gnttab_query_size op; struct domain *d; - domid_t dom; int rc; if ( count != 1 ) @@ -1364,25 +1349,12 @@ gnttab_query_size( return -EFAULT; } - dom = op.dom; - if ( dom == DOMID_SELF ) - { - d = rcu_lock_current_domain(); - } - else + d = rcu_lock_domain_by_id(op.dom); + if ( d == NULL ) { - 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; - } + gdprintk(XENLOG_INFO, "Bad domid %d.\n", op.dom); + op.status = GNTST_bad_domain; + goto query_out; } rc = xsm_grant_query_size(current->domain, d); @@ -2240,15 +2212,10 @@ gnttab_get_status_frames(XEN_GUEST_HANDLE(gnttab_get_status_frames_t) uop, return -EFAULT; } - rc = rcu_lock_target_domain_by_id(op.dom, &d); - if ( rc < 0 ) + d = rcu_lock_domain_by_id(op.dom); + if ( d == NULL ) { - if ( rc == -ESRCH ) - op.status = GNTST_bad_domain; - else if ( rc == -EPERM ) - op.status = GNTST_permission_denied; - else - op.status = GNTST_general_error; + op.status = GNTST_bad_domain; goto out1; } rc = xsm_grant_setup(current->domain, d); @@ -2298,14 +2265,15 @@ gnttab_get_version(XEN_GUEST_HANDLE(gnttab_get_version_t uop)) if ( copy_from_guest(&op, uop, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(op.dom, &d); - if ( rc < 0 ) - return rc; + d = rcu_lock_domain_by_id(op.dom); + if ( d == NULL ) + return -ESRCH; - if ( xsm_grant_query_size(current->domain, d) ) + rc = xsm_grant_query_size(current->domain, d); + if ( rc ) { rcu_unlock_domain(d); - return -EPERM; + return rc; } op.version = d->grant_table->gt_version; diff --git a/xen/common/kexec.c b/xen/common/kexec.c index 09a5624..22bca20 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -851,9 +851,6 @@ int do_kexec_op_internal(unsigned long op, XEN_GUEST_HANDLE(void) uarg, unsigned long flags; int ret = -EINVAL; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - ret = xsm_kexec(); if ( ret ) return ret; diff --git a/xen/common/memory.c b/xen/common/memory.c index 5d64cb6..77969d9 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -583,20 +583,9 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) && (reservation.mem_flags & XENMEMF_populate_on_demand) ) args.memflags |= MEMF_populate_on_demand; - if ( likely(reservation.domid == DOMID_SELF) ) - { - d = rcu_lock_current_domain(); - } - else - { - if ( (d = rcu_lock_domain_by_id(reservation.domid)) == NULL ) - return start_extent; - if ( !IS_PRIV_FOR(current->domain, d) ) - { - rcu_unlock_domain(d); - return start_extent; - } - } + d = rcu_lock_domain_by_id(reservation.domid); + if ( d == NULL ) + return start_extent; args.domain = d; rc = xsm_memory_adjust_reservation(current->domain, d); @@ -644,9 +633,9 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&domid, arg, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(domid, &d); - if ( rc ) - return rc; + d = rcu_lock_domain_by_id(domid); + if ( d == NULL ) + return -ESRCH; rc = xsm_memory_stat_reservation(current->domain, d); if ( rc ) @@ -682,9 +671,9 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&xrfp, arg, 1) ) return -EFAULT; - rc = rcu_lock_target_domain_by_id(xrfp.domid, &d); - if ( rc != 0 ) - return rc; + d = rcu_lock_domain_by_id(xrfp.domid); + if ( d == NULL ) + return -ESRCH; if ( xsm_remove_from_physmap(current->domain, d) ) { diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 0854f55..e38e6e2 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -919,12 +919,6 @@ 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 ) { diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index ea68278..2cea0c3 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -33,9 +33,6 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) struct xen_sysctl curop, *op = &curop; static DEFINE_SPINLOCK(sysctl_lock); - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( copy_from_guest(op, u_sysctl, 1) ) return -EFAULT; -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 12/18] xsm: Add missing domctl and mem_sharing hooks
This patch adds new XSM hooks to cover the 12 domctls that were not previously covered by an XSM hook, and splits up the mem_sharing and mem_event XSM hooks to better cover what the code is doing. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 5 + tools/flask/policy/policy/modules/xen/xen.if | 2 + xen/arch/x86/domctl.c | 125 +++++++++++++++---------- xen/arch/x86/mm/mem_event.c | 45 ++++----- xen/arch/x86/mm/mem_sharing.c | 23 ++++- xen/include/asm-x86/mem_event.h | 1 - xen/include/xsm/dummy.h | 65 ++++++++++++- xen/include/xsm/xsm.h | 62 +++++++++++- xen/xsm/dummy.c | 11 ++- xen/xsm/flask/hooks.c | 62 +++++++++++- xen/xsm/flask/include/av_perm_to_string.h | 5 + xen/xsm/flask/include/av_permissions.h | 5 + 12 files changed, 318 insertions(+), 93 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 11d02da..28b8ada 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -80,6 +80,9 @@ class domain2 relabelself make_priv_for set_as_target + set_cpuid + gettsc + settsc } class hvm @@ -97,6 +100,8 @@ class hvm hvmctl mem_event mem_sharing + share_mem + audit_p2m } class event diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index 4de99c8..f9bd757 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -29,6 +29,7 @@ define(`create_domain_common'', ` getdomaininfo hypercall setvcpucontext setextvcpucontext scheduler getvcpuinfo getvcpuextstate getaddrsize getvcpuaffinity setvcpuaffinity }; + allow $1 $2:domain2 { set_cpuid settsc }; allow $1 $2:security check_context; allow $1 $2:shadow enable; allow $1 $2:mmu {map_read map_write adjust memorymap physmap pinpage}; @@ -67,6 +68,7 @@ define(`migrate_domain_out'', ` allow $1 $2:hvm { gethvmc getparam irqlevel }; allow $1 $2:mmu { stat pageinfo map_read }; allow $1 $2:domain { getaddrsize getvcpucontext getextvcpucontext getvcpuextstate pause destroy }; + allow $1 $2:domain2 gettsc; '') ################################################################################ diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index bcb5b2d..95f34d2 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -54,26 +54,6 @@ long arch_do_domctl( switch ( domctl->cmd ) { - /* TODO: the following do not have XSM hooks yet */ - case XEN_DOMCTL_set_cpuid: - case XEN_DOMCTL_suppress_spurious_page_faults: - case XEN_DOMCTL_debug_op: - case XEN_DOMCTL_gettscinfo: - case XEN_DOMCTL_settscinfo: - case XEN_DOMCTL_audit_p2m: - case XEN_DOMCTL_gdbsx_guestmemio: - case XEN_DOMCTL_gdbsx_pausevcpu: - case XEN_DOMCTL_gdbsx_unpausevcpu: - case XEN_DOMCTL_gdbsx_domstatus: - /* getpageframeinfo[23] will leak XEN_DOMCTL_PFINFO_XTAB on target GFNs */ - case XEN_DOMCTL_getpageframeinfo2: - case XEN_DOMCTL_getpageframeinfo3: - if ( !IS_PRIV(current->domain) ) - return -EPERM; - } - - switch ( domctl->cmd ) - { case XEN_DOMCTL_shadow_op: { @@ -190,6 +170,13 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) ) break; + ret = xsm_getpageframeinfo_domain(d); + if ( ret ) + { + rcu_unlock_domain(d); + break; + } + if ( unlikely(num > 1024) || unlikely(num != domctl->u.getpageframeinfo3.num) ) { @@ -287,6 +274,13 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) ) break; + ret = xsm_getpageframeinfo_domain(d); + if ( ret ) + { + rcu_unlock_domain(d); + break; + } + if ( unlikely(num > 1024) ) { ret = -E2BIG; @@ -1106,6 +1100,10 @@ long arch_do_domctl( if ( d == NULL ) break; + ret = xsm_set_cpuid(d); + if ( ret ) + goto set_cpuid_out; + for ( i = 0; i < MAX_CPUID_INPUT; i++ ) { cpuid = &d->arch.cpuids[i]; @@ -1129,6 +1127,7 @@ long arch_do_domctl( ret = 0; } + set_cpuid_out: rcu_unlock_domain(d); } break; @@ -1143,6 +1142,10 @@ long arch_do_domctl( if ( d == NULL ) break; + ret = xsm_gettscinfo(d); + if ( ret ) + goto gettscinfo_out; + domain_pause(d); tsc_get_info(d, &info.tsc_mode, &info.elapsed_nsec, @@ -1154,6 +1157,7 @@ long arch_do_domctl( ret = 0; domain_unpause(d); + gettscinfo_out: rcu_unlock_domain(d); } break; @@ -1167,15 +1171,20 @@ long arch_do_domctl( if ( d == NULL ) break; + ret = xsm_settscinfo(d); + if ( ret ) + goto settscinfo_out; + domain_pause(d); tsc_set_info(d, domctl->u.tsc_info.info.tsc_mode, domctl->u.tsc_info.info.elapsed_nsec, domctl->u.tsc_info.info.gtsc_khz, domctl->u.tsc_info.info.incarnation); domain_unpause(d); + ret = 0; + settscinfo_out: rcu_unlock_domain(d); - ret = 0; } break; @@ -1187,9 +1196,10 @@ long arch_do_domctl( d = rcu_lock_domain_by_id(domctl->domain); if ( d != NULL ) { - d->arch.suppress_spurious_page_faults = 1; + ret = xsm_domctl(d, domctl->cmd); + if ( !ret ) + d->arch.suppress_spurious_page_faults = 1; rcu_unlock_domain(d); - ret = 0; } } break; @@ -1204,6 +1214,10 @@ long arch_do_domctl( if ( d == NULL ) break; + ret = xsm_debug_op(d); + if ( ret ) + goto debug_op_out; + ret = -EINVAL; if ( (domctl->u.debug_op.vcpu >= d->max_vcpus) || ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) ) @@ -1228,6 +1242,10 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; + ret = xsm_debug_op(d); + if ( ret ) + goto gdbsx_guestmemio_out; + domctl->u.gdbsx_guest_memio.remain domctl->u.gdbsx_guest_memio.len; @@ -1235,6 +1253,7 @@ long arch_do_domctl( if ( !ret && copy_to_guest(u_domctl, domctl, 1) ) ret = -EFAULT; + gdbsx_guestmemio_out: rcu_unlock_domain(d); } break; @@ -1248,21 +1267,20 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; + ret = xsm_debug_op(d); + if ( ret ) + goto gdbsx_pausevcpu_out; + ret = -EBUSY; if ( !d->is_paused_by_controller ) - { - rcu_unlock_domain(d); - break; - } + goto gdbsx_pausevcpu_out; ret = -EINVAL; if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= MAX_VIRT_CPUS || (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL ) - { - rcu_unlock_domain(d); - break; - } + goto gdbsx_pausevcpu_out; vcpu_pause(v); ret = 0; + gdbsx_pausevcpu_out: rcu_unlock_domain(d); } break; @@ -1276,23 +1294,22 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; + ret = xsm_debug_op(d); + if ( ret ) + goto gdbsx_unpausevcpu_out; + ret = -EBUSY; if ( !d->is_paused_by_controller ) - { - rcu_unlock_domain(d); - break; - } + goto gdbsx_unpausevcpu_out; ret = -EINVAL; if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= MAX_VIRT_CPUS || (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL ) - { - rcu_unlock_domain(d); - break; - } + goto gdbsx_unpausevcpu_out; if ( !atomic_read(&v->pause_count) ) printk("WARN: Unpausing vcpu:%d which is not paused\n", v->vcpu_id); vcpu_unpause(v); ret = 0; + gdbsx_unpausevcpu_out: rcu_unlock_domain(d); } break; @@ -1306,6 +1323,10 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; + ret = xsm_debug_op(d); + if ( ret ) + goto gdbsx_domstatus_out; + domctl->u.gdbsx_domstatus.vcpu_id = -1; domctl->u.gdbsx_domstatus.paused = d->is_paused_by_controller; if ( domctl->u.gdbsx_domstatus.paused ) @@ -1325,6 +1346,7 @@ long arch_do_domctl( ret = 0; if ( copy_to_guest(u_domctl, domctl, 1) ) ret = -EFAULT; + gdbsx_domstatus_out: rcu_unlock_domain(d); } break; @@ -1464,10 +1486,8 @@ long arch_do_domctl( d = rcu_lock_domain_by_id(domctl->domain); if ( d != NULL ) { - ret = xsm_mem_event(d); - if ( !ret ) - ret = mem_event_domctl(d, &domctl->u.mem_event_op, - guest_handle_cast(u_domctl, void)); + ret = mem_event_domctl(d, &domctl->u.mem_event_op, + guest_handle_cast(u_domctl, void)); rcu_unlock_domain(d); copy_to_guest(u_domctl, domctl, 1); } @@ -1496,16 +1516,19 @@ long arch_do_domctl( { struct domain *d; - ret = rcu_lock_remote_target_domain_by_id(domctl->domain, &d); - if ( ret != 0 ) + d = rcu_lock_domain_by_id(domctl->domain); + if ( d == NULL ) break; - audit_p2m(d, - &domctl->u.audit_p2m.orphans, - &domctl->u.audit_p2m.m2p_bad, - &domctl->u.audit_p2m.p2m_bad); + ret = xsm_audit_p2m(d); + if ( !ret ) + audit_p2m(d, + &domctl->u.audit_p2m.orphans, + &domctl->u.audit_p2m.m2p_bad, + &domctl->u.audit_p2m.p2m_bad); + rcu_unlock_domain(d); - if ( copy_to_guest(u_domctl, domctl, 1) ) + if ( !ret && copy_to_guest(u_domctl, domctl, 1) ) ret = -EFAULT; } break; @@ -1524,7 +1547,7 @@ long arch_do_domctl( d = rcu_lock_domain_by_id(domctl->domain); if ( d != NULL ) { - ret = xsm_mem_event(d); + ret = xsm_mem_event_setup(d); if ( !ret ) { p2m = p2m_get_hostp2m(d); p2m->access_required = domctl->u.access_required.access_required; diff --git a/xen/arch/x86/mm/mem_event.c b/xen/arch/x86/mm/mem_event.c index d728889..a5b02d9 100644 --- a/xen/arch/x86/mm/mem_event.c +++ b/xen/arch/x86/mm/mem_event.c @@ -29,6 +29,7 @@ #include <asm/mem_paging.h> #include <asm/mem_access.h> #include <asm/mem_sharing.h> +#include <xsm/xsm.h> /* for public/io/ring.h macros */ #define xen_mb() mb() @@ -439,34 +440,22 @@ static void mem_sharing_notification(struct vcpu *v, unsigned int port) mem_sharing_sharing_resume(v->domain); } -struct domain *get_mem_event_op_target(uint32_t domain, int *rc) -{ - struct domain *d; - - /* Get the target domain */ - *rc = rcu_lock_remote_target_domain_by_id(domain, &d); - if ( *rc != 0 ) - return NULL; - - /* Not dying? */ - if ( d->is_dying ) - { - rcu_unlock_domain(d); - *rc = -EINVAL; - return NULL; - } - - return d; -} - int do_mem_event_op(int op, uint32_t domain, void *arg) { int ret; struct domain *d; - d = get_mem_event_op_target(domain, &ret); + d = rcu_lock_domain_by_id(domain); if ( !d ) - return ret; + return -ESRCH; + + ret = -EINVAL; + if ( d->is_dying || d == current->domain ) + goto out; + + ret = xsm_mem_event_op(d, op); + if ( ret ) + goto out; switch (op) { @@ -483,6 +472,7 @@ int do_mem_event_op(int op, uint32_t domain, void *arg) ret = -ENOSYS; } + out: rcu_unlock_domain(d); return ret; } @@ -516,6 +506,10 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, { int rc; + rc = xsm_mem_event_control(d, mec->mode, mec->op); + if ( rc ) + return rc; + if ( unlikely(d == current->domain) ) { gdprintk(XENLOG_INFO, "Tried to do a memory event op on itself.\n"); @@ -537,13 +531,6 @@ int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, return -EINVAL; } - /* TODO: XSM hook */ -#if 0 - rc = xsm_mem_event_control(d, mec->op); - if ( rc ) - return rc; -#endif - rc = -ENOSYS; switch ( mec->mode ) diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c index 5103285..a7e6c5c 100644 --- a/xen/arch/x86/mm/mem_sharing.c +++ b/xen/arch/x86/mm/mem_sharing.c @@ -34,6 +34,7 @@ #include <asm/atomic.h> #include <xen/rcupdate.h> #include <asm/event.h> +#include <xsm/xsm.h> #include "mm-locks.h" @@ -1345,11 +1346,18 @@ int mem_sharing_memop(struct domain *d, xen_mem_sharing_op_t *mec) if ( !mem_sharing_enabled(d) ) return -EINVAL; - cd = get_mem_event_op_target(mec->u.share.client_domain, &rc); + cd = rcu_lock_domain_by_id(mec->u.share.client_domain); if ( !cd ) + return -ESRCH; + + rc = xsm_mem_sharing_op(d, cd, mec->op); + if ( rc ) + { + rcu_unlock_domain(cd); return rc; + } - if ( !mem_sharing_enabled(cd) ) + if ( cd == current->domain || !mem_sharing_enabled(cd) ) { rcu_unlock_domain(cd); return -EINVAL; @@ -1401,11 +1409,18 @@ int mem_sharing_memop(struct domain *d, xen_mem_sharing_op_t *mec) if ( !mem_sharing_enabled(d) ) return -EINVAL; - cd = get_mem_event_op_target(mec->u.share.client_domain, &rc); + cd = rcu_lock_domain_by_id(mec->u.share.client_domain); if ( !cd ) + return -ESRCH; + + rc = xsm_mem_sharing_op(d, cd, mec->op); + if ( rc ) + { + rcu_unlock_domain(cd); return rc; + } - if ( !mem_sharing_enabled(cd) ) + if ( cd == current->domain || !mem_sharing_enabled(cd) ) { rcu_unlock_domain(cd); return -EINVAL; diff --git a/xen/include/asm-x86/mem_event.h b/xen/include/asm-x86/mem_event.h index 23d71c1..448be4f 100644 --- a/xen/include/asm-x86/mem_event.h +++ b/xen/include/asm-x86/mem_event.h @@ -62,7 +62,6 @@ void mem_event_put_request(struct domain *d, struct mem_event_domain *med, int mem_event_get_response(struct domain *d, struct mem_event_domain *med, mem_event_response_t *rsp); -struct domain *get_mem_event_op_target(uint32_t domain, int *rc); int do_mem_event_op(int op, uint32_t domain, void *arg); int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, XEN_GUEST_HANDLE(void) u_domctl); diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index 0d849cc..c71c08b 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -171,6 +171,13 @@ static XSM_DEFAULT(int, setdebugging) (struct domain *d) return 0; } +static XSM_DEFAULT(int, debug_op) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + static XSM_DEFAULT(int, perfcontrol) (void) { if ( !IS_PRIV(current->domain) ) @@ -557,6 +564,34 @@ static XSM_DEFAULT(int, getpageframeinfo) (struct page_info *page) return 0; } +static XSM_DEFAULT(int, getpageframeinfo_domain) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, set_cpuid) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, gettscinfo) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, settscinfo) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + static XSM_DEFAULT(int, getmemlist) (struct domain *d) { if ( !IS_PRIV(current->domain) ) @@ -627,13 +662,27 @@ static XSM_DEFAULT(int, hvm_inject_msi) (struct domain *d) return 0; } -static XSM_DEFAULT(int, mem_event) (struct domain *d) +static XSM_DEFAULT(int, mem_event_setup) (struct domain *d) { if ( !IS_PRIV(current->domain) ) return -EPERM; return 0; } +static XSM_DEFAULT(int, mem_event_control) (struct domain *d, int mode, int op) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, mem_event_op) (struct domain *d, int op) +{ + if ( !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + static XSM_DEFAULT(int, mem_sharing) (struct domain *d) { if ( !IS_PRIV(current->domain) ) @@ -641,6 +690,20 @@ static XSM_DEFAULT(int, mem_sharing) (struct domain *d) return 0; } +static XSM_DEFAULT(int, mem_sharing_op) (struct domain *d, struct domain *cd, int op) +{ + if ( !IS_PRIV_FOR(current->domain, cd) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, audit_p2m) (struct domain *d) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + static XSM_DEFAULT(int, apic) (struct domain *d, int cmd) { if ( !IS_PRIV(current->domain) ) diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 1a9f35b..b473b54 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -67,6 +67,7 @@ struct xsm_operations { int (*setdomainmaxmem) (struct domain *d); int (*setdomainhandle) (struct domain *d); int (*setdebugging) (struct domain *d); + int (*debug_op) (struct domain *d); int (*perfcontrol) (void); int (*debug_keys) (void); int (*getcpuinfo) (void); @@ -142,6 +143,10 @@ struct xsm_operations { #ifdef CONFIG_X86 int (*shadow_control) (struct domain *d, uint32_t op); int (*getpageframeinfo) (struct page_info *page); + int (*getpageframeinfo_domain) (struct domain *d); + int (*set_cpuid) (struct domain *d); + int (*gettscinfo) (struct domain *d); + int (*settscinfo) (struct domain *d); int (*getmemlist) (struct domain *d); int (*hypercall_init) (struct domain *d); int (*hvmcontext) (struct domain *d, uint32_t op); @@ -152,8 +157,12 @@ struct xsm_operations { int (*hvm_set_isa_irq_level) (struct domain *d); int (*hvm_set_pci_link_route) (struct domain *d); int (*hvm_inject_msi) (struct domain *d); - int (*mem_event) (struct domain *d); + int (*mem_event_setup) (struct domain *d); + int (*mem_event_control) (struct domain *d, int mode, int op); + int (*mem_event_op) (struct domain *d, int op); int (*mem_sharing) (struct domain *d); + int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op); + int (*audit_p2m) (struct domain *d); int (*apic) (struct domain *d, int cmd); int (*xen_settime) (void); int (*memtype) (uint32_t access); @@ -302,6 +311,11 @@ static inline int xsm_setdebugging (struct domain *d) return xsm_call(setdebugging(d)); } +static inline int xsm_debug_op (struct domain *d) +{ + return xsm_call(debug_op(d)); +} + static inline int xsm_perfcontrol (void) { return xsm_call(perfcontrol()); @@ -329,7 +343,7 @@ static inline int xsm_get_pmstat(void) static inline int xsm_setpminfo(void) { - return xsm_call(setpminfo()); + return xsm_call(setpminfo()); } static inline int xsm_pm_op(void) @@ -608,6 +622,26 @@ static inline int xsm_getpageframeinfo (struct page_info *page) return xsm_call(getpageframeinfo(page)); } +static inline int xsm_getpageframeinfo_domain (struct domain *d) +{ + return xsm_call(getpageframeinfo_domain(d)); +} + +static inline int xsm_set_cpuid (struct domain *d) +{ + return xsm_call(set_cpuid(d)); +} + +static inline int xsm_gettscinfo (struct domain *d) +{ + return xsm_call(gettscinfo(d)); +} + +static inline int xsm_settscinfo (struct domain *d) +{ + return xsm_call(settscinfo(d)); +} + static inline int xsm_getmemlist (struct domain *d) { return xsm_call(getmemlist(d)); @@ -658,9 +692,19 @@ static inline int xsm_hvm_inject_msi (struct domain *d) return xsm_call(hvm_inject_msi(d)); } -static inline int xsm_mem_event (struct domain *d) +static inline int xsm_mem_event_setup (struct domain *d) +{ + return xsm_call(mem_event_setup(d)); +} + +static inline int xsm_mem_event_control (struct domain *d, int mode, int op) +{ + return xsm_call(mem_event_control(d, mode, op)); +} + +static inline int xsm_mem_event_op (struct domain *d, int op) { - return xsm_call(mem_event(d)); + return xsm_call(mem_event_op(d, op)); } static inline int xsm_mem_sharing (struct domain *d) @@ -668,6 +712,16 @@ static inline int xsm_mem_sharing (struct domain *d) return xsm_call(mem_sharing(d)); } +static inline int xsm_mem_sharing_op (struct domain *d, struct domain *cd, int op) +{ + return xsm_call(mem_sharing_op(d, cd, op)); +} + +static inline int xsm_audit_p2m (struct domain *d) +{ + return xsm_call(audit_p2m(d)); +} + static inline int xsm_apic (struct domain *d, int cmd) { return xsm_call(apic(d, cmd)); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index af532b8..09935d8 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -51,6 +51,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, setdomainmaxmem); set_to_dummy_if_null(ops, setdomainhandle); set_to_dummy_if_null(ops, setdebugging); + set_to_dummy_if_null(ops, debug_op); set_to_dummy_if_null(ops, perfcontrol); set_to_dummy_if_null(ops, debug_keys); set_to_dummy_if_null(ops, getcpuinfo); @@ -124,6 +125,10 @@ void xsm_fixup_ops (struct xsm_operations *ops) #ifdef CONFIG_X86 set_to_dummy_if_null(ops, shadow_control); set_to_dummy_if_null(ops, getpageframeinfo); + set_to_dummy_if_null(ops, getpageframeinfo_domain); + set_to_dummy_if_null(ops, set_cpuid); + set_to_dummy_if_null(ops, gettscinfo); + set_to_dummy_if_null(ops, settscinfo); set_to_dummy_if_null(ops, getmemlist); set_to_dummy_if_null(ops, hypercall_init); set_to_dummy_if_null(ops, hvmcontext); @@ -134,8 +139,12 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, hvm_set_isa_irq_level); set_to_dummy_if_null(ops, hvm_set_pci_link_route); set_to_dummy_if_null(ops, hvm_inject_msi); - set_to_dummy_if_null(ops, mem_event); + set_to_dummy_if_null(ops, mem_event_setup); + set_to_dummy_if_null(ops, mem_event_control); + set_to_dummy_if_null(ops, mem_event_op); set_to_dummy_if_null(ops, mem_sharing); + set_to_dummy_if_null(ops, mem_sharing_op); + set_to_dummy_if_null(ops, audit_p2m); set_to_dummy_if_null(ops, apic); set_to_dummy_if_null(ops, xen_settime); set_to_dummy_if_null(ops, memtype); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index f8aff14..4f71604 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -695,6 +695,12 @@ static int flask_setdebugging(struct domain *d) DOMAIN__SETDEBUGGING); } +static int flask_debug_op(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, + DOMAIN__SETDEBUGGING); +} + static int flask_debug_keys(void) { return domain_has_xen(current->domain, XEN__DEBUG); @@ -1111,6 +1117,26 @@ static int flask_getpageframeinfo(struct page_info *page) return avc_has_perm(dsec->sid, tsid, SECCLASS_MMU, MMU__PAGEINFO, NULL); } +static int flask_getpageframeinfo_domain(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGEINFO); +} + +static int flask_set_cpuid(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID); +} + +static int flask_gettscinfo(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__GETTSC); +} + +static int flask_settscinfo(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__SETTSC); +} + static int flask_getmemlist(struct domain *d) { return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGELIST); @@ -1201,7 +1227,17 @@ static int flask_hvm_set_pci_link_route(struct domain *d) return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCIROUTE); } -static int flask_mem_event(struct domain *d) +static int flask_mem_event_setup(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); +} + +static int flask_mem_event_control(struct domain *d, int mode, int op) +{ + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); +} + +static int flask_mem_event_op(struct domain *d, int op) { return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); } @@ -1211,6 +1247,19 @@ static int flask_mem_sharing(struct domain *d) return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_SHARING); } +static int flask_mem_sharing_op(struct domain *d, struct domain *cd, int op) +{ + int rc = domain_has_perm(current->domain, cd, SECCLASS_HVM, HVM__MEM_SHARING); + if ( rc ) + return rc; + return domain_has_perm(d, cd, SECCLASS_HVM, HVM__SHARE_MEM); +} + +static int flask_audit_p2m(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__AUDIT_P2M); +} + static int flask_apic(struct domain *d, int cmd) { u32 perm; @@ -1586,6 +1635,7 @@ static struct xsm_operations flask_ops = { .setdomainmaxmem = flask_setdomainmaxmem, .setdomainhandle = flask_setdomainhandle, .setdebugging = flask_setdebugging, + .debug_op = flask_debug_op, .perfcontrol = flask_perfcontrol, .debug_keys = flask_debug_keys, .getcpuinfo = flask_getcpuinfo, @@ -1654,6 +1704,10 @@ static struct xsm_operations flask_ops = { #ifdef CONFIG_X86 .shadow_control = flask_shadow_control, .getpageframeinfo = flask_getpageframeinfo, + .getpageframeinfo_domain = flask_getpageframeinfo_domain, + .set_cpuid = flask_set_cpuid, + .gettscinfo = flask_gettscinfo, + .settscinfo = flask_settscinfo, .getmemlist = flask_getmemlist, .hypercall_init = flask_hypercall_init, .hvmcontext = flask_hvmcontext, @@ -1662,8 +1716,12 @@ static struct xsm_operations flask_ops = { .hvm_set_pci_intx_level = flask_hvm_set_pci_intx_level, .hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level, .hvm_set_pci_link_route = flask_hvm_set_pci_link_route, - .mem_event = flask_mem_event, + .mem_event_setup = flask_mem_event_setup, + .mem_event_control = flask_mem_event_control, + .mem_event_op = flask_mem_event_op, .mem_sharing = flask_mem_sharing, + .mem_sharing_op = flask_mem_sharing_op, + .audit_p2m = flask_audit_p2m, .apic = flask_apic, .xen_settime = flask_xen_settime, .memtype = flask_memtype, diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 10f8e80..997f098 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -66,6 +66,9 @@ S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELSELF, "relabelself") S_(SECCLASS_DOMAIN2, DOMAIN2__MAKE_PRIV_FOR, "make_priv_for") S_(SECCLASS_DOMAIN2, DOMAIN2__SET_AS_TARGET, "set_as_target") + S_(SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID, "set_cpuid") + S_(SECCLASS_DOMAIN2, DOMAIN2__GETTSC, "gettsc") + S_(SECCLASS_DOMAIN2, DOMAIN2__SETTSC, "settsc") S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc") S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc") S_(SECCLASS_HVM, HVM__SETPARAM, "setparam") @@ -79,6 +82,8 @@ S_(SECCLASS_HVM, HVM__HVMCTL, "hvmctl") S_(SECCLASS_HVM, HVM__MEM_EVENT, "mem_event") S_(SECCLASS_HVM, HVM__MEM_SHARING, "mem_sharing") + S_(SECCLASS_HVM, HVM__SHARE_MEM, "share_mem") + S_(SECCLASS_HVM, HVM__AUDIT_P2M, "audit_p2m") S_(SECCLASS_EVENT, EVENT__BIND, "bind") S_(SECCLASS_EVENT, EVENT__SEND, "send") S_(SECCLASS_EVENT, EVENT__STATUS, "status") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index f7cfee1..8596a55 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -68,6 +68,9 @@ #define DOMAIN2__RELABELSELF 0x00000004UL #define DOMAIN2__MAKE_PRIV_FOR 0x00000008UL #define DOMAIN2__SET_AS_TARGET 0x00000010UL +#define DOMAIN2__SET_CPUID 0x00000020UL +#define DOMAIN2__GETTSC 0x00000040UL +#define DOMAIN2__SETTSC 0x00000080UL #define HVM__SETHVMC 0x00000001UL #define HVM__GETHVMC 0x00000002UL @@ -82,6 +85,8 @@ #define HVM__HVMCTL 0x00000400UL #define HVM__MEM_EVENT 0x00000800UL #define HVM__MEM_SHARING 0x00001000UL +#define HVM__SHARE_MEM 0x00002000UL +#define HVM__AUDIT_P2M 0x00004000UL #define EVENT__BIND 0x00000001UL #define EVENT__SEND 0x00000002UL -- 1.7.11.2
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 1 + xen/common/tmem.c | 10 +++++----- xen/include/xen/tmem_xen.h | 5 ----- xen/include/xsm/dummy.h | 7 +++++++ xen/include/xsm/xsm.h | 6 ++++++ xen/xsm/dummy.c | 1 + xen/xsm/flask/hooks.c | 6 ++++++ xen/xsm/flask/include/av_perm_to_string.h | 1 + xen/xsm/flask/include/av_permissions.h | 1 + 9 files changed, 28 insertions(+), 10 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 28b8ada..2986b40 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -35,6 +35,7 @@ class xen lockprof cpupool_op sched_op + tmem_op } class domain diff --git a/xen/common/tmem.c b/xen/common/tmem.c index dd276df..164098f 100644 --- a/xen/common/tmem.c +++ b/xen/common/tmem.c @@ -23,6 +23,7 @@ #include <xen/radix-tree.h> #include <xen/list.h> #include <xen/init.h> +#include <xsm/xsm.h> #define EXPORT /* indicates code other modules are dependent upon */ #define FORWARD @@ -2539,11 +2540,10 @@ static NOINLINE int do_tmem_control(struct tmem_op *op) uint32_t subop = op->u.ctrl.subop; OID *oidp = (OID *)(&op->u.ctrl.oid[0]); - if (!tmh_current_is_privileged()) - { - /* don''t fail... mystery: sometimes dom0 fails here */ - /* return -EPERM; */ - } + ret = xsm_tmem_control(subop); + if ( ret ) + return ret; + switch(subop) { case TMEMC_THAW: diff --git a/xen/include/xen/tmem_xen.h b/xen/include/xen/tmem_xen.h index 4a35760..f248128 100644 --- a/xen/include/xen/tmem_xen.h +++ b/xen/include/xen/tmem_xen.h @@ -344,11 +344,6 @@ static inline bool_t tmh_set_client_from_id( return rc; } -static inline bool_t tmh_current_is_privileged(void) -{ - return IS_PRIV(current->domain); -} - static inline uint8_t tmh_get_first_byte(pfp_t *pfp) { void *p = __map_domain_page(pfp); diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index c71c08b..d796a33 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -495,6 +495,13 @@ static XSM_DEFAULT(int, sched_op) (void) return 0; } +static XSM_DEFAULT(int, tmem_control) (uint32_t subcmd) +{ + if ( !IS_PRIV(current->domain) ) + return -EPERM; + return 0; +} + static XSM_DEFAULT(long, __do_xsm_op)(XEN_GUEST_HANDLE(xsm_op_t) op) { return -ENOSYS; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index b473b54..ee613a7 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -137,6 +137,7 @@ struct xsm_operations { int (*lockprof)(void); int (*cpupool_op)(void); int (*sched_op)(void); + int (*tmem_control)(uint32_t subop); long (*__do_xsm_op) (XEN_GUEST_HANDLE(xsm_op_t) op); @@ -606,6 +607,11 @@ static inline int xsm_sched_op(void) return xsm_call(sched_op()); } +static inline int xsm_tmem_control(uint32_t subop) +{ + return xsm_call(tmem_control(subop)); +} + static inline long xsm___do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) { return xsm_ops->__do_xsm_op(op); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 09935d8..aebe333 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -119,6 +119,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, lockprof); set_to_dummy_if_null(ops, cpupool_op); set_to_dummy_if_null(ops, sched_op); + set_to_dummy_if_null(ops, tmem_control); set_to_dummy_if_null(ops, __do_xsm_op); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 4f71604..be5c3ad 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -1022,6 +1022,11 @@ static inline int flask_sched_op(void) return domain_has_xen(current->domain, XEN__SCHED_OP); } +static inline int flask_tmem_control(uint32_t subcmd) +{ + return domain_has_xen(current->domain, XEN__TMEM_OP); +} + static int flask_perfcontrol(void) { return domain_has_xen(current->domain, XEN__PERFCONTROL); @@ -1698,6 +1703,7 @@ static struct xsm_operations flask_ops = { .lockprof = flask_lockprof, .cpupool_op = flask_cpupool_op, .sched_op = flask_sched_op, + .tmem_control = flask_tmem_control, .__do_xsm_op = do_flask_op, diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 997f098..5d5a45a 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -29,6 +29,7 @@ S_(SECCLASS_XEN, XEN__LOCKPROF, "lockprof") S_(SECCLASS_XEN, XEN__CPUPOOL_OP, "cpupool_op") S_(SECCLASS_XEN, XEN__SCHED_OP, "sched_op") + S_(SECCLASS_XEN, XEN__TMEM_OP, "tmem_op") S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUCONTEXT, "setvcpucontext") S_(SECCLASS_DOMAIN, DOMAIN__PAUSE, "pause") S_(SECCLASS_DOMAIN, DOMAIN__UNPAUSE, "unpause") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index 8596a55..e6d6a6d 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -29,6 +29,7 @@ #define XEN__LOCKPROF 0x08000000UL #define XEN__CPUPOOL_OP 0x10000000UL #define XEN__SCHED_OP 0x20000000UL +#define XEN__TMEM_OP 0x40000000UL #define DOMAIN__SETVCPUCONTEXT 0x00000001UL #define DOMAIN__PAUSE 0x00000002UL -- 1.7.11.2
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/include/xsm/xsm.h | 260 +++++++++++++++++++++++++------------------------- 1 file changed, 129 insertions(+), 131 deletions(-) diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index ee613a7..fa9f50e 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -21,8 +21,6 @@ typedef void xsm_op_t; DEFINE_XEN_GUEST_HANDLE(xsm_op_t); -#define xsm_call(fn) xsm_ops->fn - /* policy magic number (defined by XSM_MAGIC) */ typedef u32 xsm_magic_t; #ifndef XSM_MAGIC @@ -199,417 +197,417 @@ extern struct xsm_operations *xsm_ops; static inline void xsm_security_domaininfo (struct domain *d, struct xen_domctl_getdomaininfo *info) { - (void)xsm_call(security_domaininfo(d, info)); + xsm_ops->security_domaininfo(d, info); } static inline int xsm_setvcpucontext(struct domain *d) { - return xsm_call(setvcpucontext(d)); + return xsm_ops->setvcpucontext(d); } static inline int xsm_pausedomain (struct domain *d) { - return xsm_call(pausedomain(d)); + return xsm_ops->pausedomain(d); } static inline int xsm_unpausedomain (struct domain *d) { - return xsm_call(unpausedomain(d)); + return xsm_ops->unpausedomain(d); } static inline int xsm_resumedomain (struct domain *d) { - return xsm_call(resumedomain(d)); + return xsm_ops->resumedomain(d); } static inline int xsm_domain_create (struct domain *d, u32 ssidref) { - return xsm_call(domain_create(d, ssidref)); + return xsm_ops->domain_create(d, ssidref); } static inline int xsm_max_vcpus(struct domain *d) { - return xsm_call(max_vcpus(d)); + return xsm_ops->max_vcpus(d); } static inline int xsm_destroydomain (struct domain *d) { - return xsm_call(destroydomain(d)); + return xsm_ops->destroydomain(d); } static inline int xsm_vcpuaffinity (int cmd, struct domain *d) { - return xsm_call(vcpuaffinity(cmd, d)); + return xsm_ops->vcpuaffinity(cmd, d); } static inline int xsm_scheduler (struct domain *d) { - return xsm_call(scheduler(d)); + return xsm_ops->scheduler(d); } static inline int xsm_getdomaininfo (struct domain *d) { - return xsm_call(getdomaininfo(d)); + return xsm_ops->getdomaininfo(d); } static inline int xsm_getvcpucontext (struct domain *d) { - return xsm_call(getvcpucontext(d)); + return xsm_ops->getvcpucontext(d); } static inline int xsm_getvcpuinfo (struct domain *d) { - return xsm_call(getvcpuinfo(d)); + return xsm_ops->getvcpuinfo(d); } static inline int xsm_domain_settime (struct domain *d) { - return xsm_call(domain_settime(d)); + return xsm_ops->domain_settime(d); } static inline int xsm_set_target (struct domain *d, struct domain *e) { - return xsm_call(set_target(d, e)); + return xsm_ops->set_target(d, e); } static inline int xsm_domctl (struct domain *d, int cmd) { - return xsm_call(domctl(d, cmd)); + return xsm_ops->domctl(d, cmd); } static inline int xsm_set_virq_handler (struct domain *d, uint32_t virq) { - return xsm_call(set_virq_handler(d, virq)); + return xsm_ops->set_virq_handler(d, virq); } static inline int xsm_tbufcontrol (void) { - return xsm_call(tbufcontrol()); + return xsm_ops->tbufcontrol(); } static inline int xsm_readconsole (uint32_t clear) { - return xsm_call(readconsole(clear)); + return xsm_ops->readconsole(clear); } static inline int xsm_sched_id (void) { - return xsm_call(sched_id()); + return xsm_ops->sched_id(); } static inline int xsm_setdomainmaxmem (struct domain *d) { - return xsm_call(setdomainmaxmem(d)); + return xsm_ops->setdomainmaxmem(d); } static inline int xsm_setdomainhandle (struct domain *d) { - return xsm_call(setdomainhandle(d)); + return xsm_ops->setdomainhandle(d); } static inline int xsm_setdebugging (struct domain *d) { - return xsm_call(setdebugging(d)); + return xsm_ops->setdebugging(d); } static inline int xsm_debug_op (struct domain *d) { - return xsm_call(debug_op(d)); + return xsm_ops->debug_op(d); } static inline int xsm_perfcontrol (void) { - return xsm_call(perfcontrol()); + return xsm_ops->perfcontrol(); } static inline int xsm_debug_keys (void) { - return xsm_call(debug_keys()); + return xsm_ops->debug_keys(); } static inline int xsm_availheap (void) { - return xsm_call(availheap()); + return xsm_ops->availheap(); } static inline int xsm_getcpuinfo (void) { - return xsm_call(getcpuinfo()); + return xsm_ops->getcpuinfo(); } static inline int xsm_get_pmstat(void) { - return xsm_call(get_pmstat()); + return xsm_ops->get_pmstat(); } static inline int xsm_setpminfo(void) { - return xsm_call(setpminfo()); + return xsm_ops->setpminfo(); } static inline int xsm_pm_op(void) { - return xsm_call(pm_op()); + return xsm_ops->pm_op(); } static inline int xsm_do_mca(void) { - return xsm_call(do_mca()); + return xsm_ops->do_mca(); } static inline int xsm_evtchn_unbound (struct domain *d1, struct evtchn *chn, domid_t id2) { - return xsm_call(evtchn_unbound(d1, chn, id2)); + return xsm_ops->evtchn_unbound(d1, chn, id2); } static inline int xsm_evtchn_interdomain (struct domain *d1, struct evtchn *chan1, struct domain *d2, struct evtchn *chan2) { - return xsm_call(evtchn_interdomain(d1, chan1, d2, chan2)); + return xsm_ops->evtchn_interdomain(d1, chan1, d2, chan2); } static inline void xsm_evtchn_close_post (struct evtchn *chn) { - (void)xsm_call(evtchn_close_post(chn)); + xsm_ops->evtchn_close_post(chn); } static inline int xsm_evtchn_send (struct domain *d, struct evtchn *chn) { - return xsm_call(evtchn_send(d, chn)); + return xsm_ops->evtchn_send(d, chn); } static inline int xsm_evtchn_status (struct domain *d, struct evtchn *chn) { - return xsm_call(evtchn_status(d, chn)); + return xsm_ops->evtchn_status(d, chn); } static inline int xsm_evtchn_reset (struct domain *d1, struct domain *d2) { - return xsm_call(evtchn_reset(d1, d2)); + return xsm_ops->evtchn_reset(d1, d2); } static inline int xsm_grant_mapref (struct domain *d1, struct domain *d2, uint32_t flags) { - return xsm_call(grant_mapref(d1, d2, flags)); + return xsm_ops->grant_mapref(d1, d2, flags); } static inline int xsm_grant_unmapref (struct domain *d1, struct domain *d2) { - return xsm_call(grant_unmapref(d1, d2)); + return xsm_ops->grant_unmapref(d1, d2); } static inline int xsm_grant_setup (struct domain *d1, struct domain *d2) { - return xsm_call(grant_setup(d1, d2)); + return xsm_ops->grant_setup(d1, d2); } static inline int xsm_grant_transfer (struct domain *d1, struct domain *d2) { - return xsm_call(grant_transfer(d1, d2)); + return xsm_ops->grant_transfer(d1, d2); } static inline int xsm_grant_copy (struct domain *d1, struct domain *d2) { - return xsm_call(grant_copy(d1, d2)); + return xsm_ops->grant_copy(d1, d2); } static inline int xsm_grant_query_size (struct domain *d1, struct domain *d2) { - return xsm_call(grant_query_size(d1, d2)); + return xsm_ops->grant_query_size(d1, d2); } static inline int xsm_alloc_security_domain (struct domain *d) { - return xsm_call(alloc_security_domain(d)); + return xsm_ops->alloc_security_domain(d); } static inline void xsm_free_security_domain (struct domain *d) { - (void)xsm_call(free_security_domain(d)); + xsm_ops->free_security_domain(d); } static inline int xsm_alloc_security_evtchn (struct evtchn *chn) { - return xsm_call(alloc_security_evtchn(chn)); + return xsm_ops->alloc_security_evtchn(chn); } static inline void xsm_free_security_evtchn (struct evtchn *chn) { - (void)xsm_call(free_security_evtchn(chn)); + xsm_ops->free_security_evtchn(chn); } static inline char *xsm_show_security_evtchn (struct domain *d, const struct evtchn *chn) { - return xsm_call(show_security_evtchn(d, chn)); + return xsm_ops->show_security_evtchn(d, chn); } static inline int xsm_get_pod_target (struct domain *d) { - return xsm_call(get_pod_target(d)); + return xsm_ops->get_pod_target(d); } static inline int xsm_set_pod_target (struct domain *d) { - return xsm_call(set_pod_target(d)); + return xsm_ops->set_pod_target(d); } static inline int xsm_memory_adjust_reservation (struct domain *d1, struct domain *d2) { - return xsm_call(memory_adjust_reservation(d1, d2)); + return xsm_ops->memory_adjust_reservation(d1, d2); } static inline int xsm_memory_stat_reservation (struct domain *d1, struct domain *d2) { - return xsm_call(memory_stat_reservation(d1, d2)); + return xsm_ops->memory_stat_reservation(d1, d2); } static inline int xsm_memory_pin_page(struct domain *d, struct page_info *page) { - return xsm_call(memory_pin_page(d, page)); + return xsm_ops->memory_pin_page(d, page); } static inline int xsm_remove_from_physmap(struct domain *d1, struct domain *d2) { - return xsm_call(remove_from_physmap(d1, d2)); + return xsm_ops->remove_from_physmap(d1, d2); } static inline int xsm_console_io (struct domain *d, int cmd) { - return xsm_call(console_io(d, cmd)); + return xsm_ops->console_io(d, cmd); } static inline int xsm_profile (struct domain *d, int op) { - return xsm_call(profile(d, op)); + return xsm_ops->profile(d, op); } static inline int xsm_kexec (void) { - return xsm_call(kexec()); + return xsm_ops->kexec(); } static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2) { - return xsm_call(schedop_shutdown(d1, d2)); + return xsm_ops->schedop_shutdown(d1, d2); } static inline char *xsm_show_irq_sid (int irq) { - return xsm_call(show_irq_sid(irq)); + return xsm_ops->show_irq_sid(irq); } static inline int xsm_map_domain_pirq (struct domain *d, int irq, void *data) { - return xsm_call(map_domain_pirq(d, irq, data)); + return xsm_ops->map_domain_pirq(d, irq, data); } static inline int xsm_unmap_domain_pirq (struct domain *d, int irq) { - return xsm_call(unmap_domain_pirq(d, irq)); + return xsm_ops->unmap_domain_pirq(d, irq); } static inline int xsm_irq_permission (struct domain *d, int pirq, uint8_t allow) { - return xsm_call(irq_permission(d, pirq, allow)); + return xsm_ops->irq_permission(d, pirq, allow); } static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) { - return xsm_call(iomem_permission(d, s, e, allow)); + return xsm_ops->iomem_permission(d, s, e, allow); } static inline int xsm_iomem_mapping (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) { - return xsm_call(iomem_mapping(d, s, e, allow)); + return xsm_ops->iomem_mapping(d, s, e, allow); } static inline int xsm_pci_config_permission (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) { - return xsm_call(pci_config_permission(d, machine_bdf, start, end, access)); + return xsm_ops->pci_config_permission(d, machine_bdf, start, end, access); } static inline int xsm_get_device_group(uint32_t machine_bdf) { - return xsm_call(get_device_group(machine_bdf)); + return xsm_ops->get_device_group(machine_bdf); } static inline int xsm_test_assign_device(uint32_t machine_bdf) { - return xsm_call(test_assign_device(machine_bdf)); + return xsm_ops->test_assign_device(machine_bdf); } static inline int xsm_assign_device(struct domain *d, uint32_t machine_bdf) { - return xsm_call(assign_device(d, machine_bdf)); + return xsm_ops->assign_device(d, machine_bdf); } static inline int xsm_deassign_device(struct domain *d, uint32_t machine_bdf) { - return xsm_call(deassign_device(d, machine_bdf)); + return xsm_ops->deassign_device(d, machine_bdf); } static inline int xsm_resource_plug_pci (uint32_t machine_bdf) { - return xsm_call(resource_plug_pci(machine_bdf)); + return xsm_ops->resource_plug_pci(machine_bdf); } static inline int xsm_resource_unplug_pci (uint32_t machine_bdf) { - return xsm_call(resource_unplug_pci(machine_bdf)); + return xsm_ops->resource_unplug_pci(machine_bdf); } static inline int xsm_resource_plug_core (void) { - return xsm_call(resource_plug_core()); + return xsm_ops->resource_plug_core(); } static inline int xsm_resource_unplug_core (void) { - return xsm_call(resource_unplug_core()); + return xsm_ops->resource_unplug_core(); } static inline int xsm_resource_setup_pci (uint32_t machine_bdf) { - return xsm_call(resource_setup_pci(machine_bdf)); + return xsm_ops->resource_setup_pci(machine_bdf); } static inline int xsm_resource_setup_gsi (int gsi) { - return xsm_call(resource_setup_gsi(gsi)); + return xsm_ops->resource_setup_gsi(gsi); } static inline int xsm_resource_setup_misc (void) { - return xsm_call(resource_setup_misc()); + return xsm_ops->resource_setup_misc(); } static inline int xsm_page_offline(uint32_t cmd) { - return xsm_call(page_offline(cmd)); + return xsm_ops->page_offline(cmd); } static inline int xsm_lockprof(void) { - return xsm_call(lockprof()); + return xsm_ops->lockprof(); } static inline int xsm_cpupool_op(void) { - return xsm_call(cpupool_op()); + return xsm_ops->cpupool_op(); } static inline int xsm_sched_op(void) { - return xsm_call(sched_op()); + return xsm_ops->sched_op(); } static inline int xsm_tmem_control(uint32_t subop) { - return xsm_call(tmem_control(subop)); + return xsm_ops->tmem_control(subop); } static inline long xsm___do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) @@ -620,240 +618,240 @@ static inline long xsm___do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) #ifdef CONFIG_X86 static inline int xsm_shadow_control (struct domain *d, uint32_t op) { - return xsm_call(shadow_control(d, op)); + return xsm_ops->shadow_control(d, op); } static inline int xsm_getpageframeinfo (struct page_info *page) { - return xsm_call(getpageframeinfo(page)); + return xsm_ops->getpageframeinfo(page); } static inline int xsm_getpageframeinfo_domain (struct domain *d) { - return xsm_call(getpageframeinfo_domain(d)); + return xsm_ops->getpageframeinfo_domain(d); } static inline int xsm_set_cpuid (struct domain *d) { - return xsm_call(set_cpuid(d)); + return xsm_ops->set_cpuid(d); } static inline int xsm_gettscinfo (struct domain *d) { - return xsm_call(gettscinfo(d)); + return xsm_ops->gettscinfo(d); } static inline int xsm_settscinfo (struct domain *d) { - return xsm_call(settscinfo(d)); + return xsm_ops->settscinfo(d); } static inline int xsm_getmemlist (struct domain *d) { - return xsm_call(getmemlist(d)); + return xsm_ops->getmemlist(d); } static inline int xsm_hypercall_init (struct domain *d) { - return xsm_call(hypercall_init(d)); + return xsm_ops->hypercall_init(d); } static inline int xsm_hvmcontext (struct domain *d, uint32_t cmd) { - return xsm_call(hvmcontext(d, cmd)); + return xsm_ops->hvmcontext(d, cmd); } static inline int xsm_address_size (struct domain *d, uint32_t cmd) { - return xsm_call(address_size(d, cmd)); + return xsm_ops->address_size(d, cmd); } static inline int xsm_machine_address_size (struct domain *d, uint32_t cmd) { - return xsm_call(machine_address_size(d, cmd)); + return xsm_ops->machine_address_size(d, cmd); } static inline int xsm_hvm_param (struct domain *d, unsigned long op) { - return xsm_call(hvm_param(d, op)); + return xsm_ops->hvm_param(d, op); } static inline int xsm_hvm_set_pci_intx_level (struct domain *d) { - return xsm_call(hvm_set_pci_intx_level(d)); + return xsm_ops->hvm_set_pci_intx_level(d); } static inline int xsm_hvm_set_isa_irq_level (struct domain *d) { - return xsm_call(hvm_set_isa_irq_level(d)); + return xsm_ops->hvm_set_isa_irq_level(d); } static inline int xsm_hvm_set_pci_link_route (struct domain *d) { - return xsm_call(hvm_set_pci_link_route(d)); + return xsm_ops->hvm_set_pci_link_route(d); } static inline int xsm_hvm_inject_msi (struct domain *d) { - return xsm_call(hvm_inject_msi(d)); + return xsm_ops->hvm_inject_msi(d); } static inline int xsm_mem_event_setup (struct domain *d) { - return xsm_call(mem_event_setup(d)); + return xsm_ops->mem_event_setup(d); } static inline int xsm_mem_event_control (struct domain *d, int mode, int op) { - return xsm_call(mem_event_control(d, mode, op)); + return xsm_ops->mem_event_control(d, mode, op); } static inline int xsm_mem_event_op (struct domain *d, int op) { - return xsm_call(mem_event_op(d, op)); + return xsm_ops->mem_event_op(d, op); } static inline int xsm_mem_sharing (struct domain *d) { - return xsm_call(mem_sharing(d)); + return xsm_ops->mem_sharing(d); } static inline int xsm_mem_sharing_op (struct domain *d, struct domain *cd, int op) { - return xsm_call(mem_sharing_op(d, cd, op)); + return xsm_ops->mem_sharing_op(d, cd, op); } static inline int xsm_audit_p2m (struct domain *d) { - return xsm_call(audit_p2m(d)); + return xsm_ops->audit_p2m(d); } static inline int xsm_apic (struct domain *d, int cmd) { - return xsm_call(apic(d, cmd)); + return xsm_ops->apic(d, cmd); } static inline int xsm_xen_settime (void) { - return xsm_call(xen_settime()); + return xsm_ops->xen_settime(); } static inline int xsm_memtype (uint32_t access) { - return xsm_call(memtype(access)); + return xsm_ops->memtype(access); } static inline int xsm_microcode (void) { - return xsm_call(microcode()); + return xsm_ops->microcode(); } static inline int xsm_physinfo (void) { - return xsm_call(physinfo()); + return xsm_ops->physinfo(); } static inline int xsm_platform_quirk (uint32_t quirk) { - return xsm_call(platform_quirk(quirk)); + return xsm_ops->platform_quirk(quirk); } static inline int xsm_firmware_info (void) { - return xsm_call(firmware_info()); + return xsm_ops->firmware_info(); } static inline int xsm_efi_call (void) { - return xsm_call(efi_call()); + return xsm_ops->efi_call(); } static inline int xsm_acpi_sleep (void) { - return xsm_call(acpi_sleep()); + return xsm_ops->acpi_sleep(); } static inline int xsm_change_freq (void) { - return xsm_call(change_freq()); + return xsm_ops->change_freq(); } static inline int xsm_getidletime (void) { - return xsm_call(getidletime()); + return xsm_ops->getidletime(); } static inline int xsm_machine_memory_map(void) { - return xsm_call(machine_memory_map()); + return xsm_ops->machine_memory_map(); } static inline int xsm_domain_memory_map(struct domain *d) { - return xsm_call(domain_memory_map(d)); + return xsm_ops->domain_memory_map(d); } static inline int xsm_mmu_normal_update (struct domain *d, struct domain *t, struct domain *f, intpte_t fpte) { - return xsm_call(mmu_normal_update(d, t, f, fpte)); + return xsm_ops->mmu_normal_update(d, t, f, fpte); } static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn) { - return xsm_call(mmu_machphys_update(d, mfn)); + return xsm_ops->mmu_machphys_update(d, mfn); } static inline int xsm_update_va_mapping(struct domain *d, struct domain *f, l1_pgentry_t pte) { - return xsm_call(update_va_mapping(d, f, pte)); + return xsm_ops->update_va_mapping(d, f, pte); } static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2) { - return xsm_call(add_to_physmap(d1, d2)); + return xsm_ops->add_to_physmap(d1, d2); } static inline int xsm_sendtrigger(struct domain *d) { - return xsm_call(sendtrigger(d)); + return xsm_ops->sendtrigger(d); } static inline int xsm_bind_pt_irq(struct domain *d, struct xen_domctl_bind_pt_irq *bind) { - return xsm_call(bind_pt_irq(d, bind)); + return xsm_ops->bind_pt_irq(d, bind); } static inline int xsm_unbind_pt_irq(struct domain *d, struct xen_domctl_bind_pt_irq *bind) { - return xsm_call(unbind_pt_irq(d, bind)); + return xsm_ops->unbind_pt_irq(d, bind); } static inline int xsm_pin_mem_cacheattr(struct domain *d) { - return xsm_call(pin_mem_cacheattr(d)); + return xsm_ops->pin_mem_cacheattr(d); } static inline int xsm_ext_vcpucontext(struct domain *d, uint32_t cmd) { - return xsm_call(ext_vcpucontext(d, cmd)); + return xsm_ops->ext_vcpucontext(d, cmd); } static inline int xsm_vcpuextstate(struct domain *d, uint32_t cmd) { - return xsm_call(vcpuextstate(d, cmd)); + return xsm_ops->vcpuextstate(d, cmd); } static inline int xsm_ioport_permission (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) { - return xsm_call(ioport_permission(d, s, e, allow)); + return xsm_ops->ioport_permission(d, s, e, allow); } static inline int xsm_ioport_mapping (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) { - return xsm_call(ioport_mapping(d, s, e, allow)); + return xsm_ops->ioport_mapping(d, s, e, allow); } #endif /* CONFIG_X86 */ -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 15/18] xsm/flask: add distinct SIDs for self/target access
Because the FLASK XSM module no longer checks IS_PRIV for remote domain accesses covered by XSM permissions, domains now have the ability to perform memory management and other functions on all domains that have the same type. While it is possible to prevent this by only creating one domain per type, this solution significantly limits the flexibility of the type system. This patch introduces a domain type transition to represent a domain that is operating on itself. In the example policy, this is demonstrated by creating a type with _self appended when declaring a domain type which will be used for reflexive operations. AVCs for a domain of type domU_t will look like the following: scontext=system_u:system_r:domU_t tcontext=system_u:system_r:domU_t_self This change also allows policy to distinguish between event channels a domain creates to itself and event channels created between domains of the same type. The IS_PRIV_FOR check used for device model domains is also no longer checked by FLASK; a similar transition is performed when the target is set and used when the device model accesses its target domain. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.if | 64 +++- tools/flask/policy/policy/modules/xen/xen.te | 13 +- xen/xsm/flask/flask_op.c | 9 + xen/xsm/flask/hooks.c | 470 +++++++++++++-------------- xen/xsm/flask/include/objsec.h | 2 + 5 files changed, 289 insertions(+), 269 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index f9bd757..796698b 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -5,15 +5,34 @@ # Domain creation and setup # ################################################################################ +define(`declare_domain_common'', ` + allow $1 $2:grant { query setup }; + allow $1 $2:mmu { adjust physmap map_read map_write stat pinpage updatemp }; + allow $1 $2:hvm { getparam setparam }; +'') + # declare_domain(type, attrs...) -# Declare a type as a domain type, and allow basic domain setup +# Declare a domain type, along with associated _self and _channel types +# Allow the domain to perform basic operations on itself define(`declare_domain'', ` type $1, domain_type`''ifelse(`$#'', `1'', `'', `,shift($@)''); + type $1_self, domain_type, domain_self_type; + type_transition $1 $1:domain $1_self; + type $1_channel, event_type; + type_transition $1 domain_type:event $1_channel; + declare_domain_common($1, $1_self) +'') + +# declare_singleton_domain(type, attrs...) +# Declare a domain type and associated _channel types. +# Note: Because the domain can perform basic operations on itself and any +# other domain of the same type, this constructor should be used for types +# containing at most one domain. This is not enforced by policy. +define(`declare_singleton_domain'', ` + type $1, domain_type`''ifelse(`$#'', `1'', `'', `,shift($@)''); type $1_channel, event_type; type_transition $1 domain_type:event $1_channel; - allow $1 $1:grant { query setup }; - allow $1 $1:mmu { adjust physmap map_read map_write stat pinpage }; - allow $1 $1:hvm { getparam setparam }; + declare_domain_common($1, $1) '') # declare_build_label(type) @@ -51,6 +70,7 @@ define(`create_domain_build_label'', ` allow $1 $2_channel:event create; allow $1 $2_building:domain2 relabelfrom; allow $1 $2:domain2 relabelto; + allow $2_building $2:domain transition; '') # manage_domain(priv, target) @@ -101,20 +121,36 @@ define(`domain_comms'', ` '') # domain_self_comms(domain) -# Allow a domain types to communicate with others of its type using grants -# and event channels (this includes event channels to DOMID_SELF) +# Allow a non-singleton domain type to communicate with itself using grants +# and event channels define(`domain_self_comms'', ` - create_channel($1, $1, $1_channel) - allow $1 $1:grant { map_read map_write copy unmap }; + create_channel($1, $1_self, $1_channel) + allow $1 $1_self:grant { map_read map_write copy unmap }; '') # device_model(dm_dom, hvm_dom) # Define how a device model domain interacts with its target define(`device_model'', ` - domain_comms($1, $2) - allow $1 $2:domain { set_target shutdown }; - allow $1 $2:mmu { map_read map_write adjust physmap }; - allow $1 $2:hvm { getparam setparam trackdirtyvram hvmctl irqlevel pciroute }; + type $2_target, domain_type, domain_target_type; + type_transition $2 $1:domain $2_target; + allow $1 $2:domain set_target; + + type_transition $2_target domain_type:event $2_channel; + create_channel($1, $2_target, $1_channel) + create_channel($2, $1, $2_channel) + allow $1 $2_channel:event create; + + allow $1 $2_target:domain shutdown; + allow $1 $2_target:mmu { map_read map_write adjust physmap }; + allow $1 $2_target:hvm { getparam setparam trackdirtyvram hvmctl irqlevel pciroute cacheattr }; +'') + +# make_device_model(priv, dm_dom, hvm_dom) +# Allow creation of a device model and HVM domain pair +define(`make_device_model'', ` + device_model($2, $3) + allow $1 $2:domain2 make_priv_for; + allow $1 $3:domain2 set_as_target; '') ################################################################################ # @@ -132,7 +168,9 @@ define(`use_device'', ` # admin_device(domain, device) # Allow a device to be used and delegated by a domain define(`admin_device'', ` - allow $1 $2:resource { setup stat_device add_device add_irq add_iomem add_ioport remove_device remove_irq remove_iomem remove_ioport }; + allow $1 $2:resource { setup stat_device add_device add_irq add_iomem add_ioport + remove_device remove_irq remove_iomem remove_ioport + plug unplug }; allow $1 $2:hvm bind_irq; use_device($1, $2) '') diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 1162153..8d33285 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -8,6 +8,8 @@ ################################################################################ attribute xen_type; attribute domain_type; +attribute domain_self_type; +attribute domain_target_type; attribute resource_type; attribute event_type; attribute mls_priv; @@ -25,7 +27,7 @@ attribute mls_priv; type xen_t, xen_type, mls_priv; # Domain 0 -declare_domain(dom0_t, mls_priv); +declare_singleton_domain(dom0_t, mls_priv); # Untracked I/O memory (pseudo-domain) type domio_t, xen_type; @@ -69,7 +71,7 @@ admin_device(dom0_t, ioport_t) admin_device(dom0_t, iomem_t) allow dom0_t domio_t:mmu { map_read map_write }; -domain_self_comms(dom0_t) +domain_comms(dom0_t, dom0_t) auditallow dom0_t security_t:security { load_policy setenforce setbool }; @@ -84,11 +86,14 @@ domain_self_comms(domU_t) create_domain(dom0_t, domU_t) manage_domain(dom0_t, domU_t) domain_comms(dom0_t, domU_t) +domain_comms(domU_t, domU_t) +domain_self_comms(domU_t) declare_domain(isolated_domU_t) create_domain(dom0_t, isolated_domU_t) manage_domain(dom0_t, isolated_domU_t) domain_comms(dom0_t, isolated_domU_t) +domain_self_comms(isolated_domU_t) # Declare a boolean that denies creation of prot_domU_t domains gen_bool(prot_doms_locked, false) @@ -98,6 +103,8 @@ if (!prot_doms_locked) { } domain_comms(dom0_t, prot_domU_t) domain_comms(domU_t, prot_domU_t) +domain_comms(prot_domU_t, prot_domU_t) +domain_self_comms(prot_domU_t) # domHVM_t is meant to be paired with a qemu-dm stub domain of type dm_dom_t declare_domain(domHVM_t) @@ -110,7 +117,7 @@ declare_domain(dm_dom_t) create_domain(dom0_t, dm_dom_t) manage_domain(dom0_t, dm_dom_t) domain_comms(dom0_t, dm_dom_t) -device_model(dm_dom_t, domHVM_t) +make_device_model(dom0_t, dm_dom_t, domHVM_t) # nomigrate_t must be built via the nomigrate_t_building label; once built, # dom0 cannot read its memory. diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c index 9c0a087..28f6f5e 100644 --- a/xen/xsm/flask/flask_op.c +++ b/xen/xsm/flask/flask_op.c @@ -612,6 +612,15 @@ static int flask_relabel_domain(struct xen_flask_relabel *arg) goto out; dsec->sid = arg->sid; + dsec->self_sid = arg->sid; + security_transition_sid(dsec->sid, dsec->sid, SECCLASS_DOMAIN, + &dsec->self_sid); + if ( d->target ) + { + struct domain_security_struct *tsec = d->target->ssid; + security_transition_sid(tsec->sid, dsec->sid, SECCLASS_DOMAIN, + &dsec->target_sid); + } out: rcu_unlock_domain(d); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index be5c3ad..dae587c 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -33,38 +33,69 @@ struct xsm_operations *original_ops = NULL; +static u32 domain_sid(struct domain *dom) +{ + struct domain_security_struct *dsec = dom->ssid; + return dsec->sid; +} + +static u32 domain_target_sid(struct domain *src, struct domain *dst) +{ + struct domain_security_struct *ssec = src->ssid; + struct domain_security_struct *dsec = dst->ssid; + if (src == dst) + return ssec->self_sid; + if (src->target == dst) + return ssec->target_sid; + return dsec->sid; +} + +static u32 evtchn_sid(const struct evtchn *chn) +{ + struct evtchn_security_struct *esec = chn->ssid; + return esec->sid; +} + static int domain_has_perm(struct domain *dom1, struct domain *dom2, u16 class, u32 perms) { - struct domain_security_struct *dsec1, *dsec2; + u32 ssid, tsid; struct avc_audit_data ad; AVC_AUDIT_DATA_INIT(&ad, NONE); ad.sdom = dom1; ad.tdom = dom2; - dsec1 = dom1->ssid; - dsec2 = dom2->ssid; + ssid = domain_sid(dom1); + tsid = domain_target_sid(dom1, dom2); - return avc_has_perm(dsec1->sid, dsec2->sid, class, perms, &ad); + return avc_has_perm(ssid, tsid, class, perms, &ad); } -static int domain_has_evtchn(struct domain *d, struct evtchn *chn, u32 perms) +static int avc_current_has_perm(u32 tsid, u16 class, u32 perm, + struct avc_audit_data *ad) { - struct domain_security_struct *dsec; - struct evtchn_security_struct *esec; + u32 csid = domain_sid(current->domain); + return avc_has_perm(csid, tsid, class, perm, ad); +} - dsec = d->ssid; - esec = chn->ssid; +static int current_has_perm(struct domain *d, u16 class, u32 perms) +{ + return domain_has_perm(current->domain, d, class, perms); +} + +static int domain_has_evtchn(struct domain *d, struct evtchn *chn, u32 perms) +{ + u32 dsid = domain_sid(d); + u32 esid = evtchn_sid(chn); - return avc_has_perm(dsec->sid, esec->sid, SECCLASS_EVENT, perms, NULL); + return avc_has_perm(dsid, esid, SECCLASS_EVENT, perms, NULL); } static int domain_has_xen(struct domain *d, u32 perms) { - struct domain_security_struct *dsec; - dsec = d->ssid; + u32 dsid = domain_sid(d); - return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_XEN, perms, NULL); + return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_XEN, perms, NULL); } static int get_irq_sid(int irq, u32 *sid, struct avc_audit_data *ad) @@ -109,14 +140,11 @@ static int flask_domain_alloc_security(struct domain *d) memset(dsec, 0, sizeof(struct domain_security_struct)); if ( is_idle_domain(d) ) - { dsec->sid = SECINITSID_XEN; - } else - { dsec->sid = SECINITSID_UNLABELED; - } + dsec->self_sid = dsec->sid; d->ssid = dsec; return 0; @@ -136,68 +164,55 @@ static void flask_domain_free_security(struct domain *d) static int flask_evtchn_unbound(struct domain *d1, struct evtchn *chn, domid_t id2) { - u32 newsid; + u32 sid1, sid2, newsid; int rc; - domid_t id; struct domain *d2; - struct domain_security_struct *dsec, *dsec1, *dsec2; struct evtchn_security_struct *esec; - dsec = current->domain->ssid; - dsec1 = d1->ssid; - esec = chn->ssid; - - if ( id2 == DOMID_SELF ) - id = current->domain->domain_id; - else - id = id2; - - d2 = get_domain_by_id(id); + d2 = rcu_lock_domain_by_id(id2); if ( d2 == NULL ) return -EPERM; - dsec2 = d2->ssid; - rc = security_transition_sid(dsec1->sid, dsec2->sid, SECCLASS_EVENT, - &newsid); + sid1 = domain_sid(d1); + sid2 = domain_target_sid(d1, d2); + esec = chn->ssid; + + rc = security_transition_sid(sid1, sid2, SECCLASS_EVENT, &newsid); if ( rc ) goto out; - rc = avc_has_perm(dsec->sid, newsid, SECCLASS_EVENT, EVENT__CREATE, NULL); + rc = avc_current_has_perm(newsid, SECCLASS_EVENT, EVENT__CREATE, NULL); if ( rc ) goto out; - rc = avc_has_perm(newsid, dsec2->sid, SECCLASS_EVENT, EVENT__BIND, NULL); + rc = avc_has_perm(newsid, sid2, SECCLASS_EVENT, EVENT__BIND, NULL); if ( rc ) goto out; - else - esec->sid = newsid; + + esec->sid = newsid; out: - put_domain(d2); + rcu_unlock_domain(d2); return rc; } static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1, struct domain *d2, struct evtchn *chn2) { - u32 newsid; + u32 sid1, sid2, newsid, reverse_sid; int rc; - struct domain_security_struct *dsec, *dsec1, *dsec2; - struct evtchn_security_struct *esec1, *esec2; + struct evtchn_security_struct *esec1; struct avc_audit_data ad; AVC_AUDIT_DATA_INIT(&ad, NONE); ad.sdom = d1; ad.tdom = d2; - dsec = current->domain->ssid; - dsec1 = d1->ssid; - dsec2 = d2->ssid; + sid1 = domain_sid(d1); + sid2 = domain_target_sid(d1, d2); esec1 = chn1->ssid; - esec2 = chn2->ssid; - rc = security_transition_sid(dsec1->sid, dsec2->sid, - SECCLASS_EVENT, &newsid); + rc = security_transition_sid(sid1, sid2, SECCLASS_EVENT, &newsid); if ( rc ) { printk("%s: security_transition_sid failed, rc=%d (domain=%d)\n", @@ -205,15 +220,20 @@ static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1, return rc; } - rc = avc_has_perm(dsec->sid, newsid, SECCLASS_EVENT, EVENT__CREATE, &ad); + rc = avc_current_has_perm(newsid, SECCLASS_EVENT, EVENT__CREATE, &ad); if ( rc ) return rc; - rc = avc_has_perm(newsid, dsec2->sid, SECCLASS_EVENT, EVENT__BIND, &ad); + rc = avc_has_perm(newsid, sid2, SECCLASS_EVENT, EVENT__BIND, &ad); if ( rc ) return rc; - rc = avc_has_perm(esec2->sid, dsec1->sid, SECCLASS_EVENT, EVENT__BIND, &ad); + /* It''s possible the target domain has changed (relabel or destroy/create) + * since the unbound part was created; re-validate this binding now. + */ + reverse_sid = evtchn_sid(chn2); + sid1 = domain_target_sid(d2, d1); + rc = avc_has_perm(reverse_sid, sid1, SECCLASS_EVENT, EVENT__BIND, &ad); if ( rc ) return rc; @@ -296,7 +316,6 @@ static void flask_free_security_evtchn(struct evtchn *chn) static char *flask_show_security_evtchn(struct domain *d, const struct evtchn *chn) { - struct evtchn_security_struct *esec; int irq; u32 sid = 0; char *ctx; @@ -306,9 +325,7 @@ static char *flask_show_security_evtchn(struct domain *d, const struct evtchn *c { case ECS_UNBOUND: case ECS_INTERDOMAIN: - esec = chn->ssid; - if ( esec ) - sid = esec->sid; + sid = evtchn_sid(chn); break; case ECS_PIRQ: irq = domain_pirq_to_irq(d, chn->u.pirq.irq); @@ -359,11 +376,10 @@ static int flask_grant_query_size(struct domain *d1, struct domain *d2) return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__QUERY); } -static int get_page_sid(struct page_info *page, u32 *sid) +static int get_page_sid(struct domain *who, struct page_info *page, u32 *sid) { int rc = 0; struct domain *d; - struct domain_security_struct *dsec; unsigned long mfn; d = page_get_owner(page); @@ -389,15 +405,14 @@ static int get_page_sid(struct page_info *page, u32 *sid) default: /*Pages are implicitly labeled by domain ownership!*/ - dsec = d->ssid; - *sid = dsec ? dsec->sid : SECINITSID_UNLABELED; + *sid = domain_target_sid(who, d); break; } return rc; } -static int get_mfn_sid(unsigned long mfn, u32 *sid) +static int get_mfn_sid(struct domain *who, unsigned long mfn, u32 *sid) { int rc = 0; struct page_info *page; @@ -406,7 +421,7 @@ static int get_mfn_sid(unsigned long mfn, u32 *sid) { /*mfn is valid if this is a page that Xen is tracking!*/ page = mfn_to_page(mfn); - rc = get_page_sid(page, sid); + rc = get_page_sid(who, page, sid); } else { @@ -419,12 +434,12 @@ static int get_mfn_sid(unsigned long mfn, u32 *sid) static int flask_get_pod_target(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__GETPODTARGET); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETPODTARGET); } static int flask_set_pod_target(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SETPODTARGET); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETPODTARGET); } static int flask_memory_adjust_reservation(struct domain *d1, struct domain *d2) @@ -440,15 +455,14 @@ static int flask_memory_stat_reservation(struct domain *d1, struct domain *d2) static int flask_memory_pin_page(struct domain *d, struct page_info *page) { int rc = 0; - u32 sid; - struct domain_security_struct *dsec; - dsec = d->ssid; + u32 dsid, psid; + dsid = domain_sid(d); - rc = get_page_sid(page, &sid); + rc = get_page_sid(d, page, &psid); if ( rc ) return rc; - return avc_has_perm(dsec->sid, sid, SECCLASS_MMU, MMU__PINPAGE, NULL); + return avc_has_perm(dsid, psid, SECCLASS_MMU, MMU__PINPAGE, NULL); } static int flask_console_io(struct domain *d, int cmd) @@ -515,70 +529,65 @@ static int flask_schedop_shutdown(struct domain *d1, struct domain *d2) static void flask_security_domaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info) { - struct domain_security_struct *dsec; - - dsec = d->ssid; - info->ssidref = dsec->sid; + info->ssidref = domain_sid(d); } static int flask_setvcpucontext(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__SETVCPUCONTEXT); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETVCPUCONTEXT); } static int flask_pausedomain(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__PAUSE); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__PAUSE); } static int flask_unpausedomain(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__UNPAUSE); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__UNPAUSE); } static int flask_resumedomain(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__RESUME); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__RESUME); } static int flask_domain_create(struct domain *d, u32 ssidref) { int rc; - struct domain_security_struct *dsec1; - struct domain_security_struct *dsec2; + struct domain_security_struct *dsec = d->ssid; static int dom0_created = 0; - dsec1 = current->domain->ssid; - dsec2 = d->ssid; - if ( is_idle_domain(current->domain) && !dom0_created ) { - dsec2->sid = SECINITSID_DOM0; + dsec->sid = SECINITSID_DOM0; dom0_created = 1; - return 0; } + else + { + rc = avc_current_has_perm(ssidref, SECCLASS_DOMAIN, + DOMAIN__CREATE, NULL); + if ( rc ) + return rc; - rc = avc_has_perm(dsec1->sid, ssidref, SECCLASS_DOMAIN, - DOMAIN__CREATE, NULL); - if ( rc ) - return rc; + dsec->sid = ssidref; + } + dsec->self_sid = dsec->sid; - dsec2->sid = ssidref; + rc = security_transition_sid(dsec->sid, dsec->sid, SECCLASS_DOMAIN, + &dsec->self_sid); return rc; } static int flask_max_vcpus(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__MAX_VCPUS); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__MAX_VCPUS); } static int flask_destroydomain(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__DESTROY); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__DESTROY); } static int flask_vcpuaffinity(int cmd, struct domain *d) @@ -597,7 +606,7 @@ static int flask_vcpuaffinity(int cmd, struct domain *d) return -EPERM; } - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm ); + return current_has_perm(d, SECCLASS_DOMAIN, perm ); } static int flask_scheduler(struct domain *d) @@ -608,53 +617,61 @@ static int flask_scheduler(struct domain *d) if ( rc ) return rc; - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__SCHEDULER); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SCHEDULER); } static int flask_getdomaininfo(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__GETDOMAININFO); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETDOMAININFO); } static int flask_getvcpucontext(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__GETVCPUCONTEXT); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETVCPUCONTEXT); } static int flask_getvcpuinfo(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__GETVCPUINFO); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETVCPUINFO); } static int flask_domain_settime(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SETTIME); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETTIME); } -static int flask_set_target(struct domain *d, struct domain *e) +static int flask_set_target(struct domain *d, struct domain *t) { int rc; - rc = domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__MAKE_PRIV_FOR); + struct domain_security_struct *dsec, *tsec; + dsec = d->ssid; + tsec = t->ssid; + + rc = current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__MAKE_PRIV_FOR); if ( rc ) return rc; - rc = domain_has_perm(current->domain, e, SECCLASS_DOMAIN2, DOMAIN2__SET_AS_TARGET); + rc = current_has_perm(t, SECCLASS_DOMAIN2, DOMAIN2__SET_AS_TARGET); if ( rc ) return rc; - return domain_has_perm(d, e, SECCLASS_DOMAIN, DOMAIN__SET_TARGET); + /* Use avc_has_perm to avoid resolving target/current SID */ + rc = avc_has_perm(dsec->sid, tsec->sid, SECCLASS_DOMAIN, DOMAIN__SET_TARGET, NULL); + if ( rc ) + return rc; + + /* (tsec, dsec) defaults the label to tsec, as it should here */ + rc = security_transition_sid(tsec->sid, dsec->sid, SECCLASS_DOMAIN, + &dsec->target_sid); + return rc; } static int flask_domctl(struct domain *d, int cmd) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SET_MISC_INFO); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SET_MISC_INFO); } static int flask_set_virq_handler(struct domain *d, uint32_t virq) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SET_VIRQ_HANDLER); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SET_VIRQ_HANDLER); } static int flask_tbufcontrol(void) @@ -679,26 +696,22 @@ static int flask_sched_id(void) static int flask_setdomainmaxmem(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__SETDOMAINMAXMEM); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETDOMAINMAXMEM); } static int flask_setdomainhandle(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__SETDOMAINHANDLE); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETDOMAINHANDLE); } static int flask_setdebugging(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__SETDEBUGGING); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETDEBUGGING); } static int flask_debug_op(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__SETDEBUGGING); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETDEBUGGING); } static int flask_debug_keys(void) @@ -760,14 +773,12 @@ static char *flask_show_irq_sid (int irq) static int flask_map_domain_pirq (struct domain *d, int irq, void *data) { - u32 sid; + u32 sid, dsid; int rc = -EPERM; struct msi_info *msi = data; - - struct domain_security_struct *ssec, *tsec; struct avc_audit_data ad; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD); + rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD); if ( rc ) return rc; @@ -783,14 +794,13 @@ static int flask_map_domain_pirq (struct domain *d, int irq, void *data) if ( rc ) return rc; - ssec = current->domain->ssid; - tsec = d->ssid; + dsid = domain_sid(d); - rc = avc_has_perm(ssec->sid, sid, SECCLASS_RESOURCE, RESOURCE__ADD_IRQ, &ad); + rc = avc_current_has_perm(sid, SECCLASS_RESOURCE, RESOURCE__ADD_IRQ, &ad); if ( rc ) return rc; - rc = avc_has_perm(tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); + rc = avc_has_perm(dsid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); return rc; } @@ -798,16 +808,12 @@ static int flask_unmap_domain_pirq (struct domain *d, int irq) { u32 sid; int rc = -EPERM; - - struct domain_security_struct *ssec; struct avc_audit_data ad; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE); + rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE); if ( rc ) return rc; - ssec = current->domain->ssid; - if ( irq >= nr_irqs_gsi ) { /* TODO support for MSI here */ return 0; @@ -817,19 +823,19 @@ static int flask_unmap_domain_pirq (struct domain *d, int irq) if ( rc ) return rc; - rc = avc_has_perm(ssec->sid, sid, SECCLASS_RESOURCE, RESOURCE__REMOVE_IRQ, &ad); + rc = avc_current_has_perm(sid, SECCLASS_RESOURCE, RESOURCE__REMOVE_IRQ, &ad); return rc; } static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) { /* the PIRQ number is not useful; real IRQ is checked during mapping */ - return domain_has_perm(current->domain, d, SECCLASS_RESOURCE, - resource_to_perm(access)); + return current_has_perm(d, SECCLASS_RESOURCE, resource_to_perm(access)); } struct iomem_has_perm_data { - struct domain_security_struct *ssec, *tsec; + u32 ssid; + u32 dsid; u32 perm; }; @@ -843,12 +849,12 @@ static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long ad.range.start = start; ad.range.end = end; - rc = avc_has_perm(data->ssec->sid, sid, SECCLASS_RESOURCE, data->perm, &ad); + rc = avc_has_perm(data->ssid, sid, SECCLASS_RESOURCE, data->perm, &ad); if ( rc ) return rc; - return avc_has_perm(data->tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); + return avc_has_perm(data->dsid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end, uint8_t access) @@ -856,7 +862,7 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end struct iomem_has_perm_data data; int rc; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, + rc = current_has_perm(d, SECCLASS_RESOURCE, resource_to_perm(access)); if ( rc ) return rc; @@ -866,18 +872,17 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end else data.perm = RESOURCE__REMOVE_IOMEM; - data.ssec = current->domain->ssid; - data.tsec = d->ssid; + data.ssid = domain_sid(current->domain); + data.dsid = domain_sid(d); return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data); } static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) { - u32 rsid; + u32 dsid, rsid; int rc = -EPERM; struct avc_audit_data ad; - struct domain_security_struct *ssec; u32 perm = RESOURCE__USE; rc = security_device_sid(machine_bdf, &rsid); @@ -890,33 +895,24 @@ static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, u AVC_AUDIT_DATA_INIT(&ad, DEV); ad.device = (unsigned long) machine_bdf; - ssec = d->ssid; - return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); + dsid = domain_sid(d); + return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, perm, &ad); } static int flask_resource_plug_core(void) { - struct domain_security_struct *ssec; - - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__PLUG, NULL); + return avc_current_has_perm(SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__PLUG, NULL); } static int flask_resource_unplug_core(void) { - struct domain_security_struct *ssec; - - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__UNPLUG, NULL); + return avc_current_has_perm(SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__UNPLUG, NULL); } static int flask_resource_use_core(void) { - struct domain_security_struct *ssec; - - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__USE, NULL); + return avc_current_has_perm(SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__USE, NULL); } static int flask_resource_plug_pci(uint32_t machine_bdf) @@ -924,7 +920,6 @@ static int flask_resource_plug_pci(uint32_t machine_bdf) u32 rsid; int rc = -EPERM; struct avc_audit_data ad; - struct domain_security_struct *ssec; rc = security_device_sid(machine_bdf, &rsid); if ( rc ) @@ -932,8 +927,7 @@ static int flask_resource_plug_pci(uint32_t machine_bdf) AVC_AUDIT_DATA_INIT(&ad, DEV); ad.device = (unsigned long) machine_bdf; - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__PLUG, &ad); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__PLUG, &ad); } static int flask_resource_unplug_pci(uint32_t machine_bdf) @@ -941,7 +935,6 @@ static int flask_resource_unplug_pci(uint32_t machine_bdf) u32 rsid; int rc = -EPERM; struct avc_audit_data ad; - struct domain_security_struct *ssec; rc = security_device_sid(machine_bdf, &rsid); if ( rc ) @@ -949,8 +942,7 @@ static int flask_resource_unplug_pci(uint32_t machine_bdf) AVC_AUDIT_DATA_INIT(&ad, DEV); ad.device = (unsigned long) machine_bdf; - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__UNPLUG, &ad); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__UNPLUG, &ad); } static int flask_resource_setup_pci(uint32_t machine_bdf) @@ -958,7 +950,6 @@ static int flask_resource_setup_pci(uint32_t machine_bdf) u32 rsid; int rc = -EPERM; struct avc_audit_data ad; - struct domain_security_struct *ssec; rc = security_device_sid(machine_bdf, &rsid); if ( rc ) @@ -966,8 +957,7 @@ static int flask_resource_setup_pci(uint32_t machine_bdf) AVC_AUDIT_DATA_INIT(&ad, DEV); ad.device = (unsigned long) machine_bdf; - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); } static int flask_resource_setup_gsi(int gsi) @@ -975,22 +965,17 @@ static int flask_resource_setup_gsi(int gsi) u32 rsid; int rc = -EPERM; struct avc_audit_data ad; - struct domain_security_struct *ssec; rc = get_irq_sid(gsi, &rsid, &ad); if ( rc ) return rc; - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); } static int flask_resource_setup_misc(void) { - struct domain_security_struct *ssec; - - ssec = current->domain->ssid; - return avc_has_perm(ssec->sid, SECINITSID_XEN, SECCLASS_RESOURCE, RESOURCE__SETUP, NULL); + return avc_current_has_perm(SECINITSID_XEN, SECCLASS_RESOURCE, RESOURCE__SETUP, NULL); } static inline int flask_page_offline(uint32_t cmd) @@ -1058,11 +1043,12 @@ static int flask_shadow_control(struct domain *d, uint32_t op) return -EPERM; } - return domain_has_perm(current->domain, d, SECCLASS_SHADOW, perm); + return current_has_perm(d, SECCLASS_SHADOW, perm); } struct ioport_has_perm_data { - struct domain_security_struct *ssec, *tsec; + u32 ssid; + u32 dsid; u32 perm; }; @@ -1076,12 +1062,12 @@ static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long ad.range.start = start; ad.range.end = end; - rc = avc_has_perm(data->ssec->sid, sid, SECCLASS_RESOURCE, data->perm, &ad); + rc = avc_has_perm(data->ssid, sid, SECCLASS_RESOURCE, data->perm, &ad); if ( rc ) return rc; - return avc_has_perm(data->tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); + return avc_has_perm(data->dsid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } @@ -1090,7 +1076,7 @@ static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t en int rc; struct ioport_has_perm_data data; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, + rc = current_has_perm(d, SECCLASS_RESOURCE, resource_to_perm(access)); if ( rc ) @@ -1101,8 +1087,8 @@ static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t en else data.perm = RESOURCE__REMOVE_IOPORT; - data.ssec = current->domain->ssid; - data.tsec = d->ssid; + data.ssid = domain_sid(current->domain); + data.dsid = domain_sid(d); return security_iterate_ioport_sids(start, end, _ioport_has_perm, &data); } @@ -1111,46 +1097,42 @@ static int flask_getpageframeinfo(struct page_info *page) { int rc = 0; u32 tsid; - struct domain_security_struct *dsec; - - dsec = current->domain->ssid; - rc = get_page_sid(page, &tsid); + rc = get_page_sid(current->domain, page, &tsid); if ( rc ) return rc; - return avc_has_perm(dsec->sid, tsid, SECCLASS_MMU, MMU__PAGEINFO, NULL); + return avc_current_has_perm(tsid, SECCLASS_MMU, MMU__PAGEINFO, NULL); } static int flask_getpageframeinfo_domain(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGEINFO); + return current_has_perm(d, SECCLASS_MMU, MMU__PAGEINFO); } static int flask_set_cpuid(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID); + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID); } static int flask_gettscinfo(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__GETTSC); + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GETTSC); } static int flask_settscinfo(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, DOMAIN2__SETTSC); + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SETTSC); } static int flask_getmemlist(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGELIST); + return current_has_perm(d, SECCLASS_MMU, MMU__PAGELIST); } static int flask_hypercall_init(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, - DOMAIN__HYPERCALL); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__HYPERCALL); } static int flask_hvmcontext(struct domain *d, uint32_t cmd) @@ -1173,7 +1155,7 @@ static int flask_hvmcontext(struct domain *d, uint32_t cmd) return -EPERM; } - return domain_has_perm(current->domain, d, SECCLASS_HVM, perm); + return current_has_perm(d, SECCLASS_HVM, perm); } static int flask_address_size(struct domain *d, uint32_t cmd) @@ -1192,7 +1174,7 @@ static int flask_address_size(struct domain *d, uint32_t cmd) return -EPERM; } - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm); + return current_has_perm(d, SECCLASS_DOMAIN, perm); } static int flask_hvm_param(struct domain *d, unsigned long op) @@ -1214,47 +1196,47 @@ static int flask_hvm_param(struct domain *d, unsigned long op) perm = HVM__HVMCTL; } - return domain_has_perm(current->domain, d, SECCLASS_HVM, perm); + return current_has_perm(d, SECCLASS_HVM, perm); } static int flask_hvm_set_pci_intx_level(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCILEVEL); + return current_has_perm(d, SECCLASS_HVM, HVM__PCILEVEL); } static int flask_hvm_set_isa_irq_level(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__IRQLEVEL); + return current_has_perm(d, SECCLASS_HVM, HVM__IRQLEVEL); } static int flask_hvm_set_pci_link_route(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCIROUTE); + return current_has_perm(d, SECCLASS_HVM, HVM__PCIROUTE); } static int flask_mem_event_setup(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); + return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT); } static int flask_mem_event_control(struct domain *d, int mode, int op) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); + return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT); } static int flask_mem_event_op(struct domain *d, int op) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); + return current_has_perm(d, SECCLASS_HVM, HVM__MEM_EVENT); } static int flask_mem_sharing(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_SHARING); + return current_has_perm(d, SECCLASS_HVM, HVM__MEM_SHARING); } static int flask_mem_sharing_op(struct domain *d, struct domain *cd, int op) { - int rc = domain_has_perm(current->domain, cd, SECCLASS_HVM, HVM__MEM_SHARING); + int rc = current_has_perm(cd, SECCLASS_HVM, HVM__MEM_SHARING); if ( rc ) return rc; return domain_has_perm(d, cd, SECCLASS_HVM, HVM__SHARE_MEM); @@ -1262,7 +1244,7 @@ static int flask_mem_sharing_op(struct domain *d, struct domain *cd, int op) static int flask_audit_p2m(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__AUDIT_P2M); + return current_has_perm(d, SECCLASS_HVM, HVM__AUDIT_P2M); } static int flask_apic(struct domain *d, int cmd) @@ -1323,11 +1305,7 @@ static int flask_physinfo(void) static int flask_platform_quirk(uint32_t quirk) { - struct domain_security_struct *dsec; - dsec = current->domain->ssid; - - return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_XEN, - XEN__QUIRK, NULL); + return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN, XEN__QUIRK, NULL); } static int flask_firmware_info(void) @@ -1357,16 +1335,12 @@ static int flask_getidletime(void) static int flask_machine_memory_map(void) { - struct domain_security_struct *dsec; - dsec = current->domain->ssid; - - return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_MMU, - MMU__MEMORYMAP, NULL); + return avc_current_has_perm(SECINITSID_XEN, SECCLASS_MMU, MMU__MEMORYMAP, NULL); } static int flask_domain_memory_map(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__MEMORYMAP); + return current_has_perm(d, SECCLASS_MMU, MMU__MEMORYMAP); } static int flask_mmu_normal_update(struct domain *d, struct domain *t, @@ -1375,8 +1349,7 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *t, int rc = 0; u32 map_perms = MMU__MAP_READ; unsigned long fgfn, fmfn; - struct domain_security_struct *dsec; - u32 fsid; + u32 dsid, fsid; struct avc_audit_data ad; p2m_type_t p2mt; @@ -1388,7 +1361,7 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *t, if ( !(l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_PRESENT) ) return 0; - dsec = d->ssid; + dsid = domain_sid(d); if ( l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_RW ) map_perms |= MMU__MAP_WRITE; @@ -1402,37 +1375,35 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *t, ad.memory.pte = fpte; ad.memory.mfn = fmfn; - rc = get_mfn_sid(fmfn, &fsid); + rc = get_mfn_sid(d, fmfn, &fsid); put_gfn(f, fgfn); if ( rc ) return rc; - return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, &ad); + return avc_has_perm(dsid, fsid, SECCLASS_MMU, map_perms, &ad); } static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn) { int rc = 0; - u32 psid; - struct domain_security_struct *dsec; - dsec = d->ssid; + u32 dsid, psid; + dsid = domain_sid(d); - rc = get_mfn_sid(mfn, &psid); + rc = get_mfn_sid(d, mfn, &psid); if ( rc ) return rc; - return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, MMU__UPDATEMP, NULL); + return avc_has_perm(dsid, psid, SECCLASS_MMU, MMU__UPDATEMP, NULL); } static int flask_update_va_mapping(struct domain *d, struct domain *f, l1_pgentry_t pte) { int rc = 0; - u32 psid; + u32 dsid, psid; u32 map_perms = MMU__MAP_READ; - struct domain_security_struct *dsec; unsigned long fgfn, fmfn; p2m_type_t p2mt; @@ -1442,16 +1413,16 @@ static int flask_update_va_mapping(struct domain *d, struct domain *f, if ( l1e_get_flags(pte) & _PAGE_RW ) map_perms |= MMU__MAP_WRITE; - dsec = d->ssid; + dsid = domain_sid(d); fgfn = l1e_get_pfn(pte); fmfn = mfn_x(get_gfn_query(f, fgfn, &p2mt)); - rc = get_mfn_sid(fmfn, &psid); + rc = get_mfn_sid(d, fmfn, &psid); put_gfn(f, fgfn); if ( rc ) return rc; - return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, map_perms, NULL); + return avc_has_perm(dsid, psid, SECCLASS_MMU, map_perms, NULL); } static int flask_add_to_physmap(struct domain *d1, struct domain *d2) @@ -1466,43 +1437,40 @@ static int flask_remove_from_physmap(struct domain *d1, struct domain *d2) static int flask_sendtrigger(struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__TRIGGER); + return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__TRIGGER); } static int flask_get_device_group(uint32_t machine_bdf) { u32 rsid; int rc = -EPERM; - struct domain_security_struct *ssec = current->domain->ssid; rc = security_device_sid(machine_bdf, &rsid); if ( rc ) return rc; - return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL); } static int flask_test_assign_device(uint32_t machine_bdf) { u32 rsid; int rc = -EPERM; - struct domain_security_struct *ssec = current->domain->ssid; rc = security_device_sid(machine_bdf, &rsid); if ( rc ) return rc; - return rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL); } static int flask_assign_device(struct domain *d, uint32_t machine_bdf) { - u32 rsid; + u32 dsid, rsid; int rc = -EPERM; - struct domain_security_struct *ssec, *tsec; struct avc_audit_data ad; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD); + rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD); if ( rc ) return rc; @@ -1512,22 +1480,20 @@ static int flask_assign_device(struct domain *d, uint32_t machine_bdf) AVC_AUDIT_DATA_INIT(&ad, DEV); ad.device = (unsigned long) machine_bdf; - ssec = current->domain->ssid; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad); + rc = avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, &ad); if ( rc ) return rc; - tsec = d->ssid; - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); + dsid = domain_sid(d); + return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } static int flask_deassign_device(struct domain *d, uint32_t machine_bdf) { u32 rsid; int rc = -EPERM; - struct domain_security_struct *ssec = current->domain->ssid; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE); + rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE); if ( rc ) return rc; @@ -1535,18 +1501,17 @@ static int flask_deassign_device(struct domain *d, uint32_t machine_bdf) if ( rc ) return rc; - return rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, NULL); + return avc_current_has_perm(rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, NULL); } static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) { - u32 rsid; + u32 dsid, rsid; int rc = -EPERM; int irq; - struct domain_security_struct *ssec, *tsec; struct avc_audit_data ad; - rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD); + rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD); if ( rc ) return rc; @@ -1556,23 +1521,22 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b if ( rc ) return rc; - ssec = current->domain->ssid; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad); + rc = avc_current_has_perm(rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad); if ( rc ) return rc; - tsec = d->ssid; - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); + dsid = domain_sid(d); + return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } static int flask_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) { - return domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE); + return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE); } static int flask_pin_mem_cacheattr (struct domain *d) { - return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__CACHEATTR); + return current_has_perm(d, SECCLASS_HVM, HVM__CACHEATTR); } static int flask_ext_vcpucontext (struct domain *d, uint32_t cmd) @@ -1591,7 +1555,7 @@ static int flask_ext_vcpucontext (struct domain *d, uint32_t cmd) return -EPERM; } - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm); + return current_has_perm(d, SECCLASS_DOMAIN, perm); } static int flask_vcpuextstate (struct domain *d, uint32_t cmd) @@ -1610,7 +1574,7 @@ static int flask_vcpuextstate (struct domain *d, uint32_t cmd) return -EPERM; } - return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm); + return current_has_perm(d, SECCLASS_DOMAIN, perm); } #endif diff --git a/xen/xsm/flask/include/objsec.h b/xen/xsm/flask/include/objsec.h index 4ff52be..6595dc3 100644 --- a/xen/xsm/flask/include/objsec.h +++ b/xen/xsm/flask/include/objsec.h @@ -19,6 +19,8 @@ struct domain_security_struct { u32 sid; /* current SID */ + u32 self_sid; /* SID for target when operating on DOMID_SELF */ + u32 target_sid; /* SID for device model target domain */ }; struct evtchn_security_struct { -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks
This requires introducing a new XSM hook for do_mmuext_op to validate remote domain access there. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 1 + tools/flask/policy/policy/modules/xen/xen.if | 4 ++-- xen/arch/x86/mm.c | 25 ++++++++----------------- xen/include/xsm/dummy.h | 20 ++++++++++++++++++-- xen/include/xsm/xsm.h | 14 +++++++++++--- xen/xsm/dummy.c | 1 + xen/xsm/flask/hooks.c | 9 ++++++++- xen/xsm/flask/include/av_perm_to_string.h | 1 + xen/xsm/flask/include/av_permissions.h | 1 + 9 files changed, 51 insertions(+), 25 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 2986b40..5e897e2 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -141,6 +141,7 @@ class mmu mfnlist memorymap remote_remap + mmuext_op } class shadow diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index 796698b..78083c3 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -7,7 +7,7 @@ ################################################################################ define(`declare_domain_common'', ` allow $1 $2:grant { query setup }; - allow $1 $2:mmu { adjust physmap map_read map_write stat pinpage updatemp }; + allow $1 $2:mmu { adjust physmap map_read map_write stat pinpage updatemp mmuext_op }; allow $1 $2:hvm { getparam setparam }; '') @@ -51,7 +51,7 @@ define(`create_domain_common'', ` allow $1 $2:domain2 { set_cpuid settsc }; allow $1 $2:security check_context; allow $1 $2:shadow enable; - allow $1 $2:mmu {map_read map_write adjust memorymap physmap pinpage}; + allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage mmuext_op }; allow $1 $2:grant setup; allow $1 $2:hvm { cacheattr getparam hvmctl irqlevel pciroute sethvmc setparam pcilevel trackdirtyvram }; '') diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 1b352df..4bc3ab5 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2882,11 +2882,6 @@ static struct domain *get_pg_owner(domid_t domid) pg_owner = rcu_lock_domain(dom_io); break; case DOMID_XEN: - if ( !IS_PRIV(curr) ) - { - MEM_LOG("Cannot set foreign dom"); - break; - } pg_owner = rcu_lock_domain(dom_xen); break; default: @@ -2895,12 +2890,6 @@ static struct domain *get_pg_owner(domid_t domid) MEM_LOG("Unknown domain ''%u''", domid); break; } - if ( !IS_PRIV_FOR(curr, pg_owner) ) - { - MEM_LOG("Cannot set foreign dom"); - rcu_unlock_domain(pg_owner); - pg_owner = NULL; - } break; } @@ -3008,6 +2997,13 @@ int do_mmuext_op( goto out; } + rc = xsm_mmuext_op(d, pg_owner); + if ( rc ) + { + rcu_unlock_domain(pg_owner); + goto out; + } + for ( i = 0; i < count; i++ ) { if ( hypercall_preempt_check() ) @@ -3483,11 +3479,6 @@ int do_mmu_update( rc = -EINVAL; goto out; } - if ( !IS_PRIV_FOR(d, pt_owner) ) - { - rc = -ESRCH; - goto out; - } } if ( (pg_owner = get_pg_owner((uint16_t)foreigndom)) == NULL ) @@ -3643,7 +3634,7 @@ int do_mmu_update( mfn = req.ptr >> PAGE_SHIFT; gpfn = req.val; - rc = xsm_mmu_machphys_update(d, mfn); + rc = xsm_mmu_machphys_update(d, pg_owner, mfn); if ( rc ) break; diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index d796a33..28e1d2b 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -803,19 +803,35 @@ static XSM_DEFAULT(int, domain_memory_map) (struct domain *d) } static XSM_DEFAULT(int, mmu_normal_update) (struct domain *d, struct domain *t, - struct domain *f, intpte_t fpte) + struct domain *f, intpte_t fpte) { + if ( d != t && !IS_PRIV_FOR(d, t) ) + return -EPERM; + if ( d != f && !IS_PRIV_FOR(d, f) ) + return -EPERM; return 0; } -static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, unsigned long mfn) +static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, struct domain *f, + unsigned long mfn) { + if ( d != f && !IS_PRIV_FOR(d, f) ) + return -EPERM; + return 0; +} + +static XSM_DEFAULT(int, mmuext_op) (struct domain *d, struct domain *f) +{ + if ( d != f && !IS_PRIV_FOR(d, f) ) + return -EPERM; return 0; } static XSM_DEFAULT(int, update_va_mapping) (struct domain *d, struct domain *f, l1_pgentry_t pte) { + if ( d != f && !IS_PRIV_FOR(d, f) ) + return -EPERM; return 0; } diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index fa9f50e..4134877 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -177,7 +177,9 @@ struct xsm_operations { int (*domain_memory_map) (struct domain *d); int (*mmu_normal_update) (struct domain *d, struct domain *t, struct domain *f, intpte_t fpte); - int (*mmu_machphys_update) (struct domain *d, unsigned long mfn); + int (*mmu_machphys_update) (struct domain *d, struct domain *f, + unsigned long mfn); + int (*mmuext_op) (struct domain *d, struct domain *f); int (*update_va_mapping) (struct domain *d, struct domain *f, l1_pgentry_t pte); int (*add_to_physmap) (struct domain *d1, struct domain *d2); @@ -797,9 +799,15 @@ static inline int xsm_mmu_normal_update (struct domain *d, struct domain *t, return xsm_ops->mmu_normal_update(d, t, f, fpte); } -static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn) +static inline int xsm_mmu_machphys_update (struct domain *d, struct domain *f, + unsigned long mfn) { - return xsm_ops->mmu_machphys_update(d, mfn); + return xsm_ops->mmu_machphys_update(d, f, mfn); +} + +static inline int xsm_mmuext_op (struct domain *d, struct domain *f) +{ + return xsm_ops->mmuext_op(d, f); } static inline int xsm_update_va_mapping(struct domain *d, struct domain *f, diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index aebe333..1bf9de9 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -161,6 +161,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, domain_memory_map); set_to_dummy_if_null(ops, mmu_normal_update); set_to_dummy_if_null(ops, mmu_machphys_update); + set_to_dummy_if_null(ops, mmuext_op); set_to_dummy_if_null(ops, update_va_mapping); set_to_dummy_if_null(ops, add_to_physmap); set_to_dummy_if_null(ops, remove_from_physmap); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index dae587c..f743be1 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -1385,7 +1385,8 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *t, return avc_has_perm(dsid, fsid, SECCLASS_MMU, map_perms, &ad); } -static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn) +static int flask_mmu_machphys_update(struct domain *d, struct domain *f, + unsigned long mfn) { int rc = 0; u32 dsid, psid; @@ -1398,6 +1399,11 @@ static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn) return avc_has_perm(dsid, psid, SECCLASS_MMU, MMU__UPDATEMP, NULL); } +static int flask_mmuext_op(struct domain *d, struct domain *f) +{ + return domain_has_perm(d, f, SECCLASS_MMU, MMU__MMUEXT_OP); +} + static int flask_update_va_mapping(struct domain *d, struct domain *f, l1_pgentry_t pte) { @@ -1707,6 +1713,7 @@ static struct xsm_operations flask_ops = { .domain_memory_map = flask_domain_memory_map, .mmu_normal_update = flask_mmu_normal_update, .mmu_machphys_update = flask_mmu_machphys_update, + .mmuext_op = flask_mmuext_op, .update_va_mapping = flask_update_va_mapping, .add_to_physmap = flask_add_to_physmap, .remove_from_physmap = flask_remove_from_physmap, diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 5d5a45a..5d4f316 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -111,6 +111,7 @@ S_(SECCLASS_MMU, MMU__MFNLIST, "mfnlist") S_(SECCLASS_MMU, MMU__MEMORYMAP, "memorymap") S_(SECCLASS_MMU, MMU__REMOTE_REMAP, "remote_remap") + S_(SECCLASS_MMU, MMU__MMUEXT_OP, "mmuext_op") S_(SECCLASS_SHADOW, SHADOW__DISABLE, "disable") S_(SECCLASS_SHADOW, SHADOW__ENABLE, "enable") S_(SECCLASS_SHADOW, SHADOW__LOGDIRTY, "logdirty") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index e6d6a6d..f970b50 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -117,6 +117,7 @@ #define MMU__MFNLIST 0x00000400UL #define MMU__MEMORYMAP 0x00000800UL #define MMU__REMOTE_REMAP 0x00001000UL +#define MMU__MMUEXT_OP 0x00002000UL #define SHADOW__DISABLE 0x00000001UL #define SHADOW__ENABLE 0x00000002UL -- 1.7.11.2
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 1 + tools/flask/policy/policy/modules/xen/xen.if | 2 ++ xen/common/memory.c | 21 +++++++++------------ xen/include/xsm/dummy.h | 7 +++++++ xen/include/xsm/xsm.h | 6 ++++++ xen/xsm/dummy.c | 1 + xen/xsm/flask/hooks.c | 6 ++++++ xen/xsm/flask/include/av_perm_to_string.h | 1 + xen/xsm/flask/include/av_permissions.h | 1 + 9 files changed, 34 insertions(+), 12 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 5e897e2..2736075 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -142,6 +142,7 @@ class mmu memorymap remote_remap mmuext_op + exchange } class shadow diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index 78083c3..ab14d2f 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -30,6 +30,7 @@ define(`declare_domain'', ` # containing at most one domain. This is not enforced by policy. define(`declare_singleton_domain'', ` type $1, domain_type`''ifelse(`$#'', `1'', `'', `,shift($@)''); + define(`$1_self'', `$1'') type $1_channel, event_type; type_transition $1 domain_type:event $1_channel; declare_domain_common($1, $1) @@ -161,6 +162,7 @@ define(`make_device_model'', ` # use_device(domain, device) # Allow a device to be used by a domain define(`use_device'', ` + allow $1 $1_self:mmu exchange; allow $1 $2:resource use; allow $1 $2:mmu { map_read map_write }; '') diff --git a/xen/common/memory.c b/xen/common/memory.c index 77969d9..b8aaecb 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -329,21 +329,18 @@ static long memory_exchange(XEN_GUEST_HANDLE(xen_memory_exchange_t) arg) out_chunk_order = exch.in.extent_order - exch.out.extent_order; } - if ( likely(exch.in.domid == DOMID_SELF) ) + d = rcu_lock_domain_by_id(exch.in.domid); + if ( d == NULL ) { - d = rcu_lock_current_domain(); + rc = -ESRCH; + goto fail_early; } - else + + rc = xsm_memory_exchange(d); + if ( rc ) { - if ( (d = rcu_lock_domain_by_id(exch.in.domid)) == NULL ) - goto fail_early; - - if ( !IS_PRIV_FOR(current->domain, d) ) - { - rcu_unlock_domain(d); - rc = -EPERM; - goto fail_early; - } + rcu_unlock_domain(d); + goto fail_early; } memflags |= MEMF_bits(domain_clamp_alloc_bitsize( diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index 28e1d2b..6467928 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -279,6 +279,13 @@ static XSM_DEFAULT(int, grant_query_size) (struct domain *d1, struct domain *d2) return 0; } +static XSM_DEFAULT(int, memory_exchange) (struct domain *d) +{ + if ( d != current->domain && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; + return 0; +} + static XSM_DEFAULT(int, memory_adjust_reservation) (struct domain *d1, struct domain *d2) { diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 4134877..c5c6202 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -98,6 +98,7 @@ struct xsm_operations { int (*get_pod_target) (struct domain *d); int (*set_pod_target) (struct domain *d); + int (*memory_exchange) (struct domain *d); int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2); int (*memory_stat_reservation) (struct domain *d1, struct domain *d2); int (*memory_pin_page) (struct domain *d, struct page_info *page); @@ -455,6 +456,11 @@ static inline int xsm_set_pod_target (struct domain *d) return xsm_ops->set_pod_target(d); } +static inline int xsm_memory_exchange (struct domain *d) +{ + return xsm_ops->memory_exchange(d); +} + static inline int xsm_memory_adjust_reservation (struct domain *d1, struct domain *d2) { diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 1bf9de9..5915c5e 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -83,6 +83,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, get_pod_target); set_to_dummy_if_null(ops, set_pod_target); + set_to_dummy_if_null(ops, memory_exchange); set_to_dummy_if_null(ops, memory_adjust_reservation); set_to_dummy_if_null(ops, memory_stat_reservation); set_to_dummy_if_null(ops, memory_pin_page); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index f743be1..ad1c593 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -442,6 +442,11 @@ static int flask_set_pod_target(struct domain *d) return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SETPODTARGET); } +static int flask_memory_exchange(struct domain *d) +{ + return current_has_perm(d, SECCLASS_MMU, MMU__EXCHANGE); +} + static int flask_memory_adjust_reservation(struct domain *d1, struct domain *d2) { return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__ADJUST); @@ -1642,6 +1647,7 @@ static struct xsm_operations flask_ops = { .get_pod_target = flask_get_pod_target, .set_pod_target = flask_set_pod_target, + .memory_exchange = flask_memory_exchange, .memory_adjust_reservation = flask_memory_adjust_reservation, .memory_stat_reservation = flask_memory_stat_reservation, .memory_pin_page = flask_memory_pin_page, diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 5d4f316..b2c77b2 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -112,6 +112,7 @@ S_(SECCLASS_MMU, MMU__MEMORYMAP, "memorymap") S_(SECCLASS_MMU, MMU__REMOTE_REMAP, "remote_remap") S_(SECCLASS_MMU, MMU__MMUEXT_OP, "mmuext_op") + S_(SECCLASS_MMU, MMU__EXCHANGE, "exchange") S_(SECCLASS_SHADOW, SHADOW__DISABLE, "disable") S_(SECCLASS_SHADOW, SHADOW__ENABLE, "enable") S_(SECCLASS_SHADOW, SHADOW__LOGDIRTY, "logdirty") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index f970b50..acb0b1a 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -118,6 +118,7 @@ #define MMU__MEMORYMAP 0x00000800UL #define MMU__REMOTE_REMAP 0x00001000UL #define MMU__MMUEXT_OP 0x00002000UL +#define MMU__EXCHANGE 0x00004000UL #define SHADOW__DISABLE 0x00000001UL #define SHADOW__ENABLE 0x00000002UL -- 1.7.11.2
Daniel De Graaf
2012-Aug-06 14:32 UTC
[PATCH 18/18] xen: remove rcu_lock_target_domain_by_id
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/physdev.c | 20 +++++++++++++------- xen/common/domain.c | 34 ---------------------------------- xen/include/xen/sched.h | 14 -------------- 3 files changed, 13 insertions(+), 55 deletions(-) diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 0841a7a..37a4a29 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -87,9 +87,12 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p, int pirq, irq, ret = 0; void *map_data = NULL; - ret = rcu_lock_target_domain_by_id(domid, &d); - if ( ret ) - return ret; + d = rcu_lock_domain_by_id(domid); + if ( d == NULL ) + return -ESRCH; + + if ( d != current->domain && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; if ( domid == DOMID_SELF && is_hvm_domain(d) ) { @@ -213,11 +216,14 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p, int physdev_unmap_pirq(domid_t domid, int pirq) { struct domain *d; - int ret; + int ret = 0; - ret = rcu_lock_target_domain_by_id(domid, &d); - if ( ret ) - return ret; + d = rcu_lock_domain_by_id(domid); + if ( d == NULL ) + return -ESRCH; + + if ( d != current->domain && !IS_PRIV_FOR(current->domain, d) ) + return -EPERM; if ( is_hvm_domain(d) ) { diff --git a/xen/common/domain.c b/xen/common/domain.c index dbbc414..8989fa6 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -421,40 +421,6 @@ struct domain *rcu_lock_domain_by_id(domid_t dom) return d; } -int rcu_lock_target_domain_by_id(domid_t dom, struct domain **d) -{ - if ( dom == DOMID_SELF ) - { - *d = rcu_lock_current_domain(); - return 0; - } - - if ( (*d = rcu_lock_domain_by_id(dom)) == NULL ) - return -ESRCH; - - if ( !IS_PRIV_FOR(current->domain, *d) ) - { - rcu_unlock_domain(*d); - return -EPERM; - } - - return 0; -} - -int rcu_lock_remote_target_domain_by_id(domid_t dom, struct domain **d) -{ - if ( (*d = rcu_lock_domain_by_id(dom)) == NULL ) - return -ESRCH; - - if ( (*d == current->domain) || !IS_PRIV_FOR(current->domain, *d) ) - { - rcu_unlock_domain(*d); - return -EPERM; - } - - return 0; -} - int domain_kill(struct domain *d) { int rc = 0; diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 53804c8..73d82a8 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -446,20 +446,6 @@ struct domain *domain_create( */ struct domain *rcu_lock_domain_by_id(domid_t dom); -/* - * As above function, but accounts for current domain context: - * - Translates target DOMID_SELF into caller''s domain id; and - * - Checks that caller has permission to act on the target domain. - */ -int rcu_lock_target_domain_by_id(domid_t dom, struct domain **d); - -/* - * As rcu_lock_target_domain_by_id(), but will fail EPERM rather than resolve - * to local domain. Successful return always resolves to a remote domain that - * the local domain is privileged to control. - */ -int rcu_lock_remote_target_domain_by_id(domid_t dom, struct domain **d); - /* Finish a RCU critical region started by rcu_lock_domain_by_id(). */ static inline void rcu_unlock_domain(struct domain *d) { -- 1.7.11.2
Jan Beulich
2012-Aug-06 14:57 UTC
Re: [PATCH 07/18] arch/x86: add missing XSM checks to XENPF_ commands
>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote:What''s the point of doing XSM checks for Dom0-only interfaces anyway? I don''t see how these can be subject to disaggregation... Jan> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> > --- > tools/flask/policy/policy/modules/xen/xen.te | 4 ++-- > xen/arch/x86/platform_hypercall.c | 8 ++++++++ > 2 files changed, 10 insertions(+), 2 deletions(-) > > diff --git a/tools/flask/policy/policy/modules/xen/xen.te > b/tools/flask/policy/policy/modules/xen/xen.te > index 40c4c0a..1162153 100644 > --- a/tools/flask/policy/policy/modules/xen/xen.te > +++ b/tools/flask/policy/policy/modules/xen/xen.te > @@ -53,8 +53,8 @@ type device_t, resource_type; > # > > ############################################################################# > ### > allow dom0_t xen_t:xen { kexec readapic writeapic mtrr_read mtrr_add > mtrr_del > - scheduler physinfo heap quirk readconsole writeconsole settime > - microcode cpupool_op sched_op }; > + scheduler physinfo heap quirk readconsole writeconsole settime getcpuinfo > + microcode cpupool_op sched_op pm_op }; > allow dom0_t xen_t:mmu { memorymap }; > allow dom0_t security_t:security { check_context compute_av compute_create > compute_member load_policy compute_relabel compute_user setenforce > diff --git a/xen/arch/x86/platform_hypercall.c > b/xen/arch/x86/platform_hypercall.c > index 88880b0..c049db7 100644 > --- a/xen/arch/x86/platform_hypercall.c > +++ b/xen/arch/x86/platform_hypercall.c > @@ -501,6 +501,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) > u_xenpf_op) > { > struct xenpf_pcpu_version *ver = &op->u.pcpu_version; > > + ret = xsm_getcpuinfo(); > + if ( ret ) > + break; > + > if ( !get_cpu_maps() ) > { > ret = -EBUSY; > @@ -618,6 +622,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) > u_xenpf_op) > { > uint32_t idle_nums; > > + ret = xsm_pm_op(); > + if ( ret ) > + break; > + > switch(op->u.core_parking.type) > { > case XEN_CORE_PARKING_SET: > -- > 1.7.11.2 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Daniel De Graaf
2012-Aug-06 15:06 UTC
Re: [PATCH 07/18] arch/x86: add missing XSM checks to XENPF_ commands
On 08/06/2012 10:57 AM, Jan Beulich wrote:>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > > What''s the point of doing XSM checks for Dom0-only interfaces > anyway? I don''t see how these can be subject to disaggregation... > > Jan >When splitting up the domain builder and hardware access domains, the domain builder still needs to be privileged but should not have access the functions that manage the hardware. Similarly, the hardware domain has no need to use dom0 functions for accessing remote domains. This also allows exposing read-only interfaces like getcpuinfo to a domain containing something like OpenStack, instead of needing to proxy all such calls through dom0. -- Daniel De Graaf National Security Agency
Jan Beulich
2012-Aug-06 15:07 UTC
Re: [PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id
>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > Callers that want to prevent use of DOMID_SELF already need to ensure > the calling domain does not pass its own domain ID. This removes the > need for the caller to manually support DOMID_SELF, which many already > do.I''m not really sure this is correct. At the very least it changes the return value of rcu_lock_remote_target_domain_by_id() when called with DOMID_SELF (from -ESRCH to -EPERM). I''m also not convinced that a distinction between a domain knowing its ID and one passing DOMID_SELF isn''t/can''t be useful. That of course depends on whether the ID can be fully hidden from a guest (obviously pure HVM guests would never know their ID, but then again they also would never pass DOMID_SELF anywhere; it might be, however, that they could get the latter passed on their behalf e.g. from some emulation function). Jan> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> > --- > xen/common/domain.c | 3 +++ > xen/common/event_channel.c | 3 --- > xen/common/grant_table.c | 2 +- > 3 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/xen/common/domain.c b/xen/common/domain.c > index 4c5d241..dbbc414 100644 > --- a/xen/common/domain.c > +++ b/xen/common/domain.c > @@ -400,6 +400,9 @@ struct domain *rcu_lock_domain_by_id(domid_t dom) > { > struct domain *d = NULL; > > + if ( dom == DOMID_SELF ) > + return rcu_lock_current_domain(); > + > rcu_read_lock(&domlist_read_lock); > > for ( d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]); > diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c > index 53777f8..988d3ce 100644 > --- a/xen/common/event_channel.c > +++ b/xen/common/event_channel.c > @@ -201,9 +201,6 @@ static long > evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind) > domid_t rdom = bind->remote_dom; > long rc; > > - if ( rdom == DOMID_SELF ) > - rdom = current->domain->domain_id; > - > if ( (rd = rcu_lock_domain_by_id(rdom)) == NULL ) > return -ESRCH; > > diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c > index 9961e83..fbea67c 100644 > --- a/xen/common/grant_table.c > +++ b/xen/common/grant_table.c > @@ -715,7 +715,7 @@ __gnttab_map_grant_ref( > TRACE_1D(TRC_MEM_PAGE_GRANT_MAP, op->dom); > > mt = &maptrack_entry(lgt, handle); > - mt->domid = op->dom; > + mt->domid = rd->domain_id; > mt->ref = op->ref; > mt->flags = op->flags; > > -- > 1.7.11.2 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Jan Beulich
2012-Aug-06 15:18 UTC
Re: [PATCH 11/18] xen: use XSM instead of IS_PRIV where duplicated
>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > --- a/xen/arch/x86/domctl.c > +++ b/xen/arch/x86/domctl.c > @@ -54,6 +54,26 @@ long arch_do_domctl( > > switch ( domctl->cmd ) > { > + /* TODO: the following do not have XSM hooks yet */ > + case XEN_DOMCTL_set_cpuid: > + case XEN_DOMCTL_suppress_spurious_page_faults: > + case XEN_DOMCTL_debug_op: > + case XEN_DOMCTL_gettscinfo: > + case XEN_DOMCTL_settscinfo: > + case XEN_DOMCTL_audit_p2m: > + case XEN_DOMCTL_gdbsx_guestmemio: > + case XEN_DOMCTL_gdbsx_pausevcpu: > + case XEN_DOMCTL_gdbsx_unpausevcpu: > + case XEN_DOMCTL_gdbsx_domstatus: > + /* getpageframeinfo[23] will leak XEN_DOMCTL_PFINFO_XTAB on target GFNs */Is that to state that the patch introduces a leak here? Or are you trying to carefully tell us you spotted a problem in the existing code?> + case XEN_DOMCTL_getpageframeinfo2: > + case XEN_DOMCTL_getpageframeinfo3: > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + } > + > + switch ( domctl->cmd ) > + { > > case XEN_DOMCTL_shadow_op: > { > --- a/xen/arch/x86/hvm/hvm.c > +++ b/xen/arch/x86/hvm/hvm.c > @@ -3366,12 +3366,12 @@ static int hvmop_set_pci_intx_level( > if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) ) > return -EINVAL; > > - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); > - if ( rc != 0 ) > - return rc; > + d = rcu_lock_domain_by_id(op.domid); > + if ( d == NULL ) > + return -ESRCH; > > rc = -EINVAL; > - if ( !is_hvm_domain(d) ) > + if ( d == current->domain || !is_hvm_domain(d) )What''s wrong with rcu_lock_remote_target_domain_by_id() here and in other places below? I think this minimally would deserve a comment in the patch description, the more that this huge a patch is already bad enough to look at. Jan
Daniel De Graaf
2012-Aug-06 15:19 UTC
Re: [PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id
On 08/06/2012 11:07 AM, Jan Beulich wrote:>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >> Callers that want to prevent use of DOMID_SELF already need to ensure >> the calling domain does not pass its own domain ID. This removes the >> need for the caller to manually support DOMID_SELF, which many already >> do. > > I''m not really sure this is correct. At the very least it changes the > return value of rcu_lock_remote_target_domain_by_id() when > called with DOMID_SELF (from -ESRCH to -EPERM).This series ends up eliminating that function in patch #18, so that part is taken care of.> I''m also not convinced that a distinction between a domain knowing > its ID and one passing DOMID_SELF isn''t/can''t be useful. That of > course depends on whether the ID can be fully hidden from a guest > (obviously pure HVM guests would never know their ID, but then > again they also would never pass DOMID_SELF anywhere; it might > be, however, that they could get the latter passed on their behalf > e.g. from some emulation function). > > JanI don''t think we can (or want to) make it impossible for a guest to find out its own domain ID. I agree that the distinction between DOMID_SELF and my_own_domid can be a useful distinction in some cases. Most of those cases in Xen that I have seen already handle this at the caller. Another solution here is to create a function rcu_lock_domain_by_any_id that is identical to rcu_lock_domain_by_id except for handling DOMID_SELF. -- Daniel De Graaf National Security Agency
Daniel De Graaf
2012-Aug-06 15:25 UTC
Re: [PATCH 11/18] xen: use XSM instead of IS_PRIV where duplicated
On 08/06/2012 11:18 AM, Jan Beulich wrote:>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >> --- a/xen/arch/x86/domctl.c >> +++ b/xen/arch/x86/domctl.c >> @@ -54,6 +54,26 @@ long arch_do_domctl( >> >> switch ( domctl->cmd ) >> { >> + /* TODO: the following do not have XSM hooks yet */ >> + case XEN_DOMCTL_set_cpuid: >> + case XEN_DOMCTL_suppress_spurious_page_faults: >> + case XEN_DOMCTL_debug_op: >> + case XEN_DOMCTL_gettscinfo: >> + case XEN_DOMCTL_settscinfo: >> + case XEN_DOMCTL_audit_p2m: >> + case XEN_DOMCTL_gdbsx_guestmemio: >> + case XEN_DOMCTL_gdbsx_pausevcpu: >> + case XEN_DOMCTL_gdbsx_unpausevcpu: >> + case XEN_DOMCTL_gdbsx_domstatus: >> + /* getpageframeinfo[23] will leak XEN_DOMCTL_PFINFO_XTAB on target GFNs */ > > Is that to state that the patch introduces a leak here? Or are you > trying to carefully tell us you spotted a problem in the existing > code?This is an information leak, not a memory leak. It''s a (minor) problem with the placement of the existing XSM hooks allowing a domain to query information on remote domains. A later patch fixes this by adding an XSM hook for the entire query operation.>> + case XEN_DOMCTL_getpageframeinfo2: >> + case XEN_DOMCTL_getpageframeinfo3: >> + if ( !IS_PRIV(current->domain) ) >> + return -EPERM; >> + } >> + >> + switch ( domctl->cmd ) >> + { >> >> case XEN_DOMCTL_shadow_op: >> { >> --- a/xen/arch/x86/hvm/hvm.c >> +++ b/xen/arch/x86/hvm/hvm.c >> @@ -3366,12 +3366,12 @@ static int hvmop_set_pci_intx_level( >> if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) ) >> return -EINVAL; >> >> - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); >> - if ( rc != 0 ) >> - return rc; >> + d = rcu_lock_domain_by_id(op.domid); >> + if ( d == NULL ) >> + return -ESRCH; >> >> rc = -EINVAL; >> - if ( !is_hvm_domain(d) ) >> + if ( d == current->domain || !is_hvm_domain(d) ) > > What''s wrong with rcu_lock_remote_target_domain_by_id() here > and in other places below? I think this minimally would deserve > a comment in the patch description, the more that this huge a > patch is already bad enough to look at. > > Jan >The main reason for this change is that rcu_lock_remote_target_domain_by_id calls IS_PRIV, and this patch is attempting to remove the duplicated calls. Would you prefer making another rcu_lock_* function that only checks against current->domain and doesn''t include the IS_PRIV_FOR check? -- Daniel De Graaf National Security Agency
Jan Beulich
2012-Aug-06 15:26 UTC
Re: [PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks
>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > --- a/xen/arch/x86/mm.c > +++ b/xen/arch/x86/mm.c > @@ -2882,11 +2882,6 @@ static struct domain *get_pg_owner(domid_t domid) > pg_owner = rcu_lock_domain(dom_io); > break; > case DOMID_XEN: > - if ( !IS_PRIV(curr) ) > - { > - MEM_LOG("Cannot set foreign dom"); > - break; > - } > pg_owner = rcu_lock_domain(dom_xen); > break; > default: > @@ -2895,12 +2890,6 @@ static struct domain *get_pg_owner(domid_t domid) > MEM_LOG("Unknown domain ''%u''", domid); > break; > } > - if ( !IS_PRIV_FOR(curr, pg_owner) ) > - { > - MEM_LOG("Cannot set foreign dom"); > - rcu_unlock_domain(pg_owner); > - pg_owner = NULL; > - } > break; > } > > @@ -3008,6 +2997,13 @@ int do_mmuext_op( > goto out; > } > > + rc = xsm_mmuext_op(d, pg_owner);Given the above, this could be xsm_mmuext_op(dom0, DOMID_{IO,XEN}); yet ...> + if ( rc ) > + { > + rcu_unlock_domain(pg_owner); > + goto out; > + } > + > for ( i = 0; i < count; i++ ) > { > if ( hypercall_preempt_check() ) > @@ -3483,11 +3479,6 @@ int do_mmu_update( > rc = -EINVAL; > goto out; > } > - if ( !IS_PRIV_FOR(d, pt_owner) ) > - { > - rc = -ESRCH; > - goto out; > - } > } > > if ( (pg_owner = get_pg_owner((uint16_t)foreigndom)) == NULL ) > @@ -3643,7 +3634,7 @@ int do_mmu_update( > mfn = req.ptr >> PAGE_SHIFT; > gpfn = req.val; > > - rc = xsm_mmu_machphys_update(d, mfn); > + rc = xsm_mmu_machphys_update(d, pg_owner, mfn); > if ( rc ) > break; > > --- a/xen/include/xsm/dummy.h > +++ b/xen/include/xsm/dummy.h > @@ -803,19 +803,35 @@ static XSM_DEFAULT(int, domain_memory_map) (struct domain *d) > } > > static XSM_DEFAULT(int, mmu_normal_update) (struct domain *d, struct domain *t, > - struct domain *f, intpte_t fpte) > + struct domain *f, intpte_t fpte) > { > + if ( d != t && !IS_PRIV_FOR(d, t) ) > + return -EPERM; > + if ( d != f && !IS_PRIV_FOR(d, f) ) > + return -EPERM; > return 0; > } > > -static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, unsigned long mfn) > +static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, struct domain *f, > + unsigned long mfn) > { > + if ( d != f && !IS_PRIV_FOR(d, f) ) > + return -EPERM; > + return 0; > +} > + > +static XSM_DEFAULT(int, mmuext_op) (struct domain *d, struct domain *f) > +{ > + if ( d != f && !IS_PRIV_FOR(d, f) ) > + return -EPERM;... Dom0 is neither privileged for DOM_IO nor for DOM_XEN.> return 0; > } > > static XSM_DEFAULT(int, update_va_mapping) (struct domain *d, struct domain *f, > l1_pgentry_t pte) > { > + if ( d != f && !IS_PRIV_FOR(d, f) ) > + return -EPERM; > return 0; > } >Didn''t check the other cases in any detail. Jan
Jan Beulich
2012-Aug-06 15:50 UTC
Re: [PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id
>>> On 06.08.12 at 17:19, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > On 08/06/2012 11:07 AM, Jan Beulich wrote: >>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>> Callers that want to prevent use of DOMID_SELF already need to ensure >>> the calling domain does not pass its own domain ID. This removes the >>> need for the caller to manually support DOMID_SELF, which many already >>> do. >> >> I''m not really sure this is correct. At the very least it changes the >> return value of rcu_lock_remote_target_domain_by_id() when >> called with DOMID_SELF (from -ESRCH to -EPERM). > > This series ends up eliminating that function in patch #18, so that > part is taken care of.But may, in case of problems, then not be fully bi-sectable.>> I''m also not convinced that a distinction between a domain knowing >> its ID and one passing DOMID_SELF isn''t/can''t be useful. That of >> course depends on whether the ID can be fully hidden from a guest >> (obviously pure HVM guests would never know their ID, but then >> again they also would never pass DOMID_SELF anywhere; it might >> be, however, that they could get the latter passed on their behalf >> e.g. from some emulation function). > > I don''t think we can (or want to) make it impossible for a guest to find > out its own domain ID. I agree that the distinction between DOMID_SELF and > my_own_domid can be a useful distinction in some cases. Most of those cases > in Xen that I have seen already handle this at the caller. > > Another solution here is to create a function rcu_lock_domain_by_any_id that > is identical to rcu_lock_domain_by_id except for handling DOMID_SELF.Maybe. I''d like to see Keir''s position regarding all of the details here anyway. Jan
Jan Beulich
2012-Aug-06 15:53 UTC
Re: [PATCH 11/18] xen: use XSM instead of IS_PRIV where duplicated
>>> On 06.08.12 at 17:25, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > On 08/06/2012 11:18 AM, Jan Beulich wrote: >>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>> --- a/xen/arch/x86/hvm/hvm.c >>> +++ b/xen/arch/x86/hvm/hvm.c >>> @@ -3366,12 +3366,12 @@ static int hvmop_set_pci_intx_level( >>> if ( (op.domain > 0) || (op.bus > 0) || (op.device > 31) || (op.intx > 3) ) >>> return -EINVAL; >>> >>> - rc = rcu_lock_remote_target_domain_by_id(op.domid, &d); >>> - if ( rc != 0 ) >>> - return rc; >>> + d = rcu_lock_domain_by_id(op.domid); >>> + if ( d == NULL ) >>> + return -ESRCH; >>> >>> rc = -EINVAL; >>> - if ( !is_hvm_domain(d) ) >>> + if ( d == current->domain || !is_hvm_domain(d) ) >> >> What''s wrong with rcu_lock_remote_target_domain_by_id() here >> and in other places below? I think this minimally would deserve >> a comment in the patch description, the more that this huge a >> patch is already bad enough to look at. > > The main reason for this change is that rcu_lock_remote_target_domain_by_id > calls IS_PRIV, and this patch is attempting to remove the duplicated calls. > Would you prefer making another rcu_lock_* function that only checks against > current->domain and doesn''t include the IS_PRIV_FOR check?Yes, I think the restructuring should be so that no new "d == current->domain" or alike get introduced (or at least not as many of them as this patch did). Jan
Daniel De Graaf
2012-Aug-06 16:29 UTC
Re: [PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks
On 08/06/2012 11:26 AM, Jan Beulich wrote:>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >> --- a/xen/arch/x86/mm.c >> +++ b/xen/arch/x86/mm.c >> @@ -2882,11 +2882,6 @@ static struct domain *get_pg_owner(domid_t domid) >> pg_owner = rcu_lock_domain(dom_io); >> break; >> case DOMID_XEN: >> - if ( !IS_PRIV(curr) ) >> - { >> - MEM_LOG("Cannot set foreign dom"); >> - break; >> - } >> pg_owner = rcu_lock_domain(dom_xen); >> break; >> default: >> @@ -2895,12 +2890,6 @@ static struct domain *get_pg_owner(domid_t domid) >> MEM_LOG("Unknown domain ''%u''", domid); >> break; >> } >> - if ( !IS_PRIV_FOR(curr, pg_owner) ) >> - { >> - MEM_LOG("Cannot set foreign dom"); >> - rcu_unlock_domain(pg_owner); >> - pg_owner = NULL; >> - } >> break; >> } >> >> @@ -3008,6 +2997,13 @@ int do_mmuext_op( >> goto out; >> } >> >> + rc = xsm_mmuext_op(d, pg_owner); > > Given the above, this could be > > xsm_mmuext_op(dom0, DOMID_{IO,XEN}); > > yet ... > >> + if ( rc ) >> + { >> + rcu_unlock_domain(pg_owner); >> + goto out; >> + } >> + >> for ( i = 0; i < count; i++ ) >> { >> if ( hypercall_preempt_check() ) >> @@ -3483,11 +3479,6 @@ int do_mmu_update( >> rc = -EINVAL; >> goto out; >> } >> - if ( !IS_PRIV_FOR(d, pt_owner) ) >> - { >> - rc = -ESRCH; >> - goto out; >> - } >> } >> >> if ( (pg_owner = get_pg_owner((uint16_t)foreigndom)) == NULL ) >> @@ -3643,7 +3634,7 @@ int do_mmu_update( >> mfn = req.ptr >> PAGE_SHIFT; >> gpfn = req.val; >> >> - rc = xsm_mmu_machphys_update(d, mfn); >> + rc = xsm_mmu_machphys_update(d, pg_owner, mfn); >> if ( rc ) >> break; >> >> --- a/xen/include/xsm/dummy.h >> +++ b/xen/include/xsm/dummy.h >> @@ -803,19 +803,35 @@ static XSM_DEFAULT(int, domain_memory_map) (struct domain *d) >> } >> >> static XSM_DEFAULT(int, mmu_normal_update) (struct domain *d, struct domain *t, >> - struct domain *f, intpte_t fpte) >> + struct domain *f, intpte_t fpte) >> { >> + if ( d != t && !IS_PRIV_FOR(d, t) ) >> + return -EPERM; >> + if ( d != f && !IS_PRIV_FOR(d, f) ) >> + return -EPERM; >> return 0; >> } >> >> -static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, unsigned long mfn) >> +static XSM_DEFAULT(int, mmu_machphys_update) (struct domain *d, struct domain *f, >> + unsigned long mfn) >> { >> + if ( d != f && !IS_PRIV_FOR(d, f) ) >> + return -EPERM; >> + return 0; >> +} >> + >> +static XSM_DEFAULT(int, mmuext_op) (struct domain *d, struct domain *f) >> +{ >> + if ( d != f && !IS_PRIV_FOR(d, f) ) >> + return -EPERM; > > ... Dom0 is neither privileged for DOM_IO nor for DOM_XEN.Actually, it is. IS_PRIV_FOR returns true for any domain when called from an IS_PRIV domain.> >> return 0; >> } >> >> static XSM_DEFAULT(int, update_va_mapping) (struct domain *d, struct domain *f, >> l1_pgentry_t pte) >> { >> + if ( d != f && !IS_PRIV_FOR(d, f) ) >> + return -EPERM; >> return 0; >> } >> > > Didn''t check the other cases in any detail. > > Jan >-- Daniel De Graaf National Security Agency
Daniel De Graaf
2012-Aug-06 16:38 UTC
Re: [PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id
On 08/06/2012 11:50 AM, Jan Beulich wrote:>>>> On 06.08.12 at 17:19, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >> On 08/06/2012 11:07 AM, Jan Beulich wrote: >>>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>>> Callers that want to prevent use of DOMID_SELF already need to ensure >>>> the calling domain does not pass its own domain ID. This removes the >>>> need for the caller to manually support DOMID_SELF, which many already >>>> do. >>> >>> I''m not really sure this is correct. At the very least it changes the >>> return value of rcu_lock_remote_target_domain_by_id() when >>> called with DOMID_SELF (from -ESRCH to -EPERM). >> >> This series ends up eliminating that function in patch #18, so that >> part is taken care of. > > But may, in case of problems, then not be fully bi-sectable.Do we depend on the exact error return codes in non-error code paths? I would think most attempts to bisect would work just fine as the function will still be returning an error. I''m not sure ESRCH is really the best error to return here anyway: the problem is not that a domain with my_own_domid or DOMID_SELF couldn''t be found, it''s that you can''t specify that domain for this operation.>>> I''m also not convinced that a distinction between a domain knowing >>> its ID and one passing DOMID_SELF isn''t/can''t be useful. That of >>> course depends on whether the ID can be fully hidden from a guest >>> (obviously pure HVM guests would never know their ID, but then >>> again they also would never pass DOMID_SELF anywhere; it might >>> be, however, that they could get the latter passed on their behalf >>> e.g. from some emulation function). >> >> I don''t think we can (or want to) make it impossible for a guest to find >> out its own domain ID. I agree that the distinction between DOMID_SELF and >> my_own_domid can be a useful distinction in some cases. Most of those cases >> in Xen that I have seen already handle this at the caller. >> >> Another solution here is to create a function rcu_lock_domain_by_any_id that >> is identical to rcu_lock_domain_by_id except for handling DOMID_SELF. > > Maybe. I''d like to see Keir''s position regarding all of the details > here anyway. > > Jan > > >-- Daniel De Graaf National Security Agency
Keir Fraser
2012-Aug-06 18:53 UTC
Re: [PATCH 12/18] xsm: Add missing domctl and mem_sharing hooks
When someone wants to add a new domctl/sysctl, how many places will they have to add things to ensure that xsm dtrt for a basic setup, allowing only dom0 access to the new op? How big is the risk that we end up with new ops that have no access control? On 06/08/2012 15:32, "Daniel De Graaf" <dgdegra@tycho.nsa.gov> wrote:> This patch adds new XSM hooks to cover the 12 domctls that were not > previously covered by an XSM hook, and splits up the mem_sharing and > mem_event XSM hooks to better cover what the code is doing. > > Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> > --- > tools/flask/policy/policy/flask/access_vectors | 5 + > tools/flask/policy/policy/modules/xen/xen.if | 2 + > xen/arch/x86/domctl.c | 125 > +++++++++++++++---------- > xen/arch/x86/mm/mem_event.c | 45 ++++----- > xen/arch/x86/mm/mem_sharing.c | 23 ++++- > xen/include/asm-x86/mem_event.h | 1 - > xen/include/xsm/dummy.h | 65 ++++++++++++- > xen/include/xsm/xsm.h | 62 +++++++++++- > xen/xsm/dummy.c | 11 ++- > xen/xsm/flask/hooks.c | 62 +++++++++++- > xen/xsm/flask/include/av_perm_to_string.h | 5 + > xen/xsm/flask/include/av_permissions.h | 5 + > 12 files changed, 318 insertions(+), 93 deletions(-) > > diff --git a/tools/flask/policy/policy/flask/access_vectors > b/tools/flask/policy/policy/flask/access_vectors > index 11d02da..28b8ada 100644 > --- a/tools/flask/policy/policy/flask/access_vectors > +++ b/tools/flask/policy/policy/flask/access_vectors > @@ -80,6 +80,9 @@ class domain2 > relabelself > make_priv_for > set_as_target > + set_cpuid > + gettsc > + settsc > } > > class hvm > @@ -97,6 +100,8 @@ class hvm > hvmctl > mem_event > mem_sharing > + share_mem > + audit_p2m > } > > class event > diff --git a/tools/flask/policy/policy/modules/xen/xen.if > b/tools/flask/policy/policy/modules/xen/xen.if > index 4de99c8..f9bd757 100644 > --- a/tools/flask/policy/policy/modules/xen/xen.if > +++ b/tools/flask/policy/policy/modules/xen/xen.if > @@ -29,6 +29,7 @@ define(`create_domain_common'', ` > getdomaininfo hypercall setvcpucontext setextvcpucontext > scheduler getvcpuinfo getvcpuextstate getaddrsize > getvcpuaffinity setvcpuaffinity }; > + allow $1 $2:domain2 { set_cpuid settsc }; > allow $1 $2:security check_context; > allow $1 $2:shadow enable; > allow $1 $2:mmu {map_read map_write adjust memorymap physmap pinpage}; > @@ -67,6 +68,7 @@ define(`migrate_domain_out'', ` > allow $1 $2:hvm { gethvmc getparam irqlevel }; > allow $1 $2:mmu { stat pageinfo map_read }; > allow $1 $2:domain { getaddrsize getvcpucontext getextvcpucontext > getvcpuextstate pause destroy }; > + allow $1 $2:domain2 gettsc; > '') > > > ############################################################################## > ## > diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c > index bcb5b2d..95f34d2 100644 > --- a/xen/arch/x86/domctl.c > +++ b/xen/arch/x86/domctl.c > @@ -54,26 +54,6 @@ long arch_do_domctl( > > switch ( domctl->cmd ) > { > - /* TODO: the following do not have XSM hooks yet */ > - case XEN_DOMCTL_set_cpuid: > - case XEN_DOMCTL_suppress_spurious_page_faults: > - case XEN_DOMCTL_debug_op: > - case XEN_DOMCTL_gettscinfo: > - case XEN_DOMCTL_settscinfo: > - case XEN_DOMCTL_audit_p2m: > - case XEN_DOMCTL_gdbsx_guestmemio: > - case XEN_DOMCTL_gdbsx_pausevcpu: > - case XEN_DOMCTL_gdbsx_unpausevcpu: > - case XEN_DOMCTL_gdbsx_domstatus: > - /* getpageframeinfo[23] will leak XEN_DOMCTL_PFINFO_XTAB on target GFNs > */ > - case XEN_DOMCTL_getpageframeinfo2: > - case XEN_DOMCTL_getpageframeinfo3: > - if ( !IS_PRIV(current->domain) ) > - return -EPERM; > - } > - > - switch ( domctl->cmd ) > - { > > case XEN_DOMCTL_shadow_op: > { > @@ -190,6 +170,13 @@ long arch_do_domctl( > if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) ) > break; > > + ret = xsm_getpageframeinfo_domain(d); > + if ( ret ) > + { > + rcu_unlock_domain(d); > + break; > + } > + > if ( unlikely(num > 1024) || > unlikely(num != domctl->u.getpageframeinfo3.num) ) > { > @@ -287,6 +274,13 @@ long arch_do_domctl( > if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) ) > break; > > + ret = xsm_getpageframeinfo_domain(d); > + if ( ret ) > + { > + rcu_unlock_domain(d); > + break; > + } > + > if ( unlikely(num > 1024) ) > { > ret = -E2BIG; > @@ -1106,6 +1100,10 @@ long arch_do_domctl( > if ( d == NULL ) > break; > > + ret = xsm_set_cpuid(d); > + if ( ret ) > + goto set_cpuid_out; > + > for ( i = 0; i < MAX_CPUID_INPUT; i++ ) > { > cpuid = &d->arch.cpuids[i]; > @@ -1129,6 +1127,7 @@ long arch_do_domctl( > ret = 0; > } > > + set_cpuid_out: > rcu_unlock_domain(d); > } > break; > @@ -1143,6 +1142,10 @@ long arch_do_domctl( > if ( d == NULL ) > break; > > + ret = xsm_gettscinfo(d); > + if ( ret ) > + goto gettscinfo_out; > + > domain_pause(d); > tsc_get_info(d, &info.tsc_mode, > &info.elapsed_nsec, > @@ -1154,6 +1157,7 @@ long arch_do_domctl( > ret = 0; > domain_unpause(d); > > + gettscinfo_out: > rcu_unlock_domain(d); > } > break; > @@ -1167,15 +1171,20 @@ long arch_do_domctl( > if ( d == NULL ) > break; > > + ret = xsm_settscinfo(d); > + if ( ret ) > + goto settscinfo_out; > + > domain_pause(d); > tsc_set_info(d, domctl->u.tsc_info.info.tsc_mode, > domctl->u.tsc_info.info.elapsed_nsec, > domctl->u.tsc_info.info.gtsc_khz, > domctl->u.tsc_info.info.incarnation); > domain_unpause(d); > + ret = 0; > > + settscinfo_out: > rcu_unlock_domain(d); > - ret = 0; > } > break; > > @@ -1187,9 +1196,10 @@ long arch_do_domctl( > d = rcu_lock_domain_by_id(domctl->domain); > if ( d != NULL ) > { > - d->arch.suppress_spurious_page_faults = 1; > + ret = xsm_domctl(d, domctl->cmd); > + if ( !ret ) > + d->arch.suppress_spurious_page_faults = 1; > rcu_unlock_domain(d); > - ret = 0; > } > } > break; > @@ -1204,6 +1214,10 @@ long arch_do_domctl( > if ( d == NULL ) > break; > > + ret = xsm_debug_op(d); > + if ( ret ) > + goto debug_op_out; > + > ret = -EINVAL; > if ( (domctl->u.debug_op.vcpu >= d->max_vcpus) || > ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) ) > @@ -1228,6 +1242,10 @@ long arch_do_domctl( > if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) > break; > > + ret = xsm_debug_op(d); > + if ( ret ) > + goto gdbsx_guestmemio_out; > + > domctl->u.gdbsx_guest_memio.remain > domctl->u.gdbsx_guest_memio.len; > > @@ -1235,6 +1253,7 @@ long arch_do_domctl( > if ( !ret && copy_to_guest(u_domctl, domctl, 1) ) > ret = -EFAULT; > > + gdbsx_guestmemio_out: > rcu_unlock_domain(d); > } > break; > @@ -1248,21 +1267,20 @@ long arch_do_domctl( > if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) > break; > > + ret = xsm_debug_op(d); > + if ( ret ) > + goto gdbsx_pausevcpu_out; > + > ret = -EBUSY; > if ( !d->is_paused_by_controller ) > - { > - rcu_unlock_domain(d); > - break; > - } > + goto gdbsx_pausevcpu_out; > ret = -EINVAL; > if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= MAX_VIRT_CPUS || > (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL ) > - { > - rcu_unlock_domain(d); > - break; > - } > + goto gdbsx_pausevcpu_out; > vcpu_pause(v); > ret = 0; > + gdbsx_pausevcpu_out: > rcu_unlock_domain(d); > } > break; > @@ -1276,23 +1294,22 @@ long arch_do_domctl( > if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) > break; > > + ret = xsm_debug_op(d); > + if ( ret ) > + goto gdbsx_unpausevcpu_out; > + > ret = -EBUSY; > if ( !d->is_paused_by_controller ) > - { > - rcu_unlock_domain(d); > - break; > - } > + goto gdbsx_unpausevcpu_out; > ret = -EINVAL; > if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= MAX_VIRT_CPUS || > (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL ) > - { > - rcu_unlock_domain(d); > - break; > - } > + goto gdbsx_unpausevcpu_out; > if ( !atomic_read(&v->pause_count) ) > printk("WARN: Unpausing vcpu:%d which is not paused\n", > v->vcpu_id); > vcpu_unpause(v); > ret = 0; > + gdbsx_unpausevcpu_out: > rcu_unlock_domain(d); > } > break; > @@ -1306,6 +1323,10 @@ long arch_do_domctl( > if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) > break; > > + ret = xsm_debug_op(d); > + if ( ret ) > + goto gdbsx_domstatus_out; > + > domctl->u.gdbsx_domstatus.vcpu_id = -1; > domctl->u.gdbsx_domstatus.paused = d->is_paused_by_controller; > if ( domctl->u.gdbsx_domstatus.paused ) > @@ -1325,6 +1346,7 @@ long arch_do_domctl( > ret = 0; > if ( copy_to_guest(u_domctl, domctl, 1) ) > ret = -EFAULT; > + gdbsx_domstatus_out: > rcu_unlock_domain(d); > } > break; > @@ -1464,10 +1486,8 @@ long arch_do_domctl( > d = rcu_lock_domain_by_id(domctl->domain); > if ( d != NULL ) > { > - ret = xsm_mem_event(d); > - if ( !ret ) > - ret = mem_event_domctl(d, &domctl->u.mem_event_op, > - guest_handle_cast(u_domctl, void)); > + ret = mem_event_domctl(d, &domctl->u.mem_event_op, > + guest_handle_cast(u_domctl, void)); > rcu_unlock_domain(d); > copy_to_guest(u_domctl, domctl, 1); > } > @@ -1496,16 +1516,19 @@ long arch_do_domctl( > { > struct domain *d; > > - ret = rcu_lock_remote_target_domain_by_id(domctl->domain, &d); > - if ( ret != 0 ) > + d = rcu_lock_domain_by_id(domctl->domain); > + if ( d == NULL ) > break; > > - audit_p2m(d, > - &domctl->u.audit_p2m.orphans, > - &domctl->u.audit_p2m.m2p_bad, > - &domctl->u.audit_p2m.p2m_bad); > + ret = xsm_audit_p2m(d); > + if ( !ret ) > + audit_p2m(d, > + &domctl->u.audit_p2m.orphans, > + &domctl->u.audit_p2m.m2p_bad, > + &domctl->u.audit_p2m.p2m_bad); > + > rcu_unlock_domain(d); > - if ( copy_to_guest(u_domctl, domctl, 1) ) > + if ( !ret && copy_to_guest(u_domctl, domctl, 1) ) > ret = -EFAULT; > } > break; > @@ -1524,7 +1547,7 @@ long arch_do_domctl( > d = rcu_lock_domain_by_id(domctl->domain); > if ( d != NULL ) > { > - ret = xsm_mem_event(d); > + ret = xsm_mem_event_setup(d); > if ( !ret ) { > p2m = p2m_get_hostp2m(d); > p2m->access_required > domctl->u.access_required.access_required; > diff --git a/xen/arch/x86/mm/mem_event.c b/xen/arch/x86/mm/mem_event.c > index d728889..a5b02d9 100644 > --- a/xen/arch/x86/mm/mem_event.c > +++ b/xen/arch/x86/mm/mem_event.c > @@ -29,6 +29,7 @@ > #include <asm/mem_paging.h> > #include <asm/mem_access.h> > #include <asm/mem_sharing.h> > +#include <xsm/xsm.h> > > /* for public/io/ring.h macros */ > #define xen_mb() mb() > @@ -439,34 +440,22 @@ static void mem_sharing_notification(struct vcpu *v, > unsigned int port) > mem_sharing_sharing_resume(v->domain); > } > > -struct domain *get_mem_event_op_target(uint32_t domain, int *rc) > -{ > - struct domain *d; > - > - /* Get the target domain */ > - *rc = rcu_lock_remote_target_domain_by_id(domain, &d); > - if ( *rc != 0 ) > - return NULL; > - > - /* Not dying? */ > - if ( d->is_dying ) > - { > - rcu_unlock_domain(d); > - *rc = -EINVAL; > - return NULL; > - } > - > - return d; > -} > - > int do_mem_event_op(int op, uint32_t domain, void *arg) > { > int ret; > struct domain *d; > > - d = get_mem_event_op_target(domain, &ret); > + d = rcu_lock_domain_by_id(domain); > if ( !d ) > - return ret; > + return -ESRCH; > + > + ret = -EINVAL; > + if ( d->is_dying || d == current->domain ) > + goto out; > + > + ret = xsm_mem_event_op(d, op); > + if ( ret ) > + goto out; > > switch (op) > { > @@ -483,6 +472,7 @@ int do_mem_event_op(int op, uint32_t domain, void *arg) > ret = -ENOSYS; > } > > + out: > rcu_unlock_domain(d); > return ret; > } > @@ -516,6 +506,10 @@ int mem_event_domctl(struct domain *d, > xen_domctl_mem_event_op_t *mec, > { > int rc; > > + rc = xsm_mem_event_control(d, mec->mode, mec->op); > + if ( rc ) > + return rc; > + > if ( unlikely(d == current->domain) ) > { > gdprintk(XENLOG_INFO, "Tried to do a memory event op on itself.\n"); > @@ -537,13 +531,6 @@ int mem_event_domctl(struct domain *d, > xen_domctl_mem_event_op_t *mec, > return -EINVAL; > } > > - /* TODO: XSM hook */ > -#if 0 > - rc = xsm_mem_event_control(d, mec->op); > - if ( rc ) > - return rc; > -#endif > - > rc = -ENOSYS; > > switch ( mec->mode ) > diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c > index 5103285..a7e6c5c 100644 > --- a/xen/arch/x86/mm/mem_sharing.c > +++ b/xen/arch/x86/mm/mem_sharing.c > @@ -34,6 +34,7 @@ > #include <asm/atomic.h> > #include <xen/rcupdate.h> > #include <asm/event.h> > +#include <xsm/xsm.h> > > #include "mm-locks.h" > > @@ -1345,11 +1346,18 @@ int mem_sharing_memop(struct domain *d, > xen_mem_sharing_op_t *mec) > if ( !mem_sharing_enabled(d) ) > return -EINVAL; > > - cd = get_mem_event_op_target(mec->u.share.client_domain, &rc); > + cd = rcu_lock_domain_by_id(mec->u.share.client_domain); > if ( !cd ) > + return -ESRCH; > + > + rc = xsm_mem_sharing_op(d, cd, mec->op); > + if ( rc ) > + { > + rcu_unlock_domain(cd); > return rc; > + } > > - if ( !mem_sharing_enabled(cd) ) > + if ( cd == current->domain || !mem_sharing_enabled(cd) ) > { > rcu_unlock_domain(cd); > return -EINVAL; > @@ -1401,11 +1409,18 @@ int mem_sharing_memop(struct domain *d, > xen_mem_sharing_op_t *mec) > if ( !mem_sharing_enabled(d) ) > return -EINVAL; > > - cd = get_mem_event_op_target(mec->u.share.client_domain, &rc); > + cd = rcu_lock_domain_by_id(mec->u.share.client_domain); > if ( !cd ) > + return -ESRCH; > + > + rc = xsm_mem_sharing_op(d, cd, mec->op); > + if ( rc ) > + { > + rcu_unlock_domain(cd); > return rc; > + } > > - if ( !mem_sharing_enabled(cd) ) > + if ( cd == current->domain || !mem_sharing_enabled(cd) ) > { > rcu_unlock_domain(cd); > return -EINVAL; > diff --git a/xen/include/asm-x86/mem_event.h b/xen/include/asm-x86/mem_event.h > index 23d71c1..448be4f 100644 > --- a/xen/include/asm-x86/mem_event.h > +++ b/xen/include/asm-x86/mem_event.h > @@ -62,7 +62,6 @@ void mem_event_put_request(struct domain *d, struct > mem_event_domain *med, > int mem_event_get_response(struct domain *d, struct mem_event_domain *med, > mem_event_response_t *rsp); > > -struct domain *get_mem_event_op_target(uint32_t domain, int *rc); > int do_mem_event_op(int op, uint32_t domain, void *arg); > int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, > XEN_GUEST_HANDLE(void) u_domctl); > diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h > index 0d849cc..c71c08b 100644 > --- a/xen/include/xsm/dummy.h > +++ b/xen/include/xsm/dummy.h > @@ -171,6 +171,13 @@ static XSM_DEFAULT(int, setdebugging) (struct domain *d) > return 0; > } > > +static XSM_DEFAULT(int, debug_op) (struct domain *d) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > static XSM_DEFAULT(int, perfcontrol) (void) > { > if ( !IS_PRIV(current->domain) ) > @@ -557,6 +564,34 @@ static XSM_DEFAULT(int, getpageframeinfo) (struct > page_info *page) > return 0; > } > > +static XSM_DEFAULT(int, getpageframeinfo_domain) (struct domain *d) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > +static XSM_DEFAULT(int, set_cpuid) (struct domain *d) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > +static XSM_DEFAULT(int, gettscinfo) (struct domain *d) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > +static XSM_DEFAULT(int, settscinfo) (struct domain *d) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > static XSM_DEFAULT(int, getmemlist) (struct domain *d) > { > if ( !IS_PRIV(current->domain) ) > @@ -627,13 +662,27 @@ static XSM_DEFAULT(int, hvm_inject_msi) (struct domain > *d) > return 0; > } > > -static XSM_DEFAULT(int, mem_event) (struct domain *d) > +static XSM_DEFAULT(int, mem_event_setup) (struct domain *d) > { > if ( !IS_PRIV(current->domain) ) > return -EPERM; > return 0; > } > > +static XSM_DEFAULT(int, mem_event_control) (struct domain *d, int mode, int > op) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > +static XSM_DEFAULT(int, mem_event_op) (struct domain *d, int op) > +{ > + if ( !IS_PRIV_FOR(current->domain, d) ) > + return -EPERM; > + return 0; > +} > + > static XSM_DEFAULT(int, mem_sharing) (struct domain *d) > { > if ( !IS_PRIV(current->domain) ) > @@ -641,6 +690,20 @@ static XSM_DEFAULT(int, mem_sharing) (struct domain *d) > return 0; > } > > +static XSM_DEFAULT(int, mem_sharing_op) (struct domain *d, struct domain *cd, > int op) > +{ > + if ( !IS_PRIV_FOR(current->domain, cd) ) > + return -EPERM; > + return 0; > +} > + > +static XSM_DEFAULT(int, audit_p2m) (struct domain *d) > +{ > + if ( !IS_PRIV(current->domain) ) > + return -EPERM; > + return 0; > +} > + > static XSM_DEFAULT(int, apic) (struct domain *d, int cmd) > { > if ( !IS_PRIV(current->domain) ) > diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h > index 1a9f35b..b473b54 100644 > --- a/xen/include/xsm/xsm.h > +++ b/xen/include/xsm/xsm.h > @@ -67,6 +67,7 @@ struct xsm_operations { > int (*setdomainmaxmem) (struct domain *d); > int (*setdomainhandle) (struct domain *d); > int (*setdebugging) (struct domain *d); > + int (*debug_op) (struct domain *d); > int (*perfcontrol) (void); > int (*debug_keys) (void); > int (*getcpuinfo) (void); > @@ -142,6 +143,10 @@ struct xsm_operations { > #ifdef CONFIG_X86 > int (*shadow_control) (struct domain *d, uint32_t op); > int (*getpageframeinfo) (struct page_info *page); > + int (*getpageframeinfo_domain) (struct domain *d); > + int (*set_cpuid) (struct domain *d); > + int (*gettscinfo) (struct domain *d); > + int (*settscinfo) (struct domain *d); > int (*getmemlist) (struct domain *d); > int (*hypercall_init) (struct domain *d); > int (*hvmcontext) (struct domain *d, uint32_t op); > @@ -152,8 +157,12 @@ struct xsm_operations { > int (*hvm_set_isa_irq_level) (struct domain *d); > int (*hvm_set_pci_link_route) (struct domain *d); > int (*hvm_inject_msi) (struct domain *d); > - int (*mem_event) (struct domain *d); > + int (*mem_event_setup) (struct domain *d); > + int (*mem_event_control) (struct domain *d, int mode, int op); > + int (*mem_event_op) (struct domain *d, int op); > int (*mem_sharing) (struct domain *d); > + int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op); > + int (*audit_p2m) (struct domain *d); > int (*apic) (struct domain *d, int cmd); > int (*xen_settime) (void); > int (*memtype) (uint32_t access); > @@ -302,6 +311,11 @@ static inline int xsm_setdebugging (struct domain *d) > return xsm_call(setdebugging(d)); > } > > +static inline int xsm_debug_op (struct domain *d) > +{ > + return xsm_call(debug_op(d)); > +} > + > static inline int xsm_perfcontrol (void) > { > return xsm_call(perfcontrol()); > @@ -329,7 +343,7 @@ static inline int xsm_get_pmstat(void) > > static inline int xsm_setpminfo(void) > { > - return xsm_call(setpminfo()); > + return xsm_call(setpminfo()); > } > > static inline int xsm_pm_op(void) > @@ -608,6 +622,26 @@ static inline int xsm_getpageframeinfo (struct page_info > *page) > return xsm_call(getpageframeinfo(page)); > } > > +static inline int xsm_getpageframeinfo_domain (struct domain *d) > +{ > + return xsm_call(getpageframeinfo_domain(d)); > +} > + > +static inline int xsm_set_cpuid (struct domain *d) > +{ > + return xsm_call(set_cpuid(d)); > +} > + > +static inline int xsm_gettscinfo (struct domain *d) > +{ > + return xsm_call(gettscinfo(d)); > +} > + > +static inline int xsm_settscinfo (struct domain *d) > +{ > + return xsm_call(settscinfo(d)); > +} > + > static inline int xsm_getmemlist (struct domain *d) > { > return xsm_call(getmemlist(d)); > @@ -658,9 +692,19 @@ static inline int xsm_hvm_inject_msi (struct domain *d) > return xsm_call(hvm_inject_msi(d)); > } > > -static inline int xsm_mem_event (struct domain *d) > +static inline int xsm_mem_event_setup (struct domain *d) > +{ > + return xsm_call(mem_event_setup(d)); > +} > + > +static inline int xsm_mem_event_control (struct domain *d, int mode, int op) > +{ > + return xsm_call(mem_event_control(d, mode, op)); > +} > + > +static inline int xsm_mem_event_op (struct domain *d, int op) > { > - return xsm_call(mem_event(d)); > + return xsm_call(mem_event_op(d, op)); > } > > static inline int xsm_mem_sharing (struct domain *d) > @@ -668,6 +712,16 @@ static inline int xsm_mem_sharing (struct domain *d) > return xsm_call(mem_sharing(d)); > } > > +static inline int xsm_mem_sharing_op (struct domain *d, struct domain *cd, > int op) > +{ > + return xsm_call(mem_sharing_op(d, cd, op)); > +} > + > +static inline int xsm_audit_p2m (struct domain *d) > +{ > + return xsm_call(audit_p2m(d)); > +} > + > static inline int xsm_apic (struct domain *d, int cmd) > { > return xsm_call(apic(d, cmd)); > diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c > index af532b8..09935d8 100644 > --- a/xen/xsm/dummy.c > +++ b/xen/xsm/dummy.c > @@ -51,6 +51,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) > set_to_dummy_if_null(ops, setdomainmaxmem); > set_to_dummy_if_null(ops, setdomainhandle); > set_to_dummy_if_null(ops, setdebugging); > + set_to_dummy_if_null(ops, debug_op); > set_to_dummy_if_null(ops, perfcontrol); > set_to_dummy_if_null(ops, debug_keys); > set_to_dummy_if_null(ops, getcpuinfo); > @@ -124,6 +125,10 @@ void xsm_fixup_ops (struct xsm_operations *ops) > #ifdef CONFIG_X86 > set_to_dummy_if_null(ops, shadow_control); > set_to_dummy_if_null(ops, getpageframeinfo); > + set_to_dummy_if_null(ops, getpageframeinfo_domain); > + set_to_dummy_if_null(ops, set_cpuid); > + set_to_dummy_if_null(ops, gettscinfo); > + set_to_dummy_if_null(ops, settscinfo); > set_to_dummy_if_null(ops, getmemlist); > set_to_dummy_if_null(ops, hypercall_init); > set_to_dummy_if_null(ops, hvmcontext); > @@ -134,8 +139,12 @@ void xsm_fixup_ops (struct xsm_operations *ops) > set_to_dummy_if_null(ops, hvm_set_isa_irq_level); > set_to_dummy_if_null(ops, hvm_set_pci_link_route); > set_to_dummy_if_null(ops, hvm_inject_msi); > - set_to_dummy_if_null(ops, mem_event); > + set_to_dummy_if_null(ops, mem_event_setup); > + set_to_dummy_if_null(ops, mem_event_control); > + set_to_dummy_if_null(ops, mem_event_op); > set_to_dummy_if_null(ops, mem_sharing); > + set_to_dummy_if_null(ops, mem_sharing_op); > + set_to_dummy_if_null(ops, audit_p2m); > set_to_dummy_if_null(ops, apic); > set_to_dummy_if_null(ops, xen_settime); > set_to_dummy_if_null(ops, memtype); > diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c > index f8aff14..4f71604 100644 > --- a/xen/xsm/flask/hooks.c > +++ b/xen/xsm/flask/hooks.c > @@ -695,6 +695,12 @@ static int flask_setdebugging(struct domain *d) > DOMAIN__SETDEBUGGING); > } > > +static int flask_debug_op(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, > + DOMAIN__SETDEBUGGING); > +} > + > static int flask_debug_keys(void) > { > return domain_has_xen(current->domain, XEN__DEBUG); > @@ -1111,6 +1117,26 @@ static int flask_getpageframeinfo(struct page_info > *page) > return avc_has_perm(dsec->sid, tsid, SECCLASS_MMU, MMU__PAGEINFO, NULL); > } > > +static int flask_getpageframeinfo_domain(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGEINFO); > +} > + > +static int flask_set_cpuid(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, > DOMAIN2__SET_CPUID); > +} > + > +static int flask_gettscinfo(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, > DOMAIN2__GETTSC); > +} > + > +static int flask_settscinfo(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN2, > DOMAIN2__SETTSC); > +} > + > static int flask_getmemlist(struct domain *d) > { > return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGELIST); > @@ -1201,7 +1227,17 @@ static int flask_hvm_set_pci_link_route(struct domain > *d) > return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCIROUTE); > } > > -static int flask_mem_event(struct domain *d) > +static int flask_mem_event_setup(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); > +} > + > +static int flask_mem_event_control(struct domain *d, int mode, int op) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); > +} > + > +static int flask_mem_event_op(struct domain *d, int op) > { > return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); > } > @@ -1211,6 +1247,19 @@ static int flask_mem_sharing(struct domain *d) > return domain_has_perm(current->domain, d, SECCLASS_HVM, > HVM__MEM_SHARING); > } > > +static int flask_mem_sharing_op(struct domain *d, struct domain *cd, int op) > +{ > + int rc = domain_has_perm(current->domain, cd, SECCLASS_HVM, > HVM__MEM_SHARING); > + if ( rc ) > + return rc; > + return domain_has_perm(d, cd, SECCLASS_HVM, HVM__SHARE_MEM); > +} > + > +static int flask_audit_p2m(struct domain *d) > +{ > + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__AUDIT_P2M); > +} > + > static int flask_apic(struct domain *d, int cmd) > { > u32 perm; > @@ -1586,6 +1635,7 @@ static struct xsm_operations flask_ops = { > .setdomainmaxmem = flask_setdomainmaxmem, > .setdomainhandle = flask_setdomainhandle, > .setdebugging = flask_setdebugging, > + .debug_op = flask_debug_op, > .perfcontrol = flask_perfcontrol, > .debug_keys = flask_debug_keys, > .getcpuinfo = flask_getcpuinfo, > @@ -1654,6 +1704,10 @@ static struct xsm_operations flask_ops = { > #ifdef CONFIG_X86 > .shadow_control = flask_shadow_control, > .getpageframeinfo = flask_getpageframeinfo, > + .getpageframeinfo_domain = flask_getpageframeinfo_domain, > + .set_cpuid = flask_set_cpuid, > + .gettscinfo = flask_gettscinfo, > + .settscinfo = flask_settscinfo, > .getmemlist = flask_getmemlist, > .hypercall_init = flask_hypercall_init, > .hvmcontext = flask_hvmcontext, > @@ -1662,8 +1716,12 @@ static struct xsm_operations flask_ops = { > .hvm_set_pci_intx_level = flask_hvm_set_pci_intx_level, > .hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level, > .hvm_set_pci_link_route = flask_hvm_set_pci_link_route, > - .mem_event = flask_mem_event, > + .mem_event_setup = flask_mem_event_setup, > + .mem_event_control = flask_mem_event_control, > + .mem_event_op = flask_mem_event_op, > .mem_sharing = flask_mem_sharing, > + .mem_sharing_op = flask_mem_sharing_op, > + .audit_p2m = flask_audit_p2m, > .apic = flask_apic, > .xen_settime = flask_xen_settime, > .memtype = flask_memtype, > diff --git a/xen/xsm/flask/include/av_perm_to_string.h > b/xen/xsm/flask/include/av_perm_to_string.h > index 10f8e80..997f098 100644 > --- a/xen/xsm/flask/include/av_perm_to_string.h > +++ b/xen/xsm/flask/include/av_perm_to_string.h > @@ -66,6 +66,9 @@ > S_(SECCLASS_DOMAIN2, DOMAIN2__RELABELSELF, "relabelself") > S_(SECCLASS_DOMAIN2, DOMAIN2__MAKE_PRIV_FOR, "make_priv_for") > S_(SECCLASS_DOMAIN2, DOMAIN2__SET_AS_TARGET, "set_as_target") > + S_(SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID, "set_cpuid") > + S_(SECCLASS_DOMAIN2, DOMAIN2__GETTSC, "gettsc") > + S_(SECCLASS_DOMAIN2, DOMAIN2__SETTSC, "settsc") > S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc") > S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc") > S_(SECCLASS_HVM, HVM__SETPARAM, "setparam") > @@ -79,6 +82,8 @@ > S_(SECCLASS_HVM, HVM__HVMCTL, "hvmctl") > S_(SECCLASS_HVM, HVM__MEM_EVENT, "mem_event") > S_(SECCLASS_HVM, HVM__MEM_SHARING, "mem_sharing") > + S_(SECCLASS_HVM, HVM__SHARE_MEM, "share_mem") > + S_(SECCLASS_HVM, HVM__AUDIT_P2M, "audit_p2m") > S_(SECCLASS_EVENT, EVENT__BIND, "bind") > S_(SECCLASS_EVENT, EVENT__SEND, "send") > S_(SECCLASS_EVENT, EVENT__STATUS, "status") > diff --git a/xen/xsm/flask/include/av_permissions.h > b/xen/xsm/flask/include/av_permissions.h > index f7cfee1..8596a55 100644 > --- a/xen/xsm/flask/include/av_permissions.h > +++ b/xen/xsm/flask/include/av_permissions.h > @@ -68,6 +68,9 @@ > #define DOMAIN2__RELABELSELF 0x00000004UL > #define DOMAIN2__MAKE_PRIV_FOR 0x00000008UL > #define DOMAIN2__SET_AS_TARGET 0x00000010UL > +#define DOMAIN2__SET_CPUID 0x00000020UL > +#define DOMAIN2__GETTSC 0x00000040UL > +#define DOMAIN2__SETTSC 0x00000080UL > > #define HVM__SETHVMC 0x00000001UL > #define HVM__GETHVMC 0x00000002UL > @@ -82,6 +85,8 @@ > #define HVM__HVMCTL 0x00000400UL > #define HVM__MEM_EVENT 0x00000800UL > #define HVM__MEM_SHARING 0x00001000UL > +#define HVM__SHARE_MEM 0x00002000UL > +#define HVM__AUDIT_P2M 0x00004000UL > > #define EVENT__BIND 0x00000001UL > #define EVENT__SEND 0x00000002UL
Daniel De Graaf
2012-Aug-06 19:30 UTC
Re: [PATCH 12/18] xsm: Add missing domctl and mem_sharing hooks
On 08/06/2012 02:53 PM, Keir Fraser wrote:> When someone wants to add a new domctl/sysctl, how many places will they > have to add things to ensure that xsm dtrt for a basic setup, allowing only > dom0 access to the new op? How big is the risk that we end up with new ops > that have no access control?Short answer: 3 files (xsm.h, dummy.h, dummy.c); 13 lines including whitespace. Long answer: there are a couple ways to add access controls: 1. Add an explicit IS_PRIV check. That''s pretty much what occurs before this series, only the IS_PRIV is at the top of the hypercall for domctl and sysctl. This is the least preferred, but is trivially correct for the new patch and fairly easy to wire up as an XSM hook in the future. 2. Reuse an existing XSM hook. This requires no changes required except at the caller, but requires that a suitable hook exist to reuse. There are generic hooks like xsm_domctl(), but it''s best not to just create dumping grounds for permissions if we ever want to allow subsets of them to different domains. This is probably best for incremental modifications or trivial features. 3. Add a new XSM hook. This requires adding a hook function in xsm.h and a default implementation in dummy.h/dummy.c. The changes made in this patch to FLASK would not be required, as XSM will fall back to the dummy implementation when the FLASK module doesn''t provide its own hook. Patch #13 (tmem) is a good example of adding a single hook; all changes with /flask/ could be done in a later patch implementing new FLASK permissions. If you''re adding a new function, the only way to compile both with and without XSM enabled is to add functions in dummy.h, dummy.c, and xsm.h; incomplete implementations will yield a compilation error in one of those cases. One patch I haven''t included in this series is adding automatic generation of the xen/xsm/flask/include/av_*.h files from tools/flask/policy/policy/flask/*; this simplifies adding the FLASK part of the XSM hook. The auto-generation is in tools/flask/policy/policy/flask/Makefile, just not wired in to the xen build. -- Daniel De Graaf National Security Agency
Shakeel Butt
2012-Aug-07 05:12 UTC
Re: [PATCH 00/18] RFC: Merge IS_PRIV checks into XSM hooks
I have just two comments: 1. Although the apparent benefit of this patch series seems dom0 disaggregation [VEE''08,SOSP''11] but (completely covered) xsm hooks will facilitate the implementation of recently proposed system like CloudVisor [SOSP''11] and Self-service Cloud [CCS''12] and can be used to further explore access control and flexibility for different scenarios. 2. This patch series is the hypervisor part of the dom0 disaggregation idea realization. I think the next step should be applying similar ideas to xen tools and Linux kernel. For example in Linux kernel is_initial_domain() is equivalent to IS_PRIV, what should be the xsm equivalent solution here. Other parts which need some discussion or thinking are xenbus, xenstored, privcmd (and others). Shakeel
Jan Beulich
2012-Aug-07 06:55 UTC
Re: [PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks
>>> On 06.08.12 at 18:29, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > On 08/06/2012 11:26 AM, Jan Beulich wrote: >>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>> +static XSM_DEFAULT(int, mmuext_op) (struct domain *d, struct domain *f) >>> +{ >>> + if ( d != f && !IS_PRIV_FOR(d, f) ) >>> + return -EPERM; >> >> ... Dom0 is neither privileged for DOM_IO nor for DOM_XEN. > > Actually, it is. IS_PRIV_FOR returns true for any domain when called from an > IS_PRIV domain.That''s a side effect of the current way of handling this, not something that is either logical or designed to be that way (it certainly is bogus even now for DOM_XEN, and with disaggregation - afaiu your plans - it''ll also become bogus for DOM_IO, where right now one could consider it half-way correct). Jan
Jan Beulich
2012-Aug-07 07:00 UTC
Re: [PATCH 08/18] xen: Add DOMID_SELF support to rcu_lock_domain_by_id
>>> On 06.08.12 at 18:38, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > On 08/06/2012 11:50 AM, Jan Beulich wrote: >>>>> On 06.08.12 at 17:19, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>> On 08/06/2012 11:07 AM, Jan Beulich wrote: >>>>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>>>> Callers that want to prevent use of DOMID_SELF already need to ensure >>>>> the calling domain does not pass its own domain ID. This removes the >>>>> need for the caller to manually support DOMID_SELF, which many already >>>>> do. >>>> >>>> I''m not really sure this is correct. At the very least it changes the >>>> return value of rcu_lock_remote_target_domain_by_id() when >>>> called with DOMID_SELF (from -ESRCH to -EPERM). >>> >>> This series ends up eliminating that function in patch #18, so that >>> part is taken care of. >> >> But may, in case of problems, then not be fully bi-sectable. > > Do we depend on the exact error return codes in non-error code paths? > I would think most attempts to bisect would work just fine as the > function will still be returning an error. I''m not sure ESRCH is > really the best error to return here anyway: the problem is not that > a domain with my_own_domid or DOMID_SELF couldn''t be found, it''s that > you can''t specify that domain for this operation.I''m not aware of any such dependency, but I also cannot exclude them (some testsuites tend to check for specific error codes for example). These adjustments generally claim that they don''t actually change any behavior, yet here they clearly do. Hence what I''m asking that if that behavioral change is unavoidable, it should be mentioned in the description, so that whoever runs across this can be easily aware of this not immediately obvious effect of the patch without having to analyze it. Jan
Daniel De Graaf
2012-Aug-07 13:44 UTC
Re: [PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks
On 08/07/2012 02:55 AM, Jan Beulich wrote:>>>> On 06.08.12 at 18:29, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >> On 08/06/2012 11:26 AM, Jan Beulich wrote: >>>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>>> +static XSM_DEFAULT(int, mmuext_op) (struct domain *d, struct domain *f) >>>> +{ >>>> + if ( d != f && !IS_PRIV_FOR(d, f) ) >>>> + return -EPERM; >>> >>> ... Dom0 is neither privileged for DOM_IO nor for DOM_XEN. >> >> Actually, it is. IS_PRIV_FOR returns true for any domain when called from an >> IS_PRIV domain. > > That''s a side effect of the current way of handling this, not > something that is either logical or designed to be that way (it > certainly is bogus even now for DOM_XEN, and with > disaggregation - afaiu your plans - it''ll also become bogus for > DOM_IO, where right now one could consider it half-way > correct). > > Jan >In that case, I think it would make sense to modify these XSM hooks when IS_PRIV_FOR is changed to not short-circuit on DOM_IO/DOM_XEN. If you''re suggesting changing the condition to something like ( d != f && !(IS_PRIV_FOR(d, f) || IS_PRIV(d)) ) I could do that, but I think that type of change would be best done in another patch actually making IS_PRIV_FOR(dom0, DOM_XEN) == false. -- Daniel De Graaf National Security Agency
Jan Beulich
2012-Aug-07 13:56 UTC
Re: [PATCH 16/18] arch/x86: use XSM hooks for get_pg_owner access checks
>>> On 07.08.12 at 15:44, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: > On 08/07/2012 02:55 AM, Jan Beulich wrote: >>>>> On 06.08.12 at 18:29, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>> On 08/06/2012 11:26 AM, Jan Beulich wrote: >>>>>>> On 06.08.12 at 16:32, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote: >>>>> +static XSM_DEFAULT(int, mmuext_op) (struct domain *d, struct domain *f) >>>>> +{ >>>>> + if ( d != f && !IS_PRIV_FOR(d, f) ) >>>>> + return -EPERM; >>>> >>>> ... Dom0 is neither privileged for DOM_IO nor for DOM_XEN. >>> >>> Actually, it is. IS_PRIV_FOR returns true for any domain when called from an >>> IS_PRIV domain. >> >> That''s a side effect of the current way of handling this, not >> something that is either logical or designed to be that way (it >> certainly is bogus even now for DOM_XEN, and with >> disaggregation - afaiu your plans - it''ll also become bogus for >> DOM_IO, where right now one could consider it half-way >> correct). > > In that case, I think it would make sense to modify these XSM hooks > when IS_PRIV_FOR is changed to not short-circuit on DOM_IO/DOM_XEN. > If you''re suggesting changing the condition to something like > ( d != f && !(IS_PRIV_FOR(d, f) || IS_PRIV(d)) ) > I could do that, but I think that type of change would be best done > in another patch actually making IS_PRIV_FOR(dom0, DOM_XEN) == false.From a standpoint of wanting to keep logically distinct things separate I agree. I''m merely afraid that this will be overlooked later, and causing otherwise unnecessary loss of hair until the now hidden construct is found and adjusted. Jan
Daniel De Graaf
2012-Aug-07 17:46 UTC
Re: [PATCH 00/18] RFC: Merge IS_PRIV checks into XSM hooks
On 08/07/2012 01:12 AM, Shakeel Butt wrote:> I have just two comments: > > 1. Although the apparent benefit of this patch series seems dom0 > disaggregation [VEE''08,SOSP''11] but (completely covered) xsm hooks > will facilitate the implementation of recently proposed system like > CloudVisor [SOSP''11] and Self-service Cloud [CCS''12] and can be used > to further explore access control and flexibility for different > scenarios.I wasn''t intending to exclude the other uses of XSM that this series will benefit; dom0 disaggregation is just the most obvious case that requires the larger changes like removing IS_PRIV checks.> 2. This patch series is the hypervisor part of the dom0 disaggregation > idea realization. I think the next step should be applying similar > ideas to xen tools and Linux kernel. For example in Linux kernel > is_initial_domain() is equivalent to IS_PRIV, what should be the xsm > equivalent solution here. Other parts which need some discussion or > thinking are xenbus, xenstored, privcmd (and others). > > ShakeelLinux should not be doing any access control for the hypervisor based on xen_initial_domain; this is the hypervisor''s job, and duplicating access checks based on this bit will just make it more likely to be inconsistent. The actual equivalent for XSM in Linux is SELinux; a method for mapping between the XSM/FLASK labels in the hypervisor and SELinux labels in a domain will be needed to make security policy extend from the hypervisor down to processes. Currently, Xen interfaces are labeled as a whole, so a process with access to these interfaces has access to everything that the domain it is running in has access to. This is often sufficient, especially if stub domains (Linux or minios) are used to limit the access that any given domain requires. The xen_initial_domain() access checks are mostly confined to controlling if PV Linux domains attempt direct access to hardware: things like ACPI support, IRQ configuration, direct PCI access, etc. It should be possible to use the rest of the Xen toolstack from a domU, once this series is applied. Xenstore can already be split into its own stub domain (or domains, as in the Xoar paper). The permissions model in Xenstore has a privileged bit similar to IS_PRIV; extending XSM controls into Xenstore similar to how SELinux controls were extended into DBus will address this. -- Daniel De Graaf National Security Agency
Konrad Rzeszutek Wilk
2012-Aug-07 18:06 UTC
Re: [PATCH 00/18] RFC: Merge IS_PRIV checks into XSM hooks
On Tue, Aug 07, 2012 at 02:07:55PM -0400, Shakeel Butt wrote:> > I wasn''t intending to exclude the other uses of XSM that this series will > > benefit; dom0 disaggregation is just the most obvious case that requires > > the larger changes like removing IS_PRIV checks. > I was just saying that this patch series is more beneficial than claimed. > > > Xenstore can already be split into its own stub domain (or domains, as in > > the Xoar paper). The permissions model in Xenstore has a privileged bit > > similar to IS_PRIV; extending XSM controls into Xenstore similar to how > > SELinux controls were extended into DBus will address this. > > My real concern here was the use of is_initial_domain() in the xenbus driver > code. For example I am running all Linux PV and one of them is XenStore > domain, the xenbus driver needs to do something different than > is_initial_domain(),Stefano and Daniel are already making the Linux XenBus driver more intelligient. So that it can figure out whether is initial domain, but not running XenBus.> maybe something like is_xenstore_domain() [not saying this is right > way to do it]. > Please correct me if I am wrong. > > thanks, > Shakeel > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Shakeel Butt
2012-Aug-07 18:07 UTC
Re: [PATCH 00/18] RFC: Merge IS_PRIV checks into XSM hooks
> I wasn''t intending to exclude the other uses of XSM that this series will > benefit; dom0 disaggregation is just the most obvious case that requires > the larger changes like removing IS_PRIV checks.I was just saying that this patch series is more beneficial than claimed.> Xenstore can already be split into its own stub domain (or domains, as in > the Xoar paper). The permissions model in Xenstore has a privileged bit > similar to IS_PRIV; extending XSM controls into Xenstore similar to how > SELinux controls were extended into DBus will address this.My real concern here was the use of is_initial_domain() in the xenbus driver code. For example I am running all Linux PV and one of them is XenStore domain, the xenbus driver needs to do something different than is_initial_domain(), maybe something like is_xenstore_domain() [not saying this is right way to do it]. Please correct me if I am wrong. thanks, Shakeel
Daniel De Graaf
2012-Aug-07 18:20 UTC
Re: [PATCH 00/18] RFC: Merge IS_PRIV checks into XSM hooks
On 08/07/2012 02:07 PM, Shakeel Butt wrote:>> I wasn''t intending to exclude the other uses of XSM that this series will >> benefit; dom0 disaggregation is just the most obvious case that requires >> the larger changes like removing IS_PRIV checks. > I was just saying that this patch series is more beneficial than claimed. > >> Xenstore can already be split into its own stub domain (or domains, as in >> the Xoar paper). The permissions model in Xenstore has a privileged bit >> similar to IS_PRIV; extending XSM controls into Xenstore similar to how >> SELinux controls were extended into DBus will address this. > > My real concern here was the use of is_initial_domain() in the xenbus driver > code. For example I am running all Linux PV and one of them is XenStore > domain, the xenbus driver needs to do something different than > is_initial_domain(), > maybe something like is_xenstore_domain() [not saying this is right > way to do it]. > Please correct me if I am wrong. > > thanks, > Shakeel >The method in upstream Linux is more complete than this: if the domain is started with xenstore information in the shared page, it will use it (which happens when a domain builder is used to launch dom0 and xenstore stub domains at the same time); otherwise, there is an ioctl that can be used in dom0 to tell it about a newly launched xenstore stub domain. The combination of these eliminates any need for an is_xenstore_domain() function. -- Daniel De Graaf National Security Agency