Commit 4be2700f authored by Paul Moore's avatar Paul Moore Committed by David S. Miller

[NetLabel]: correct usage of RCU locking

This fixes some awkward, and perhaps even problematic, RCU lock usage in the
NetLabel code as well as some other related trivial cleanups found when
looking through the RCU locking.  Most of the changes involve removing the
redundant RCU read locks wrapping spinlocks in the case of a RCU writer.
Signed-off-by: default avatarPaul Moore <paul.moore@hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 94d3b1e5
...@@ -504,22 +504,16 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) ...@@ -504,22 +504,16 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
INIT_RCU_HEAD(&doi_def->rcu); INIT_RCU_HEAD(&doi_def->rcu);
INIT_LIST_HEAD(&doi_def->dom_list); INIT_LIST_HEAD(&doi_def->dom_list);
rcu_read_lock();
if (cipso_v4_doi_search(doi_def->doi) != NULL)
goto doi_add_failure_rlock;
spin_lock(&cipso_v4_doi_list_lock); spin_lock(&cipso_v4_doi_list_lock);
if (cipso_v4_doi_search(doi_def->doi) != NULL) if (cipso_v4_doi_search(doi_def->doi) != NULL)
goto doi_add_failure_slock; goto doi_add_failure;
list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list); list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_unlock();
return 0; return 0;
doi_add_failure_slock: doi_add_failure:
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
doi_add_failure_rlock:
rcu_read_unlock();
return -EEXIST; return -EEXIST;
} }
...@@ -543,29 +537,23 @@ int cipso_v4_doi_remove(u32 doi, ...@@ -543,29 +537,23 @@ int cipso_v4_doi_remove(u32 doi,
struct cipso_v4_doi *doi_def; struct cipso_v4_doi *doi_def;
struct cipso_v4_domhsh_entry *dom_iter; struct cipso_v4_domhsh_entry *dom_iter;
rcu_read_lock();
if (cipso_v4_doi_search(doi) != NULL) {
spin_lock(&cipso_v4_doi_list_lock); spin_lock(&cipso_v4_doi_list_lock);
doi_def = cipso_v4_doi_search(doi); doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL) { if (doi_def != NULL) {
spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_unlock();
return -ENOENT;
}
doi_def->valid = 0; doi_def->valid = 0;
list_del_rcu(&doi_def->list); list_del_rcu(&doi_def->list);
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_lock();
list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
if (dom_iter->valid) if (dom_iter->valid)
netlbl_domhsh_remove(dom_iter->domain, netlbl_domhsh_remove(dom_iter->domain,
audit_info); audit_info);
cipso_v4_cache_invalidate();
rcu_read_unlock(); rcu_read_unlock();
cipso_v4_cache_invalidate();
call_rcu(&doi_def->rcu, callback); call_rcu(&doi_def->rcu, callback);
return 0; return 0;
} }
rcu_read_unlock(); spin_unlock(&cipso_v4_doi_list_lock);
return -ENOENT; return -ENOENT;
} }
...@@ -653,22 +641,19 @@ int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain) ...@@ -653,22 +641,19 @@ int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
new_dom->valid = 1; new_dom->valid = 1;
INIT_RCU_HEAD(&new_dom->rcu); INIT_RCU_HEAD(&new_dom->rcu);
rcu_read_lock();
spin_lock(&cipso_v4_doi_list_lock); spin_lock(&cipso_v4_doi_list_lock);
list_for_each_entry_rcu(iter, &doi_def->dom_list, list) list_for_each_entry(iter, &doi_def->dom_list, list)
if (iter->valid && if (iter->valid &&
((domain != NULL && iter->domain != NULL && ((domain != NULL && iter->domain != NULL &&
strcmp(iter->domain, domain) == 0) || strcmp(iter->domain, domain) == 0) ||
(domain == NULL && iter->domain == NULL))) { (domain == NULL && iter->domain == NULL))) {
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_unlock();
kfree(new_dom->domain); kfree(new_dom->domain);
kfree(new_dom); kfree(new_dom);
return -EEXIST; return -EEXIST;
} }
list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_unlock();
return 0; return 0;
} }
...@@ -689,9 +674,8 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, ...@@ -689,9 +674,8 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
{ {
struct cipso_v4_domhsh_entry *iter; struct cipso_v4_domhsh_entry *iter;
rcu_read_lock();
spin_lock(&cipso_v4_doi_list_lock); spin_lock(&cipso_v4_doi_list_lock);
list_for_each_entry_rcu(iter, &doi_def->dom_list, list) list_for_each_entry(iter, &doi_def->dom_list, list)
if (iter->valid && if (iter->valid &&
((domain != NULL && iter->domain != NULL && ((domain != NULL && iter->domain != NULL &&
strcmp(iter->domain, domain) == 0) || strcmp(iter->domain, domain) == 0) ||
...@@ -699,13 +683,10 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, ...@@ -699,13 +683,10 @@ int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
iter->valid = 0; iter->valid = 0;
list_del_rcu(&iter->list); list_del_rcu(&iter->list);
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_unlock();
call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
return 0; return 0;
} }
spin_unlock(&cipso_v4_doi_list_lock); spin_unlock(&cipso_v4_doi_list_lock);
rcu_read_unlock();
return -ENOENT; return -ENOENT;
} }
......
...@@ -178,11 +178,9 @@ int netlbl_domhsh_init(u32 size) ...@@ -178,11 +178,9 @@ int netlbl_domhsh_init(u32 size)
for (iter = 0; iter < hsh_tbl->size; iter++) for (iter = 0; iter < hsh_tbl->size; iter++)
INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
rcu_read_lock();
spin_lock(&netlbl_domhsh_lock); spin_lock(&netlbl_domhsh_lock);
rcu_assign_pointer(netlbl_domhsh, hsh_tbl); rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
spin_unlock(&netlbl_domhsh_lock); spin_unlock(&netlbl_domhsh_lock);
rcu_read_unlock();
return 0; return 0;
} }
...@@ -222,7 +220,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, ...@@ -222,7 +220,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
entry->valid = 1; entry->valid = 1;
INIT_RCU_HEAD(&entry->rcu); INIT_RCU_HEAD(&entry->rcu);
ret_val = 0;
rcu_read_lock(); rcu_read_lock();
if (entry->domain != NULL) { if (entry->domain != NULL) {
bkt = netlbl_domhsh_hash(entry->domain); bkt = netlbl_domhsh_hash(entry->domain);
...@@ -233,7 +230,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, ...@@ -233,7 +230,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
else else
ret_val = -EEXIST; ret_val = -EEXIST;
spin_unlock(&netlbl_domhsh_lock); spin_unlock(&netlbl_domhsh_lock);
} else if (entry->domain == NULL) { } else {
INIT_LIST_HEAD(&entry->list); INIT_LIST_HEAD(&entry->list);
spin_lock(&netlbl_domhsh_def_lock); spin_lock(&netlbl_domhsh_def_lock);
if (rcu_dereference(netlbl_domhsh_def) == NULL) if (rcu_dereference(netlbl_domhsh_def) == NULL)
...@@ -241,9 +238,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, ...@@ -241,9 +238,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
else else
ret_val = -EEXIST; ret_val = -EEXIST;
spin_unlock(&netlbl_domhsh_def_lock); spin_unlock(&netlbl_domhsh_def_lock);
} else }
ret_val = -EINVAL;
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
if (audit_buf != NULL) { if (audit_buf != NULL) {
audit_log_format(audit_buf, audit_log_format(audit_buf,
...@@ -262,7 +257,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, ...@@ -262,7 +257,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
audit_log_end(audit_buf); audit_log_end(audit_buf);
} }
rcu_read_unlock(); rcu_read_unlock();
if (ret_val != 0) { if (ret_val != 0) {
...@@ -313,38 +307,30 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) ...@@ -313,38 +307,30 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
struct audit_buffer *audit_buf; struct audit_buffer *audit_buf;
rcu_read_lock(); rcu_read_lock();
if (domain != NULL) entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1));
entry = netlbl_domhsh_search(domain, 0);
else
entry = netlbl_domhsh_search(domain, 1);
if (entry == NULL) if (entry == NULL)
goto remove_return; goto remove_return;
switch (entry->type) { switch (entry->type) {
case NETLBL_NLTYPE_UNLABELED:
break;
case NETLBL_NLTYPE_CIPSOV4: case NETLBL_NLTYPE_CIPSOV4:
ret_val = cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
entry->domain); entry->domain);
if (ret_val != 0)
goto remove_return;
break; break;
} }
ret_val = 0;
if (entry != rcu_dereference(netlbl_domhsh_def)) { if (entry != rcu_dereference(netlbl_domhsh_def)) {
spin_lock(&netlbl_domhsh_lock); spin_lock(&netlbl_domhsh_lock);
if (entry->valid) { if (entry->valid) {
entry->valid = 0; entry->valid = 0;
list_del_rcu(&entry->list); list_del_rcu(&entry->list);
} else ret_val = 0;
ret_val = -ENOENT; }
spin_unlock(&netlbl_domhsh_lock); spin_unlock(&netlbl_domhsh_lock);
} else { } else {
spin_lock(&netlbl_domhsh_def_lock); spin_lock(&netlbl_domhsh_def_lock);
if (entry->valid) { if (entry->valid) {
entry->valid = 0; entry->valid = 0;
rcu_assign_pointer(netlbl_domhsh_def, NULL); rcu_assign_pointer(netlbl_domhsh_def, NULL);
} else ret_val = 0;
ret_val = -ENOENT; }
spin_unlock(&netlbl_domhsh_def_lock); spin_unlock(&netlbl_domhsh_def_lock);
} }
...@@ -357,11 +343,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) ...@@ -357,11 +343,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
audit_log_end(audit_buf); audit_log_end(audit_buf);
} }
if (ret_val == 0)
call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
remove_return: remove_return:
rcu_read_unlock(); rcu_read_unlock();
if (ret_val == 0)
call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
return ret_val; return ret_val;
} }
......
...@@ -85,11 +85,9 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { ...@@ -85,11 +85,9 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
*/ */
void netlbl_mgmt_protocount_inc(void) void netlbl_mgmt_protocount_inc(void)
{ {
rcu_read_lock();
spin_lock(&netlabel_mgmt_protocount_lock); spin_lock(&netlabel_mgmt_protocount_lock);
netlabel_mgmt_protocount++; netlabel_mgmt_protocount++;
spin_unlock(&netlabel_mgmt_protocount_lock); spin_unlock(&netlabel_mgmt_protocount_lock);
rcu_read_unlock();
} }
/** /**
...@@ -103,12 +101,10 @@ void netlbl_mgmt_protocount_inc(void) ...@@ -103,12 +101,10 @@ void netlbl_mgmt_protocount_inc(void)
*/ */
void netlbl_mgmt_protocount_dec(void) void netlbl_mgmt_protocount_dec(void)
{ {
rcu_read_lock();
spin_lock(&netlabel_mgmt_protocount_lock); spin_lock(&netlabel_mgmt_protocount_lock);
if (netlabel_mgmt_protocount > 0) if (netlabel_mgmt_protocount > 0)
netlabel_mgmt_protocount--; netlabel_mgmt_protocount--;
spin_unlock(&netlabel_mgmt_protocount_lock); spin_unlock(&netlabel_mgmt_protocount_lock);
rcu_read_unlock();
} }
/** /**
......
...@@ -84,12 +84,10 @@ static void netlbl_unlabel_acceptflg_set(u8 value, ...@@ -84,12 +84,10 @@ static void netlbl_unlabel_acceptflg_set(u8 value,
struct audit_buffer *audit_buf; struct audit_buffer *audit_buf;
u8 old_val; u8 old_val;
rcu_read_lock();
old_val = netlabel_unlabel_acceptflg;
spin_lock(&netlabel_unlabel_acceptflg_lock); spin_lock(&netlabel_unlabel_acceptflg_lock);
old_val = netlabel_unlabel_acceptflg;
netlabel_unlabel_acceptflg = value; netlabel_unlabel_acceptflg = value;
spin_unlock(&netlabel_unlabel_acceptflg_lock); spin_unlock(&netlabel_unlabel_acceptflg_lock);
rcu_read_unlock();
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
audit_info); audit_info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment