--- xen-unstable.hg/tools/security/secpol_tool.c | 59 +++++++++- xen-unstable.hg/tools/security/secpol_xml2bin.c | 3 xen-unstable.hg/xen/acm/acm_chinesewall_hooks.c | 13 ++ xen-unstable.hg/xen/acm/acm_core.c | 65 ++++++++++-- xen-unstable.hg/xen/acm/acm_simple_type_enforcement_hooks.c | 26 +++- xen-unstable.hg/xen/include/acm/acm_core.h | 9 + xen-unstable.hg/xen/include/acm/acm_hooks.h | 12 +- 7 files changed, 156 insertions(+), 31 deletions(-) Index: root/xen-unstable.hg/xen/acm/acm_core.c =================================================================== --- root.orig/xen-unstable.hg/xen/acm/acm_core.c +++ root/xen-unstable.hg/xen/acm/acm_core.c @@ -62,18 +62,63 @@ struct acm_binary_policy acm_bin_pol; /* acm binary policy lock */ DEFINE_RWLOCK(acm_bin_pol_rwlock); +/* ACM's only accepted policy name */ +char polname[80]; +char *acm_accepted_boot_policy_name = NULL; + +static void __init set_dom0_ssidref(const char *val) +{ + /* expected format: + ssidref=: + Policy name must not have a 'space'. + */ + const char *c; + int lo, hi; + int i; + int dom0_ssidref = simple_strtoull(val, &c, 0); + + if (!strncmp(&c[0],":sHype:", 7)) { + lo = dom0_ssidref & 0xffff; + if (lo < ACM_MAX_NUM_TYPES && lo >= 1) + dom0_chwall_ssidref = lo; + hi = dom0_ssidref >> 16; + if (hi < ACM_MAX_NUM_TYPES && hi >= 1) + dom0_ste_ssidref = hi; + for (i = 0; i < sizeof(polname); i++) { + polname[i] = c[7+i]; + if (polname[i] == '\0' || polname[i] == '\t' || + polname[i] == '\n' || polname[i] == ' ' || + polname[i] == ':') { + break; + } + } + polname[i] = 0; + acm_accepted_boot_policy_name = polname; + } +} + +custom_param("ssidref", set_dom0_ssidref); + int acm_set_policy_reference(u8 *buf, u32 buf_size) { + char *name = (char *)(buf + sizeof(struct acm_policy_reference_buffer)); struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf; + + if (acm_accepted_boot_policy_name != NULL) { + if (strcmp(acm_accepted_boot_policy_name, name)) { + printk("Policy's name '%s' is not the expected one '%s'.\n", + name, acm_accepted_boot_policy_name); + return ACM_ERROR; + } + } + acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len)); if (!acm_bin_pol.policy_reference_name) return -ENOMEM; + strlcpy(acm_bin_pol.policy_reference_name, name, be32_to_cpu(pr->len)); - strlcpy(acm_bin_pol.policy_reference_name, - (char *)(buf + sizeof(struct acm_policy_reference_buffer)), - be32_to_cpu(pr->len)); printk("%s: Activating policy %s\n", __func__, acm_bin_pol.policy_reference_name); return 0; @@ -190,7 +235,8 @@ acm_is_policy(char *buf, unsigned long l static int acm_setup(char *policy_start, - unsigned long policy_len) + unsigned long policy_len, + int is_bootpolicy) { int rc = ACM_OK; struct acm_policy_buffer *pol; @@ -202,7 +248,8 @@ acm_setup(char *policy_start, if (be32_to_cpu(pol->magic) != ACM_MAGIC) return rc; - rc = do_acm_set_policy((void *)policy_start, (u32)policy_len); + rc = do_acm_set_policy((void *)policy_start, (u32)policy_len, + is_bootpolicy); if (rc == ACM_OK) { printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start); @@ -224,7 +271,10 @@ acm_init(char *policy_start, int ret = ACM_OK; /* first try to load the boot policy (uses its own locks) */ - acm_setup(policy_start, policy_len); + acm_setup(policy_start, policy_len, 1); + + /* a user-provided policy may have any name; only matched during boot */ + acm_accepted_boot_policy_name = NULL; if (acm_active_security_policy != ACM_POLICY_UNDEFINED) { @@ -236,6 +286,9 @@ acm_init(char *policy_start, printk("%s: Loading default policy (%s).\n", __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY)); + /* (re-)set dom-0 ssidref to default */ + dom0_ste_ssidref = dom0_chwall_ssidref = 0x0001; + if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) { ret = -EINVAL; goto out; Index: root/xen-unstable.hg/xen/include/acm/acm_hooks.h =================================================================== --- root.orig/xen-unstable.hg/xen/include/acm/acm_hooks.h +++ root/xen-unstable.hg/xen/include/acm/acm_hooks.h @@ -91,7 +91,8 @@ struct acm_operations { int (*init_domain_ssid) (void **ssid, ssidref_t ssidref); void (*free_domain_ssid) (void *ssid); int (*dump_binary_policy) (u8 *buffer, u32 buf_size); - int (*set_binary_policy) (u8 *buffer, u32 buf_size); + int (*set_binary_policy) (u8 *buffer, u32 buf_size, + int is_bootpolicy); int (*dump_statistics) (u8 *buffer, u16 buf_size); int (*dump_ssid_types) (ssidref_t ssidref, u8 *buffer, u16 buf_size); /* domain management control hooks (can be NULL) */ @@ -347,14 +348,13 @@ static inline int acm_pre_grant_setup(do } } -/* predefined ssidref for DOM0 used by xen when creating DOM0 */ -#define ACM_DOM0_SSIDREF 0x00010001 - static inline void acm_post_domain0_create(domid_t domid) { /* initialialize shared sHype security labels for new domain */ - acm_init_domain_ssid(domid, ACM_DOM0_SSIDREF); - acm_post_domain_create(domid, ACM_DOM0_SSIDREF); + int dom0_ssidref = dom0_ste_ssidref << 16 | dom0_chwall_ssidref; + + acm_init_domain_ssid(domid, dom0_ssidref); + acm_post_domain_create(domid, dom0_ssidref); } static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2) Index: root/xen-unstable.hg/xen/acm/acm_simple_type_enforcement_hooks.c =================================================================== --- root.orig/xen-unstable.hg/xen/acm/acm_simple_type_enforcement_hooks.c +++ root/xen-unstable.hg/xen/acm/acm_simple_type_enforcement_hooks.c @@ -31,6 +31,9 @@ #include #include #include +#include + +ssidref_t dom0_ste_ssidref = 0x0001; /* local cache structures for STE policy */ struct ste_binary_policy ste_bin_pol; @@ -74,15 +77,21 @@ int acm_init_ste_policy(void) { /* minimal startup policy; policy write-locked already */ ste_bin_pol.max_types = 1; - ste_bin_pol.max_ssidrefs = 2; - ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 2); - memset(ste_bin_pol.ssidrefs, 0, 2); + ste_bin_pol.max_ssidrefs = 1 + dom0_ste_ssidref; + ste_bin_pol.ssidrefs = + (domaintype_t *)xmalloc_array(domaintype_t, + ste_bin_pol.max_types * + ste_bin_pol.max_ssidrefs); if (ste_bin_pol.ssidrefs == NULL) return ACM_INIT_SSID_ERROR; - /* initialize state so that dom0 can start up and communicate with itself */ - ste_bin_pol.ssidrefs[1] = 1; + memset(ste_bin_pol.ssidrefs, 0, sizeof(domaintype_t) * + ste_bin_pol.max_types * + ste_bin_pol.max_ssidrefs); + + /* initialize state so that dom0 can start up and communicate with itself */ + ste_bin_pol.ssidrefs[ste_bin_pol.max_types * dom0_ste_ssidref] = 1; /* init stats */ atomic_set(&(ste_bin_pol.ec_eval_count), 0); @@ -274,7 +283,7 @@ ste_init_state(struct acm_ste_policy_buf /* set new policy; policy write-locked already */ static int -ste_set_policy(u8 *buf, u32 buf_size) +ste_set_policy(u8 *buf, u32 buf_size, int is_bootpolicy) { struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf; void *ssidrefsbuf; @@ -305,6 +314,11 @@ ste_set_policy(u8 *buf, u32 buf_size) if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size) goto error_free; + /* during boot dom0_chwall_ssidref is set */ + if (is_bootpolicy && (dom0_ste_ssidref >= ste_buf->ste_max_ssidrefs)) { + goto error_free; + } + arrcpy(ssidrefsbuf, buf + ste_buf->ste_ssid_offset, sizeof(domaintype_t), Index: root/xen-unstable.hg/xen/acm/acm_chinesewall_hooks.c =================================================================== --- root.orig/xen-unstable.hg/xen/acm/acm_chinesewall_hooks.c +++ root/xen-unstable.hg/xen/acm/acm_chinesewall_hooks.c @@ -41,6 +41,9 @@ #include #include #include +#include + +ssidref_t dom0_chwall_ssidref = 0x0001; /* local cache structures for chinese wall policy */ struct chwall_binary_policy chwall_bin_pol; @@ -53,7 +56,7 @@ int acm_init_chwall_policy(void) { /* minimal startup policy; policy write-locked already */ chwall_bin_pol.max_types = 1; - chwall_bin_pol.max_ssidrefs = 2; + chwall_bin_pol.max_ssidrefs = 1 + dom0_chwall_ssidref; chwall_bin_pol.max_conflictsets = 1; chwall_bin_pol.ssidrefs = (domaintype_t *) xmalloc_array(domaintype_t, @@ -254,7 +257,7 @@ chwall_init_state(struct acm_chwall_poli * more than one type is currently running */ } -static int chwall_set_policy(u8 * buf, u32 buf_size) +static int chwall_set_policy(u8 * buf, u32 buf_size, int is_bootpolicy) { /* policy write-locked already */ struct acm_chwall_policy_buffer *chwall_buf = @@ -286,6 +289,12 @@ static int chwall_set_policy(u8 * buf, u (chwall_buf->policy_version != ACM_CHWALL_VERSION)) return -EINVAL; + /* during boot dom0_chwall_ssidref is set */ + if (is_bootpolicy && + (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs)) { + goto error_free; + } + /* 1. allocate new buffers */ ssids = xmalloc_array(domaintype_t, Index: root/xen-unstable.hg/tools/security/secpol_tool.c =================================================================== --- root.orig/xen-unstable.hg/tools/security/secpol_tool.c +++ root/xen-unstable.hg/tools/security/secpol_tool.c @@ -57,7 +57,7 @@ void usage(char *progname) /*************************** DUMPS *******************************/ -void acm_dump_chinesewall_buffer(void *buf, int buflen) +void acm_dump_chinesewall_buffer(void *buf, int buflen, uint16_t chwall_ref) { struct acm_chwall_policy_buffer *cwbuf = @@ -91,6 +91,8 @@ void acm_dump_chinesewall_buffer(void *b for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++) printf("%02x ", ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j])); + if (i == chwall_ref) + printf(" <-- Domain-0"); } printf("\n\nConfict Sets:\n"); conflicts = @@ -131,7 +133,7 @@ void acm_dump_chinesewall_buffer(void *b } } -void acm_dump_ste_buffer(void *buf, int buflen) +void acm_dump_ste_buffer(void *buf, int buflen, uint16_t ste_ref) { struct acm_ste_policy_buffer *stebuf = @@ -158,11 +160,14 @@ void acm_dump_ste_buffer(void *buf, int for (j = 0; j < ntohl(stebuf->ste_max_types); j++) printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j])); + if (i == ste_ref) + printf(" <-- Domain-0"); } printf("\n\n"); } -void acm_dump_policy_buffer(void *buf, int buflen) +void acm_dump_policy_buffer(void *buf, int buflen, + uint16_t chwall_ref, uint16_t ste_ref) { struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf; char *policy_reference_name = @@ -190,13 +195,15 @@ void acm_dump_policy_buffer(void *buf, i acm_dump_chinesewall_buffer(ALIGN8(buf + ntohl(pol->primary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->primary_buffer_offset)); + ntohl(pol->primary_buffer_offset), + chwall_ref); break; case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->primary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->primary_buffer_offset)); + ntohl(pol->primary_buffer_offset), + ste_ref); break; case ACM_NULL_POLICY: @@ -212,13 +219,15 @@ void acm_dump_policy_buffer(void *buf, i acm_dump_chinesewall_buffer(ALIGN8(buf + ntohl(pol->secondary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->secondary_buffer_offset)); + ntohl(pol->secondary_buffer_offset), + chwall_ref); break; case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->secondary_buffer_offset)), ntohl(pol->len) - - ntohl(pol->secondary_buffer_offset)); + ntohl(pol->secondary_buffer_offset), + ste_ref); break; case ACM_NULL_POLICY: @@ -230,6 +239,27 @@ void acm_dump_policy_buffer(void *buf, i } } +/************************** get dom0 ssidref *****************************/ +int acm_get_ssidref(int xc_handle, int domid, uint16_t *chwall_ref, + uint16_t *ste_ref) +{ + int ret; + struct acm_getssid getssid; + char buf[4096]; + struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)buf; + getssid.interface_version = ACM_INTERFACE_VERSION; + set_xen_guest_handle(getssid.ssidbuf, buf); + getssid.ssidbuf_size = sizeof(buf); + getssid.get_ssid_by = ACM_GETBY_domainid; + getssid.id.domainid = domid; + ret = xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid)); + if (ret == 0) { + *chwall_ref = ssid->ssidref & 0xffff; + *ste_ref = ssid->ssidref >> 16; + } + return ret; +} + /******************************* get policy ******************************/ #define PULL_CACHE_SIZE 8192 @@ -239,12 +269,16 @@ int acm_domain_getpolicy(int xc_handle) { struct acm_getpolicy getpolicy; int ret; + uint16_t chwall_ref, ste_ref; memset(pull_buffer, 0x00, sizeof(pull_buffer)); getpolicy.interface_version = ACM_INTERFACE_VERSION; set_xen_guest_handle(getpolicy.pullcache, pull_buffer); getpolicy.pullcache_size = sizeof(pull_buffer); ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy)); + if (ret >= 0) { + ret = acm_get_ssidref(xc_handle, 0, &chwall_ref, &ste_ref); + } if (ret < 0) { printf("ACM operation failed: errno=%d\n", errno); @@ -254,7 +288,9 @@ int acm_domain_getpolicy(int xc_handle) } /* dump policy */ - acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer)); + acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer), + chwall_ref, ste_ref); + return ret; } @@ -266,6 +302,7 @@ int acm_domain_loadpolicy(int xc_handle, int ret, fd; off_t len; uint8_t *buffer; + uint16_t chwall_ssidref, ste_ssidref; if ((ret = stat(filename, &mystat))) { printf("File %s not found.\n", filename); @@ -282,10 +319,14 @@ int acm_domain_loadpolicy(int xc_handle, printf("File %s not found.\n", filename); goto free_out; } + ret =acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref); + if (ret < 0) { + goto free_out; + } if (len == read(fd, buffer, len)) { struct acm_setpolicy setpolicy; /* dump it and then push it down into xen/acm */ - acm_dump_policy_buffer(buffer, len); + acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref); setpolicy.interface_version = ACM_INTERFACE_VERSION; set_xen_guest_handle(setpolicy.pushcache, buffer); setpolicy.pushcache_size = len; Index: root/xen-unstable.hg/tools/security/secpol_xml2bin.c =================================================================== --- root.orig/xen-unstable.hg/tools/security/secpol_xml2bin.c +++ root/xen-unstable.hg/tools/security/secpol_xml2bin.c @@ -1163,7 +1163,8 @@ int write_binary(char *filename) u_int32_t len_ste = 0, len_chwall = 0, len_pr = 0; /* length of policy components */ - sscanf(policy_version_string,"%d.%d", &major, &minor); + if (policy_version_string) + sscanf(policy_version_string,"%d.%d", &major, &minor); /* open binary file */ if ((fd = Index: root/xen-unstable.hg/xen/include/acm/acm_core.h =================================================================== --- root.orig/xen-unstable.hg/xen/include/acm/acm_core.h +++ root/xen-unstable.hg/xen/include/acm/acm_core.h @@ -123,13 +123,20 @@ int acm_init_domain_ssid(domid_t id, ssi void acm_free_domain_ssid(struct acm_ssid_domain *ssid); int acm_init_binary_policy(u32 policy_code); int acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size); -int do_acm_set_policy(void *buf, u32 buf_size); +int do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy); int acm_get_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size); int acm_dump_statistics(XEN_GUEST_HANDLE(void) buf, u16 buf_size); int acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE(void) buf, u16 buf_size); int acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook); int acm_set_policy_reference(u8 * buf, u32 buf_size); int acm_dump_policy_reference(u8 *buf, u32 buf_size); + + +/* variables */ +extern ssidref_t dom0_chwall_ssidref; +extern ssidref_t dom0_ste_ssidref; +#define ACM_MAX_NUM_TYPES (256) + #endif /*