📄 acm_chinesewall_hooks.c
字号:
/* 3. now re-calculate the state for the new policy based on * running domains; this can fail if new policy is conflicting * with running domains */ if ( chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set, errors)) { printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__); goto error_free; /* new policy conflicts with running domains */ } /* if this was only a test run, exit with ACM_OK */ if ( test_only ) { rc = ACM_OK; goto error_free; } /* 4. free old policy buffers, replace with new ones */ chwall_bin_pol.max_types = chwall_buf->chwall_max_types; chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs; chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets; xfree(chwall_bin_pol.ssidrefs); xfree(chwall_bin_pol.conflict_aggregate_set); xfree(chwall_bin_pol.running_types); xfree(chwall_bin_pol.conflict_sets); chwall_bin_pol.ssidrefs = ssids; chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set; chwall_bin_pol.running_types = running_types; chwall_bin_pol.conflict_sets = conflict_sets; return ACM_OK; error_free: if ( !test_only ) printk("%s: ERROR setting policy.\n", __func__); xfree(ssids); xfree(conflict_sets); xfree(running_types); xfree(conflict_aggregate_set); return rc;}/* * This function MUST be called before the chwall_ste_policy function! */static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy, struct acm_sized_buffer *errors){ struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *) buf; if ( buf_size < sizeof(struct acm_chwall_policy_buffer) ) return -EINVAL; /* rewrite the policy due to endianess */ chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code); chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version); chwall_buf->chwall_max_types = be32_to_cpu(chwall_buf->chwall_max_types); chwall_buf->chwall_max_ssidrefs = be32_to_cpu(chwall_buf->chwall_max_ssidrefs); chwall_buf->chwall_max_conflictsets = be32_to_cpu(chwall_buf->chwall_max_conflictsets); chwall_buf->chwall_ssid_offset = be32_to_cpu(chwall_buf->chwall_ssid_offset); chwall_buf->chwall_conflict_sets_offset = be32_to_cpu(chwall_buf->chwall_conflict_sets_offset); chwall_buf->chwall_running_types_offset = be32_to_cpu(chwall_buf->chwall_running_types_offset); chwall_buf->chwall_conflict_aggregate_offset = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset); /* policy type and version checks */ if ( (chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) || (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) ) return -EINVAL; return _chwall_update_policy(buf, buf_size, 1, errors);}static int chwall_set_policy(u8 *buf, u32 buf_size){ return _chwall_update_policy(buf, buf_size, 0, NULL);}static int chwall_dump_stats(u8 * buf, u16 len){ /* no stats for Chinese Wall Policy */ return 0;}static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len){ int i; /* fill in buffer */ if ( chwall_bin_pol.max_types > len ) return -EFAULT; if ( ssidref >= chwall_bin_pol.max_ssidrefs ) return -EFAULT; /* read types for chwall ssidref */ for ( i = 0; i < chwall_bin_pol.max_types; i++ ) { if ( chwall_bin_pol. ssidrefs[ssidref * chwall_bin_pol.max_types + i] ) buf[i] = 1; else buf[i] = 0; } return chwall_bin_pol.max_types;}/*************************** * Authorization functions ***************************//* -------- DOMAIN OPERATION HOOKS -----------*/static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref){ ssidref_t chwall_ssidref; int i, j; chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); if ( chwall_ssidref >= chwall_bin_pol.max_ssidrefs ) { printk("%s: ERROR chwall_ssidref > max(%x).\n", __func__, chwall_bin_pol.max_ssidrefs - 1); return ACM_ACCESS_DENIED; } /* A: chinese wall check for conflicts */ for ( i = 0; i < chwall_bin_pol.max_types; i++ ) if ( chwall_bin_pol.conflict_aggregate_set[i] && chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + i] ) { printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i); return ACM_ACCESS_DENIED; } /* B: chinese wall conflict set adjustment (so that other * other domains simultaneously created are evaluated against * this new set) */ for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) { int common = 0; /* check if conflict_set_i and ssidref have common types */ for ( j = 0; j < chwall_bin_pol.max_types; j++ ) if ( chwall_bin_pol. conflict_sets[i * chwall_bin_pol.max_types + j] && chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + j] ) { common = 1; break; } if ( common == 0 ) continue; /* try next conflict set */ /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ for ( j = 0; j < chwall_bin_pol.max_types; j++ ) if ( chwall_bin_pol. conflict_sets[i * chwall_bin_pol.max_types + j] && !chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + j]) chwall_bin_pol.conflict_aggregate_set[j]++; } return ACM_ACCESS_PERMITTED;}static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref){ int i; ssidref_t chwall_ssidref; chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref); /* adjust types ref-count for running domains */ for ( i = 0; i < chwall_bin_pol.max_types; i++ ) chwall_bin_pol.running_types[i] += chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + i];}/* * To be called when creating a domain. If this call is unsuccessful, * no state changes have occurred (adjustments of counters etc.). If it * was successful, state was changed and can be undone using * chwall_domain_destroy. */static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref, domid_t domid){ int rc; read_lock(&acm_bin_pol_rwlock); rc = _chwall_pre_domain_create(subject_ssid, ssidref); if ( rc == ACM_ACCESS_PERMITTED ) _chwall_post_domain_create(domid, ssidref); read_unlock(&acm_bin_pol_rwlock); return rc;}/* * This function undoes everything a successful call to * chwall_domain_create has done. */static void chwall_domain_destroy(void *object_ssid, struct domain *d){ int i, j; struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *) object_ssid); ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref; read_lock(&acm_bin_pol_rwlock); /* adjust running types set */ for ( i = 0; i < chwall_bin_pol.max_types; i++ ) chwall_bin_pol.running_types[i] -= chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + i]; /* roll-back: re-adjust conflicting types aggregate */ for ( i = 0; i < chwall_bin_pol.max_conflictsets; i++ ) { int common = 0; /* check if conflict_set_i and ssidref have common types */ for ( j = 0; j < chwall_bin_pol.max_types; j++ ) if ( chwall_bin_pol.conflict_sets[i * chwall_bin_pol.max_types + j] && chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + j]) { common = 1; break; } if ( common == 0 ) { /* try next conflict set, this one does not include any type of chwall_ssidref */ continue; } /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */ for ( j = 0; j < chwall_bin_pol.max_types; j++ ) if ( chwall_bin_pol. conflict_sets[i * chwall_bin_pol.max_types + j] && !chwall_bin_pol.ssidrefs[chwall_ssidref * chwall_bin_pol.max_types + j]) chwall_bin_pol.conflict_aggregate_set[j]--; } read_unlock(&acm_bin_pol_rwlock); return;}static int chwall_is_default_policy(void){ static const domaintype_t def_policy[2] = { 0x0, 0x0 }; return ( ( chwall_bin_pol.max_types == 1 ) && ( chwall_bin_pol.max_ssidrefs == 2 ) && ( memcmp(chwall_bin_pol.ssidrefs, def_policy, sizeof(def_policy)) == 0 ) );}static int chwall_is_in_conflictset(ssidref_t ssidref1){ /* is ssidref1 in conflict with any running domains ? */ int rc = 0; int i, j; ssidref_t ssid_chwall; read_lock(&acm_bin_pol_rwlock); ssid_chwall = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref1); if ( ssid_chwall >= 0 && ssid_chwall < chwall_bin_pol.max_ssidrefs ) { for ( i = 0; i < chwall_bin_pol.max_conflictsets && rc == 0; i++ ) { for ( j = 0; j < chwall_bin_pol.max_types; j++ ) { if ( chwall_bin_pol.conflict_aggregate_set [i * chwall_bin_pol.max_types + j] && chwall_bin_pol.ssidrefs [ssid_chwall * chwall_bin_pol.max_types + j]) { rc = 1; break; } } } } else { rc = 1; } read_unlock(&acm_bin_pol_rwlock); return rc;}struct acm_operations acm_chinesewall_ops = { /* policy management services */ .init_domain_ssid = chwall_init_domain_ssid, .free_domain_ssid = chwall_free_domain_ssid, .dump_binary_policy = chwall_dump_policy, .test_binary_policy = chwall_test_policy, .set_binary_policy = chwall_set_policy, .dump_statistics = chwall_dump_stats, .dump_ssid_types = chwall_dump_ssid_types, /* domain management control hooks */ .domain_create = chwall_domain_create, .domain_destroy = chwall_domain_destroy, /* event channel control hooks */ .pre_eventchannel_unbound = NULL, .fail_eventchannel_unbound = NULL, .pre_eventchannel_interdomain = NULL, .fail_eventchannel_interdomain = NULL, /* grant table control hooks */ .pre_grant_map_ref = NULL, .fail_grant_map_ref = NULL, .pre_grant_setup = NULL, .fail_grant_setup = NULL, /* generic domain-requested decision hooks */ .sharing = NULL, .authorization = NULL, .conflictset = chwall_is_in_conflictset, .is_default_policy = chwall_is_default_policy,};/* * 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -