acm_policy.c
来自「xen 3.2.2 源码」· C语言 代码 · 共 883 行 · 第 1/2 页
C
883 行
break; case ACMHOOK_authorization: ret = acm_authorization(ssidref1, ssidref2); break; default: /* deny */ break; } read_unlock(&acm_bin_pol_rwlock); printkd("%s: ssid1=%x, ssid2=%x, decision=%s.\n", __func__, ssidref1, ssidref2, (ret == ACM_ACCESS_PERMITTED) ? "GRANTED" : "DENIED"); return ret;}/* Check if an ssidref of the current policy type is being used by any domain. */static intacm_check_used_ssidref(uint32_t policy_type, uint32_t search_ssidref, struct acm_sized_buffer *errors){ int rc = 0; struct acm_ssid_domain *rawssid; read_lock(&ssid_list_rwlock); for_each_acmssid( rawssid ) { ssidref_t ssidref; void *s = GET_SSIDP(policy_type, rawssid); if ( policy_type == ACM_CHINESE_WALL_POLICY ) { ssidref = ((struct chwall_ssid *)s)->chwall_ssidref; } else { ssidref = ((struct ste_ssid *)s)->ste_ssidref; } gdprintk(XENLOG_INFO,"domid=%d: search ssidref=%d, ssidref=%d\n", rawssid->domainid,search_ssidref,ssidref); if ( ssidref == search_ssidref ) { /* one is enough */ acm_array_append_tuple(errors, ACM_SSIDREF_IN_USE, search_ssidref); rc = 1; break; } } read_unlock(&ssid_list_rwlock); return rc;}/* * Translate a current ssidref into its future representation under * the new policy. * The map provides translation of ssidrefs from old to new in tuples * of (old ssidref, new ssidref). */static ssidref_toldssid_to_newssid(const struct acm_ssid_domain *rawssid, const struct acm_sized_buffer *map){ uint i; if ( rawssid != NULL ) { ssidref_t ssid = rawssid->ssidref & 0xffff; for ( i = 0; i + 1 < map->num_items; i += 2 ) { if ( map->array[i] == ssid ) { return (map->array[i+1] << 16 | map->array[i+1]); } } } return ACM_INVALID_SSIDREF;}/* * Assign an ssidref to the CHWALL policy component of the domain */static voidacm_pri_policy_assign_ssidref(struct acm_ssid_domain *rawssid, ssidref_t new_ssid){ struct chwall_ssid *chwall = (struct chwall_ssid *)rawssid->primary_ssid; chwall->chwall_ssidref = new_ssid;}/* * Assign an ssidref to the STE policy component of the domain */static voidacm_sec_policy_assign_ssidref(struct acm_ssid_domain *rawssid, ssidref_t new_ssid){ struct ste_ssid *ste = (struct ste_ssid *)rawssid->secondary_ssid; ste->ste_ssidref = new_ssid;}/* Change the ssidrefs on each domain using a passed translation function; */static voidacm_doms_change_ssidref(ssidref_t (*translator_fn) (const struct acm_ssid_domain *, const struct acm_sized_buffer *), struct acm_sized_buffer *translation_map){ struct acm_ssid_domain *rawssid; write_lock(&ssid_list_rwlock); for_each_acmssid( rawssid ) { ssidref_t new_ssid; rawssid->old_ssidref = rawssid->ssidref; new_ssid = translator_fn(rawssid, translation_map); if ( new_ssid == ACM_INVALID_SSIDREF ) { /* means no mapping found, so no change -- old = new */ continue; } acm_pri_policy_assign_ssidref(rawssid, ACM_PRIMARY (new_ssid) ); acm_sec_policy_assign_ssidref(rawssid, ACM_SECONDARY(new_ssid) ); rawssid->ssidref = new_ssid; } write_unlock(&ssid_list_rwlock);}/* * Restore the previous ssidref values on all domains */static voidacm_doms_restore_ssidref(void){ struct acm_ssid_domain *rawssid; write_lock(&ssid_list_rwlock); for_each_acmssid( rawssid ) { ssidref_t old_ssid; if ( rawssid->old_ssidref == rawssid->ssidref ) continue; old_ssid = rawssid->old_ssidref & 0xffff; rawssid->ssidref = rawssid->old_ssidref; acm_pri_policy_assign_ssidref(rawssid, old_ssid); acm_sec_policy_assign_ssidref(rawssid, old_ssid); } write_unlock(&ssid_list_rwlock);}/* Check the list of domains whether either one of them uses a to-be-deleted ssidref. */static intacm_check_deleted_ssidrefs(struct acm_sized_buffer *dels, struct acm_sized_buffer *errors){ int rc = 0; uint idx; /* check for running domains that should not be there anymore */ for ( idx = 0; idx < dels->num_items; idx++ ) { if ( acm_check_used_ssidref(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, dels->array[idx], errors) > 0 || acm_check_used_ssidref(ACM_CHINESE_WALL_POLICY, dels->array[idx], errors) > 0) { rc = ACM_ERROR; break; } } return rc;}/* * Change the policy of the system. */intacm_change_policy(struct acm_change_policy *chgpolicy){ int rc = 0; u8 *binpolicy = NULL; struct acm_sized_buffer dels = { .array = NULL, }; struct acm_sized_buffer ssidmap = { .array = NULL, }; struct acm_sized_buffer errors = { .array = NULL, }; gdprintk(XENLOG_INFO, "change policy operation\n"); if ( (chgpolicy->delarray_size > 4096) || (chgpolicy->chgarray_size > 4096) || (chgpolicy->errarray_size > 4096)) { return ACM_ERROR; } dels.num_items = chgpolicy->delarray_size / sizeof(uint32_t); if ( dels.num_items > 0 ) { dels.array = xmalloc_array(uint32_t, dels.num_items); if ( dels.array == NULL ) { rc = -ENOMEM; goto acm_chg_policy_exit; } } ssidmap.num_items = chgpolicy->chgarray_size / sizeof(uint32_t); if ( ssidmap.num_items > 0 ) { ssidmap.array = xmalloc_array(uint32_t, ssidmap.num_items); if ( ssidmap.array == NULL ) { rc = -ENOMEM; goto acm_chg_policy_exit; } } errors.num_items = chgpolicy->errarray_size / sizeof(uint32_t); if ( errors.num_items > 0 ) { errors.array = xmalloc_array(uint32_t, errors.num_items); if ( errors.array == NULL ) { rc = -ENOMEM; goto acm_chg_policy_exit; } memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items); } binpolicy = xmalloc_array(u8, chgpolicy->policy_pushcache_size); if ( binpolicy == NULL ) { rc = -ENOMEM; goto acm_chg_policy_exit; } if ( copy_from_guest(dels.array, chgpolicy->del_array, dels.num_items) || copy_from_guest(ssidmap.array, chgpolicy->chg_array, ssidmap.num_items) || copy_from_guest(binpolicy, chgpolicy->policy_pushcache, chgpolicy->policy_pushcache_size )) { rc = -EFAULT; goto acm_chg_policy_exit; } rc = do_acm_set_policy(binpolicy, chgpolicy->policy_pushcache_size, 0, &dels, &ssidmap, &errors); if ( (errors.num_items > 0) && copy_to_guest(chgpolicy->err_array, errors.array, errors.num_items ) ) { rc = -EFAULT; goto acm_chg_policy_exit; }acm_chg_policy_exit: xfree(dels.array); xfree(ssidmap.array); xfree(errors.array); xfree(binpolicy); return rc;}/* * Lookup the new ssidref given the domain's id. * The translation map provides a list of tuples in the format * (domid, new ssidref). */static ssidref_tdomid_to_newssid(const struct acm_ssid_domain *rawssid, const struct acm_sized_buffer *map){ domid_t domid = rawssid->domainid; uint i; for ( i = 0; (i+1) < map->num_items; i += 2 ) { if ( map->array[i] == domid ) return (ssidref_t)map->array[i+1]; } return ACM_INVALID_SSIDREF;}intdo_acm_relabel_doms(struct acm_sized_buffer *relabel_map, struct acm_sized_buffer *errors){ int rc = 0, irc; write_lock(&acm_bin_pol_rwlock); acm_doms_change_ssidref(domid_to_newssid, relabel_map); /* run tests; collect as much error info as possible */ irc = do_chwall_init_state_curr(errors); irc += do_ste_init_state_curr(errors); if ( irc != 0 ) { rc = -EFAULT; goto acm_relabel_doms_lock_err_exit; } write_unlock(&acm_bin_pol_rwlock); return rc;acm_relabel_doms_lock_err_exit: /* revert the new ssidref assignment */ acm_doms_restore_ssidref(); do_chwall_init_state_curr(NULL); write_unlock(&acm_bin_pol_rwlock); return rc;}intacm_relabel_domains(struct acm_relabel_doms *relabel){ int rc = ACM_OK; struct acm_sized_buffer relabels = { .array = NULL, }; struct acm_sized_buffer errors = { .array = NULL, }; if ( relabel->relabel_map_size > 4096 ) { return ACM_ERROR; } relabels.num_items = relabel->relabel_map_size / sizeof(uint32_t); if ( relabels.num_items > 0 ) { relabels.array = xmalloc_array(uint32_t, relabels.num_items); if ( relabels.array == NULL ) { rc = -ENOMEM; goto acm_relabel_doms_exit; } } errors.num_items = relabel->errarray_size / sizeof(uint32_t); if ( errors.num_items > 0 ) { errors.array = xmalloc_array(uint32_t, errors.num_items); if ( errors.array == NULL ) { rc = -ENOMEM; goto acm_relabel_doms_exit; } memset(errors.array, 0x0, sizeof(uint32_t) * errors.num_items); } if ( copy_from_guest(relabels.array, relabel->relabel_map, relabels.num_items) ) { rc = -EFAULT; goto acm_relabel_doms_exit; } rc = do_acm_relabel_doms(&relabels, &errors); if ( copy_to_guest(relabel->err_array, errors.array, errors.num_items ) ) rc = -EFAULT;acm_relabel_doms_exit: xfree(relabels.array); xfree(errors.array); return rc;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?