📄 cipso_ipv4.c
字号:
for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) { switch (doi_def->tags[iter]) { case CIPSO_V4_TAG_RBITMAP: break; case CIPSO_V4_TAG_RANGE: if (doi_def->type != CIPSO_V4_MAP_PASS) return -EINVAL; break; case CIPSO_V4_TAG_INVALID: if (iter == 0) return -EINVAL; break; case CIPSO_V4_TAG_ENUM: if (doi_def->type != CIPSO_V4_MAP_PASS) return -EINVAL; break; default: return -EINVAL; } } doi_def->valid = 1; INIT_RCU_HEAD(&doi_def->rcu); INIT_LIST_HEAD(&doi_def->dom_list); spin_lock(&cipso_v4_doi_list_lock); if (cipso_v4_doi_search(doi_def->doi) != NULL) goto doi_add_failure; list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list); spin_unlock(&cipso_v4_doi_list_lock); return 0;doi_add_failure: spin_unlock(&cipso_v4_doi_list_lock); return -EEXIST;}/** * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine * @doi: the DOI value * @audit_secid: the LSM secid to use in the audit message * @callback: the DOI cleanup/free callback * * Description: * Removes a DOI definition from the CIPSO engine, @callback is called to * free any memory. The NetLabel routines will be called to release their own * LSM domain mappings as well as our own domain list. Returns zero on * success and negative values on failure. * */int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info, void (*callback) (struct rcu_head * head)){ struct cipso_v4_doi *doi_def; struct cipso_v4_domhsh_entry *dom_iter; spin_lock(&cipso_v4_doi_list_lock); doi_def = cipso_v4_doi_search(doi); if (doi_def != NULL) { doi_def->valid = 0; list_del_rcu(&doi_def->list); spin_unlock(&cipso_v4_doi_list_lock); rcu_read_lock(); list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) if (dom_iter->valid) netlbl_domhsh_remove(dom_iter->domain, audit_info); rcu_read_unlock(); cipso_v4_cache_invalidate(); call_rcu(&doi_def->rcu, callback); return 0; } spin_unlock(&cipso_v4_doi_list_lock); return -ENOENT;}/** * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition * @doi: the DOI value * * Description: * Searches for a valid DOI definition and if one is found it is returned to * the caller. Otherwise NULL is returned. The caller must ensure that * rcu_read_lock() is held while accessing the returned definition. * */struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi){ return cipso_v4_doi_search(doi);}/** * cipso_v4_doi_walk - Iterate through the DOI definitions * @skip_cnt: skip past this number of DOI definitions, updated * @callback: callback for each DOI definition * @cb_arg: argument for the callback function * * Description: * Iterate over the DOI definition list, skipping the first @skip_cnt entries. * For each entry call @callback, if @callback returns a negative value stop * 'walking' through the list and return. Updates the value in @skip_cnt upon * return. Returns zero on success, negative values on failure. * */int cipso_v4_doi_walk(u32 *skip_cnt, int (*callback) (struct cipso_v4_doi *doi_def, void *arg), void *cb_arg){ int ret_val = -ENOENT; u32 doi_cnt = 0; struct cipso_v4_doi *iter_doi; rcu_read_lock(); list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list) if (iter_doi->valid) { if (doi_cnt++ < *skip_cnt) continue; ret_val = callback(iter_doi, cb_arg); if (ret_val < 0) { doi_cnt--; goto doi_walk_return; } }doi_walk_return: rcu_read_unlock(); *skip_cnt = doi_cnt; return ret_val;}/** * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition * @doi_def: the DOI definition * @domain: the domain to add * * Description: * Adds the @domain to the DOI specified by @doi_def, this function * should only be called by external functions (i.e. NetLabel). This function * does allocate memory. Returns zero on success, negative values on failure. * */int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain){ struct cipso_v4_domhsh_entry *iter; struct cipso_v4_domhsh_entry *new_dom; new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL); if (new_dom == NULL) return -ENOMEM; if (domain) { new_dom->domain = kstrdup(domain, GFP_KERNEL); if (new_dom->domain == NULL) { kfree(new_dom); return -ENOMEM; } } new_dom->valid = 1; INIT_RCU_HEAD(&new_dom->rcu); spin_lock(&cipso_v4_doi_list_lock); list_for_each_entry(iter, &doi_def->dom_list, list) if (iter->valid && ((domain != NULL && iter->domain != NULL && strcmp(iter->domain, domain) == 0) || (domain == NULL && iter->domain == NULL))) { spin_unlock(&cipso_v4_doi_list_lock); kfree(new_dom->domain); kfree(new_dom); return -EEXIST; } list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); spin_unlock(&cipso_v4_doi_list_lock); return 0;}/** * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition * @doi_def: the DOI definition * @domain: the domain to remove * * Description: * Removes the @domain from the DOI specified by @doi_def, this function * should only be called by external functions (i.e. NetLabel). Returns zero * on success and negative values on error. * */int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, const char *domain){ struct cipso_v4_domhsh_entry *iter; spin_lock(&cipso_v4_doi_list_lock); list_for_each_entry(iter, &doi_def->dom_list, list) if (iter->valid && ((domain != NULL && iter->domain != NULL && strcmp(iter->domain, domain) == 0) || (domain == NULL && iter->domain == NULL))) { iter->valid = 0; list_del_rcu(&iter->list); spin_unlock(&cipso_v4_doi_list_lock); call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); return 0; } spin_unlock(&cipso_v4_doi_list_lock); return -ENOENT;}/* * Label Mapping Functions *//** * cipso_v4_map_lvl_valid - Checks to see if the given level is understood * @doi_def: the DOI definition * @level: the level to check * * Description: * Checks the given level against the given DOI definition and returns a * negative value if the level does not have a valid mapping and a zero value * if the level is defined by the DOI. * */static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level){ switch (doi_def->type) { case CIPSO_V4_MAP_PASS: return 0; case CIPSO_V4_MAP_STD: if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) return 0; break; } return -EFAULT;}/** * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network * @doi_def: the DOI definition * @host_lvl: the host MLS level * @net_lvl: the network/CIPSO MLS level * * Description: * Perform a label mapping to translate a local MLS level to the correct * CIPSO level using the given DOI definition. Returns zero on success, * negative values otherwise. * */static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def, u32 host_lvl, u32 *net_lvl){ switch (doi_def->type) { case CIPSO_V4_MAP_PASS: *net_lvl = host_lvl; return 0; case CIPSO_V4_MAP_STD: if (host_lvl < doi_def->map.std->lvl.local_size && doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) { *net_lvl = doi_def->map.std->lvl.local[host_lvl]; return 0; } return -EPERM; } return -EINVAL;}/** * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host * @doi_def: the DOI definition * @net_lvl: the network/CIPSO MLS level * @host_lvl: the host MLS level * * Description: * Perform a label mapping to translate a CIPSO level to the correct local MLS * level using the given DOI definition. Returns zero on success, negative * values otherwise. * */static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def, u32 net_lvl, u32 *host_lvl){ struct cipso_v4_std_map_tbl *map_tbl; switch (doi_def->type) { case CIPSO_V4_MAP_PASS: *host_lvl = net_lvl; return 0; case CIPSO_V4_MAP_STD: map_tbl = doi_def->map.std; if (net_lvl < map_tbl->lvl.cipso_size && map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { *host_lvl = doi_def->map.std->lvl.cipso[net_lvl]; return 0; } return -EPERM; } return -EINVAL;}/** * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid * @doi_def: the DOI definition * @bitmap: category bitmap * @bitmap_len: bitmap length in bytes * * Description: * Checks the given category bitmap against the given DOI definition and * returns a negative value if any of the categories in the bitmap do not have * a valid mapping and a zero value if all of the categories are valid. * */static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, const unsigned char *bitmap, u32 bitmap_len){ int cat = -1; u32 bitmap_len_bits = bitmap_len * 8; u32 cipso_cat_size; u32 *cipso_array; switch (doi_def->type) { case CIPSO_V4_MAP_PASS: return 0; case CIPSO_V4_MAP_STD: cipso_cat_size = doi_def->map.std->cat.cipso_size; cipso_array = doi_def->map.std->cat.cipso; for (;;) { cat = cipso_v4_bitmap_walk(bitmap, bitmap_len_bits, cat + 1, 1); if (cat < 0) break; if (cat >= cipso_cat_size || cipso_array[cat] >= CIPSO_V4_INV_CAT) return -EFAULT; } if (cat == -1) return 0; break; } return -EFAULT;}/** * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network * @doi_def: the DOI definition * @secattr: the security attributes * @net_cat: the zero'd out category bitmap in network/CIPSO format * @net_cat_len: the length of the CIPSO bitmap in bytes * * Description: * Perform a label mapping to translate a local MLS category bitmap to the * correct CIPSO bitmap using the given DOI definition. Returns the minimum * size in bytes of the network bitmap on success, negative values otherwise. * */static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, const struct netlbl_lsm_secattr *secattr, unsigned char *net_cat, u32 net_cat_len){ int host_spot = -1; u32 net_spot = CIPSO_V4_INV_CAT; u32 net_spot_max = 0; u32 net_clen_bits = net_cat_len * 8; u32 host_cat_size = 0; u32 *host_cat_array = NULL; if (doi_def->type == CIPSO_V4_MAP_STD) { host_cat_size = doi_def->map.std->cat.local_size; host_cat_array = doi_def->map.std->cat.local; } for (;;) { host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat, host_spot + 1); if (host_spot < 0) break; switch (doi_def->type) { case CIPSO_V4_MAP_PASS: net_spot = host_spot; break; case CIPSO_V4_MAP_STD: if (host_spot >= host_cat_size) return -EPERM; net_spot = host_cat_array[host_spot]; if (net_spot >= CIPSO_V4_INV_CAT) return -EPERM; break; } if (net_spot >= net_clen_bits) return -ENOSPC; cipso_v4_bitmap_setbit(net_cat, net_spot, 1); if (net_spot > net_spot_max) net_spot_max = net_spot; } if (++net_spot_max % 8) return net_spot_max / 8 + 1; return net_spot_max / 8;}/** * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host * @doi_def: the DOI definition * @net_cat: the category bitmap in network/CIPSO format * @net_cat_len: the length of the CIPSO bitmap in bytes * @secattr: the security attributes * * Description: * Perform a label mapping to translate a CIPSO bitmap to the correct local * MLS category bitmap using the given DOI definition. Returns zero on * success, negative values on failure. * */static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, const unsigned char *net_cat, u32 net_cat_len, struct netlbl_lsm_secattr *secattr){ int ret_val; int net_spot = -1; u32 host_spot = CIPSO_V4_INV_CAT; u32 net_clen_bits = net_cat_len * 8; u32 net_cat_size = 0; u32 *net_cat_array = NULL; if (doi_def->type == CIPSO_V4_MAP_STD) { net_cat_size = doi_def->map.std->cat.cipso_size; net_cat_array = doi_def->map.std->cat.cipso; } for (;;) { net_spot = cipso_v4_bitmap_walk(net_cat, net_clen_bits, net_spot + 1, 1); if (net_spot < 0) { if (net_spot == -2) return -EFAULT; return 0; } switch (doi_def->type) { case CIPSO_V4_MAP_PASS: host_spot = net_spot; break; case CIPSO_V4_MAP_STD: if (net_spot >= net_cat_size) return -EPERM; host_spot = net_cat_array[net_spot]; if (host_spot >= CIPSO_V4_INV_CAT) return -EPERM; break; } ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, host_spot, GFP_ATOMIC); if (ret_val != 0) return ret_val; } return -EINVAL;}/** * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -