[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v7] libxl: introduce XSM relabel on build
In response to a suggestion from Jan, I am splitting out independent patches from the larger XSM series that I have been posting. This is the only patch from that series that touches the toolstack; it is independent of the rest of the series as the hypervisor component has already been committed. ---------------------8<------------------------------------------------- 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. Example domain configuration snippet: seclabel='customer_1:vm_r:nomigrate_t' init_seclabel='customer_1:vm_r:nomigrate_t_building' 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. However, if dom0 correctly unmaps the domain upon building, a the domU is protected against dom0 becoming malicious in the future. Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> Cc: Ian Campbell <ian.campbell@xxxxxxxxxx> --- docs/man/xl.cfg.pod.5 | 9 +++++ docs/misc/xsm-flask.txt | 2 + tools/flask/policy/policy/modules/xen/xen.if | 56 +++++++++++++++++++++------- tools/flask/policy/policy/modules/xen/xen.te | 10 +++++ 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 +++++++++- 9 files changed, 99 insertions(+), 14 deletions(-) diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index dc3f494..caba162 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -270,6 +270,15 @@ UUID will be generated. Assign an XSM security label to this domain. +=item B<init_seclabel="LABEL"> + +Specify an XSM security label used for this domain temporarily during +its build. The domain's XSM label will be changed to the execution +seclabel (specified by "seclabel") once the build is complete, prior to +unpausing the domain. With a properly constructed security policy (such +as nomigrate_t in the example policy), this can be used to build a +domain whose memory is not accessible to the toolstack domain. + =item B<nomigrate=BOOLEAN> Disable migration of this domain. This enables certain other features 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 3f58909..2ad11b2 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 9550397..1162153 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 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 1cd13c1..32122fd 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -2169,6 +2169,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 9d20086..b183255 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -1182,6 +1182,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 7eac4a8..93524f0 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -268,6 +268,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 4b75fc3..e964bf1 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -596,16 +596,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.7 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |