diff options
Diffstat (limited to 'net/netlabel')
-rw-r--r-- | net/netlabel/netlabel_cipso_v4.c | 90 | ||||
-rw-r--r-- | net/netlabel/netlabel_domainhash.c | 48 | ||||
-rw-r--r-- | net/netlabel/netlabel_kapi.c | 212 | ||||
-rw-r--r-- | net/netlabel/netlabel_mgmt.c | 42 | ||||
-rw-r--r-- | net/netlabel/netlabel_unlabeled.c | 48 | ||||
-rw-r--r-- | net/netlabel/netlabel_user.c | 7 | ||||
-rw-r--r-- | net/netlabel/netlabel_user.h | 31 |
7 files changed, 332 insertions, 146 deletions
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index a6ce1d6d5c5..73e0ff469bf 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -130,12 +130,12 @@ static int netlbl_cipsov4_add_common(struct genl_info *info, nla_for_each_nested(nla, info->attrs[NLBL_CIPSOV4_A_TAGLST], nla_rem) if (nla->nla_type == NLBL_CIPSOV4_A_TAG) { - if (iter > CIPSO_V4_TAG_MAXCNT) + if (iter >= CIPSO_V4_TAG_MAXCNT) return -EINVAL; doi_def->tags[iter++] = nla_get_u8(nla); } - if (iter < CIPSO_V4_TAG_MAXCNT) - doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; + while (iter < CIPSO_V4_TAG_MAXCNT) + doi_def->tags[iter++] = CIPSO_V4_TAG_INVALID; return 0; } @@ -162,6 +162,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) struct nlattr *nla_b; int nla_a_rem; int nla_b_rem; + u32 iter; if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] || !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]) @@ -185,20 +186,31 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) ret_val = netlbl_cipsov4_add_common(info, doi_def); if (ret_val != 0) goto add_std_failure; + ret_val = -EINVAL; nla_for_each_nested(nla_a, info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], nla_a_rem) if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) { + if (nla_validate_nested(nla_a, + NLBL_CIPSOV4_A_MAX, + netlbl_cipsov4_genl_policy) != 0) + goto add_std_failure; nla_for_each_nested(nla_b, nla_a, nla_b_rem) switch (nla_b->nla_type) { case NLBL_CIPSOV4_A_MLSLVLLOC: + if (nla_get_u32(nla_b) > + CIPSO_V4_MAX_LOC_LVLS) + goto add_std_failure; if (nla_get_u32(nla_b) >= doi_def->map.std->lvl.local_size) doi_def->map.std->lvl.local_size = nla_get_u32(nla_b) + 1; break; case NLBL_CIPSOV4_A_MLSLVLREM: + if (nla_get_u32(nla_b) > + CIPSO_V4_MAX_REM_LVLS) + goto add_std_failure; if (nla_get_u32(nla_b) >= doi_def->map.std->lvl.cipso_size) doi_def->map.std->lvl.cipso_size = @@ -206,9 +218,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) break; } } - if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS || - doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS) - goto add_std_failure; doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, sizeof(u32), GFP_KERNEL); @@ -223,6 +232,10 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) ret_val = -ENOMEM; goto add_std_failure; } + for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) + doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; + for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) + doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; nla_for_each_nested(nla_a, info->attrs[NLBL_CIPSOV4_A_MLSLVLLST], nla_a_rem) @@ -230,11 +243,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) struct nlattr *lvl_loc; struct nlattr *lvl_rem; - if (nla_validate_nested(nla_a, - NLBL_CIPSOV4_A_MAX, - netlbl_cipsov4_genl_policy) != 0) - goto add_std_failure; - lvl_loc = nla_find_nested(nla_a, NLBL_CIPSOV4_A_MLSLVLLOC); lvl_rem = nla_find_nested(nla_a, @@ -264,12 +272,18 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) nla_for_each_nested(nla_b, nla_a, nla_b_rem) switch (nla_b->nla_type) { case NLBL_CIPSOV4_A_MLSCATLOC: + if (nla_get_u32(nla_b) > + CIPSO_V4_MAX_LOC_CATS) + goto add_std_failure; if (nla_get_u32(nla_b) >= doi_def->map.std->cat.local_size) doi_def->map.std->cat.local_size = nla_get_u32(nla_b) + 1; break; case NLBL_CIPSOV4_A_MLSCATREM: + if (nla_get_u32(nla_b) > + CIPSO_V4_MAX_REM_CATS) + goto add_std_failure; if (nla_get_u32(nla_b) >= doi_def->map.std->cat.cipso_size) doi_def->map.std->cat.cipso_size = @@ -277,9 +291,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) break; } } - if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS || - doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) - goto add_std_failure; doi_def->map.std->cat.local = kcalloc( doi_def->map.std->cat.local_size, sizeof(u32), @@ -296,6 +307,10 @@ static int netlbl_cipsov4_add_std(struct genl_info *info) ret_val = -ENOMEM; goto add_std_failure; } + for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) + doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; + for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) + doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; nla_for_each_nested(nla_a, info->attrs[NLBL_CIPSOV4_A_MLSCATLST], nla_a_rem) @@ -407,12 +422,14 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD, &audit_info); - audit_log_format(audit_buf, - " cipso_doi=%u cipso_type=%s res=%u", - doi, - type_str, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " cipso_doi=%u cipso_type=%s res=%u", + doi, + type_str, + ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } return ret_val; } @@ -452,17 +469,13 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) } list_start: - ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL); if (ans_skb == NULL) { ret_val = -ENOMEM; goto list_failure; } - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_cipsov4_gnl_family.id, - 0, - NLBL_CIPSOV4_C_LIST); + data = genlmsg_put_reply(ans_skb, info, &netlbl_cipsov4_gnl_family, + 0, NLBL_CIPSOV4_C_LIST); if (data == NULL) { ret_val = -ENOMEM; goto list_failure; @@ -568,7 +581,7 @@ list_start: genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto list_failure; @@ -607,12 +620,9 @@ static int netlbl_cipsov4_listall_cb(struct cipso_v4_doi *doi_def, void *arg) struct netlbl_cipsov4_doiwalk_arg *cb_arg = arg; void *data; - data = netlbl_netlink_hdr_put(cb_arg->skb, - NETLINK_CB(cb_arg->nl_cb->skb).pid, - cb_arg->seq, - netlbl_cipsov4_gnl_family.id, - NLM_F_MULTI, - NLBL_CIPSOV4_C_LISTALL); + data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, + cb_arg->seq, &netlbl_cipsov4_gnl_family, + NLM_F_MULTI, NLBL_CIPSOV4_C_LISTALL); if (data == NULL) goto listall_cb_failure; @@ -687,11 +697,13 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL, &audit_info); - audit_log_format(audit_buf, - " cipso_doi=%u res=%u", - doi, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " cipso_doi=%u res=%u", + doi, + ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } return ret_val; } diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index af4371d3b45..f46a0aeec44 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -202,7 +202,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, int ret_val; u32 bkt; struct audit_buffer *audit_buf; - char *audit_domain; switch (entry->type) { case NETLBL_NLTYPE_UNLABELED: @@ -243,24 +242,24 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, } else ret_val = -EINVAL; - if (entry->domain != NULL) - audit_domain = entry->domain; - else - audit_domain = "(default)"; audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); - audit_log_format(audit_buf, " nlbl_domain=%s", audit_domain); - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - audit_log_format(audit_buf, " nlbl_protocol=unlbl"); - break; - case NETLBL_NLTYPE_CIPSOV4: + if (audit_buf != NULL) { audit_log_format(audit_buf, - " nlbl_protocol=cipsov4 cipso_doi=%u", - entry->type_def.cipsov4->doi); - break; + " nlbl_domain=%s", + entry->domain ? entry->domain : "(default)"); + switch (entry->type) { + case NETLBL_NLTYPE_UNLABELED: + audit_log_format(audit_buf, " nlbl_protocol=unlbl"); + break; + case NETLBL_NLTYPE_CIPSOV4: + audit_log_format(audit_buf, + " nlbl_protocol=cipsov4 cipso_doi=%u", + entry->type_def.cipsov4->doi); + break; + } + audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); } - audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); rcu_read_unlock(); @@ -310,7 +309,6 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) int ret_val = -ENOENT; struct netlbl_dom_map *entry; struct audit_buffer *audit_buf; - char *audit_domain; rcu_read_lock(); if (domain != NULL) @@ -348,16 +346,14 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) spin_unlock(&netlbl_domhsh_def_lock); } - if (entry->domain != NULL) - audit_domain = entry->domain; - else - audit_domain = "(default)"; audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); - audit_log_format(audit_buf, - " nlbl_domain=%s res=%u", - audit_domain, - ret_val == 0 ? 1 : 0); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " nlbl_domain=%s res=%u", + entry->domain ? entry->domain : "(default)", + ret_val == 0 ? 1 : 0); + audit_log_end(audit_buf); + } if (ret_val == 0) call_rcu(&entry->rcu, netlbl_domhsh_free_entry); diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index ff971103fd0..e03a3282c55 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -40,6 +40,207 @@ #include "netlabel_user.h" /* + * Security Attribute Functions + */ + +/** + * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit + * @catmap: the category bitmap + * @offset: the offset to start searching at, in bits + * + * Description: + * This function walks a LSM secattr category bitmap starting at @offset and + * returns the spot of the first set bit or -ENOENT if no bits are set. + * + */ +int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, + u32 offset) +{ + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 node_idx; + u32 node_bit; + NETLBL_CATMAP_MAPTYPE bitmap; + + if (offset > iter->startbit) { + while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { + iter = iter->next; + if (iter == NULL) + return -ENOENT; + } + node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; + node_bit = offset - iter->startbit - + (NETLBL_CATMAP_MAPSIZE * node_idx); + } else { + node_idx = 0; + node_bit = 0; + } + bitmap = iter->bitmap[node_idx] >> node_bit; + + for (;;) { + if (bitmap != 0) { + while ((bitmap & NETLBL_CATMAP_BIT) == 0) { + bitmap >>= 1; + node_bit++; + } + return iter->startbit + + (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit; + } + if (++node_idx >= NETLBL_CATMAP_MAPCNT) { + if (iter->next != NULL) { + iter = iter->next; + node_idx = 0; + } else + return -ENOENT; + } + bitmap = iter->bitmap[node_idx]; + node_bit = 0; + } + + return -ENOENT; +} + +/** + * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits + * @catmap: the category bitmap + * @offset: the offset to start searching at, in bits + * + * Description: + * This function walks a LSM secattr category bitmap starting at @offset and + * returns the spot of the first cleared bit or -ENOENT if the offset is past + * the end of the bitmap. + * + */ +int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, + u32 offset) +{ + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 node_idx; + u32 node_bit; + NETLBL_CATMAP_MAPTYPE bitmask; + NETLBL_CATMAP_MAPTYPE bitmap; + + if (offset > iter->startbit) { + while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { + iter = iter->next; + if (iter == NULL) + return -ENOENT; + } + node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; + node_bit = offset - iter->startbit - + (NETLBL_CATMAP_MAPSIZE * node_idx); + } else { + node_idx = 0; + node_bit = 0; + } + bitmask = NETLBL_CATMAP_BIT << node_bit; + + for (;;) { + bitmap = iter->bitmap[node_idx]; + while (bitmask != 0 && (bitmap & bitmask) != 0) { + bitmask <<= 1; + node_bit++; + } + + if (bitmask != 0) + return iter->startbit + + (NETLBL_CATMAP_MAPSIZE * node_idx) + + node_bit - 1; + else if (++node_idx >= NETLBL_CATMAP_MAPCNT) { + if (iter->next == NULL) + return iter->startbit + NETLBL_CATMAP_SIZE - 1; + iter = iter->next; + node_idx = 0; + } + bitmask = NETLBL_CATMAP_BIT; + node_bit = 0; + } + + return -ENOENT; +} + +/** + * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap + * @catmap: the category bitmap + * @bit: the bit to set + * @flags: memory allocation flags + * + * Description: + * Set the bit specified by @bit in @catmap. Returns zero on success, + * negative values on failure. + * + */ +int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap, + u32 bit, + gfp_t flags) +{ + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 node_bit; + u32 node_idx; + + while (iter->next != NULL && + bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) + iter = iter->next; + if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) { + iter->next = netlbl_secattr_catmap_alloc(flags); + if (iter->next == NULL) + return -ENOMEM; + iter = iter->next; + iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1); + } + + /* gcc always rounds to zero when doing integer division */ + node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE; + node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx); + iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit; + + return 0; +} + +/** + * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap + * @catmap: the category bitmap + * @start: the starting bit + * @end: the last bit in the string + * @flags: memory allocation flags + * + * Description: + * Set a range of bits, starting at @start and ending with @end. Returns zero + * on success, negative values on failure. + * + */ +int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, + u32 start, + u32 end, + gfp_t flags) +{ + int ret_val = 0; + struct netlbl_lsm_secattr_catmap *iter = catmap; + u32 iter_max_spot; + u32 spot; + + /* XXX - This could probably be made a bit faster by combining writes + * to the catmap instead of setting a single bit each time, but for + * right now skipping to the start of the range in the catmap should + * be a nice improvement over calling the individual setbit function + * repeatedly from a loop. */ + + while (iter->next != NULL && + start >= (iter->startbit + NETLBL_CATMAP_SIZE)) + iter = iter->next; + iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; + + for (spot = start; spot <= end && ret_val == 0; spot++) { + if (spot >= iter_max_spot && iter->next != NULL) { + iter = iter->next; + iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; + } + ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC); + } + + return ret_val; +} + +/* * LSM Functions */ @@ -62,6 +263,9 @@ int netlbl_socket_setattr(const struct socket *sock, int ret_val = -ENOENT; struct netlbl_dom_map *dom_entry; + if ((secattr->flags & NETLBL_SECATTR_DOMAIN) == 0) + return -ENOENT; + rcu_read_lock(); dom_entry = netlbl_domhsh_getentry(secattr->domain); if (dom_entry == NULL) @@ -146,10 +350,8 @@ int netlbl_socket_getattr(const struct socket *sock, int netlbl_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr) { - int ret_val; - - ret_val = cipso_v4_skbuff_getattr(skb, secattr); - if (ret_val == 0) + if (CIPSO_V4_OPTEXIST(skb) && + cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; return netlbl_unlabel_getattr(secattr); @@ -200,7 +402,7 @@ void netlbl_cache_invalidate(void) int netlbl_cache_add(const struct sk_buff *skb, const struct netlbl_lsm_secattr *secattr) { - if (secattr->cache == NULL) + if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) return -ENOMSG; if (CIPSO_V4_OPTEXIST(skb)) diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 53c9079ad2c..e8c80f33f3d 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -188,12 +188,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) struct netlbl_domhsh_walk_arg *cb_arg = arg; void *data; - data = netlbl_netlink_hdr_put(cb_arg->skb, - NETLINK_CB(cb_arg->nl_cb->skb).pid, - cb_arg->seq, - netlbl_mgmt_gnl_family.id, - NLM_F_MULTI, - NLBL_MGMT_C_LISTALL); + data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, + cb_arg->seq, &netlbl_mgmt_gnl_family, + NLM_F_MULTI, NLBL_MGMT_C_LISTALL); if (data == NULL) goto listall_cb_failure; @@ -356,15 +353,11 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) void *data; struct netlbl_dom_map *entry; - ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) return -ENOMEM; - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_mgmt_gnl_family.id, - 0, - NLBL_MGMT_C_LISTDEF); + data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, + 0, NLBL_MGMT_C_LISTDEF); if (data == NULL) goto listdef_failure; @@ -390,7 +383,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto listdef_failure; return 0; @@ -422,12 +415,9 @@ static int netlbl_mgmt_protocols_cb(struct sk_buff *skb, int ret_val = -ENOMEM; void *data; - data = netlbl_netlink_hdr_put(skb, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - netlbl_mgmt_gnl_family.id, - NLM_F_MULTI, - NLBL_MGMT_C_PROTOCOLS); + data = genlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, + &netlbl_mgmt_gnl_family, NLM_F_MULTI, + NLBL_MGMT_C_PROTOCOLS); if (data == NULL) goto protocols_cb_failure; @@ -492,15 +482,11 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) struct sk_buff *ans_skb = NULL; void *data; - ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) return -ENOMEM; - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_mgmt_gnl_family.id, - 0, - NLBL_MGMT_C_VERSION); + data = genlmsg_put_reply(ans_skb, info, &netlbl_mgmt_gnl_family, + 0, NLBL_MGMT_C_VERSION); if (data == NULL) goto version_failure; @@ -512,7 +498,7 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto version_failure; return 0; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 1833ad233b3..5bc37181662 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -35,6 +35,7 @@ #include <linux/socket.h> #include <linux/string.h> #include <linux/skbuff.h> +#include <linux/audit.h> #include <net/sock.h> #include <net/netlink.h> #include <net/genetlink.h> @@ -47,7 +48,8 @@ #include "netlabel_unlabeled.h" /* Accept unlabeled packets flag */ -static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0); +static DEFINE_SPINLOCK(netlabel_unlabel_acceptflg_lock); +static u8 netlabel_unlabel_acceptflg = 0; /* NetLabel Generic NETLINK CIPSOv4 family */ static struct genl_family netlbl_unlabel_gnl_family = { @@ -82,13 +84,20 @@ static void netlbl_unlabel_acceptflg_set(u8 value, struct audit_buffer *audit_buf; u8 old_val; - old_val = atomic_read(&netlabel_unlabel_accept_flg); - atomic_set(&netlabel_unlabel_accept_flg, value); + rcu_read_lock(); + old_val = netlabel_unlabel_acceptflg; + spin_lock(&netlabel_unlabel_acceptflg_lock); + netlabel_unlabel_acceptflg = value; + spin_unlock(&netlabel_unlabel_acceptflg_lock); + rcu_read_unlock(); audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, audit_info); - audit_log_format(audit_buf, " unlbl_accept=%u old=%u", value, old_val); - audit_log_end(audit_buf); + if (audit_buf != NULL) { + audit_log_format(audit_buf, + " unlbl_accept=%u old=%u", value, old_val); + audit_log_end(audit_buf); + } } /* @@ -138,29 +147,27 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) struct sk_buff *ans_skb; void *data; - ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (ans_skb == NULL) goto list_failure; - data = netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - info->snd_seq, - netlbl_unlabel_gnl_family.id, - 0, - NLBL_UNLABEL_C_LIST); + data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, + 0, NLBL_UNLABEL_C_LIST); if (data == NULL) { ret_val = -ENOMEM; goto list_failure; } + rcu_read_lock(); ret_val = nla_put_u8(ans_skb, NLBL_UNLABEL_A_ACPTFLG, - atomic_read(&netlabel_unlabel_accept_flg)); + netlabel_unlabel_acceptflg); + rcu_read_unlock(); if (ret_val != 0) goto list_failure; genlmsg_end(ans_skb, data); - ret_val = genlmsg_unicast(ans_skb, info->snd_pid); + ret_val = genlmsg_reply(ans_skb, info); if (ret_val != 0) goto list_failure; return 0; @@ -240,10 +247,17 @@ int netlbl_unlabel_genl_init(void) */ int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) { - if (atomic_read(&netlabel_unlabel_accept_flg) == 1) - return netlbl_secattr_init(secattr); + int ret_val; - return -ENOMSG; + rcu_read_lock(); + if (netlabel_unlabel_acceptflg == 1) { + netlbl_secattr_init(secattr); + ret_val = 0; + } else + ret_val = -ENOMSG; + rcu_read_unlock(); + + return ret_val; } /** diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 98a416381e6..42f12bd6596 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c @@ -46,6 +46,10 @@ #include "netlabel_cipso_v4.h" #include "netlabel_user.h" +/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for + * details */ +extern int audit_enabled; + /* * NetLabel NETLINK Setup Functions */ @@ -101,6 +105,9 @@ struct audit_buffer *netlbl_audit_start_common(int type, char *secctx; u32 secctx_len; + if (audit_enabled == 0) + return NULL; + audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type); if (audit_buf == NULL) return NULL; diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h index 47967ef3296..6d7f4ab46c2 100644 --- a/net/netlabel/netlabel_user.h +++ b/net/netlabel/netlabel_user.h @@ -42,37 +42,6 @@ /* NetLabel NETLINK helper functions */ /** - * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff - * @skb: the packet - * @pid: the PID of the receipient - * @seq: the sequence number - * @type: the generic NETLINK message family type - * @cmd: command - * - * Description: - * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr - * struct to the packet. Returns a pointer to the start of the payload buffer - * on success or NULL on failure. - * - */ -static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, - u32 pid, - u32 seq, - int type, - int flags, - u8 cmd) -{ - return genlmsg_put(skb, - pid, - seq, - type, - 0, - flags, - cmd, - NETLBL_PROTO_VERSION); -} - -/** * netlbl_netlink_auditinfo - Fetch the audit information from a NETLINK msg * @skb: the packet * @audit_info: NetLabel audit information |