diff options
Diffstat (limited to 'net/netlabel/netlabel_domainhash.c')
-rw-r--r-- | net/netlabel/netlabel_domainhash.c | 77 |
1 files changed, 43 insertions, 34 deletions
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index b3675bd7db33..9a8ea0195c4f 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -54,9 +54,6 @@ struct netlbl_domhsh_tbl { | |||
54 | * hash table should be okay */ | 54 | * hash table should be okay */ |
55 | static DEFINE_SPINLOCK(netlbl_domhsh_lock); | 55 | static DEFINE_SPINLOCK(netlbl_domhsh_lock); |
56 | static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; | 56 | static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; |
57 | |||
58 | /* Default domain mapping */ | ||
59 | static DEFINE_SPINLOCK(netlbl_domhsh_def_lock); | ||
60 | static struct netlbl_dom_map *netlbl_domhsh_def = NULL; | 57 | static struct netlbl_dom_map *netlbl_domhsh_def = NULL; |
61 | 58 | ||
62 | /* | 59 | /* |
@@ -109,17 +106,14 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
109 | /** | 106 | /** |
110 | * netlbl_domhsh_search - Search for a domain entry | 107 | * netlbl_domhsh_search - Search for a domain entry |
111 | * @domain: the domain | 108 | * @domain: the domain |
112 | * @def: return default if no match is found | ||
113 | * | 109 | * |
114 | * Description: | 110 | * Description: |
115 | * Searches the domain hash table and returns a pointer to the hash table | 111 | * Searches the domain hash table and returns a pointer to the hash table |
116 | * entry if found, otherwise NULL is returned. If @def is non-zero and a | 112 | * entry if found, otherwise NULL is returned. The caller is responsibile for |
117 | * match is not found in the domain hash table the default mapping is returned | 113 | * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). |
118 | * if it exists. The caller is responsibile for the rcu hash table locks | ||
119 | * (i.e. the caller much call rcu_read_[un]lock()). | ||
120 | * | 114 | * |
121 | */ | 115 | */ |
122 | static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) | 116 | static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) |
123 | { | 117 | { |
124 | u32 bkt; | 118 | u32 bkt; |
125 | struct netlbl_dom_map *iter; | 119 | struct netlbl_dom_map *iter; |
@@ -133,10 +127,31 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) | |||
133 | return iter; | 127 | return iter; |
134 | } | 128 | } |
135 | 129 | ||
136 | if (def != 0) { | 130 | return NULL; |
137 | iter = rcu_dereference(netlbl_domhsh_def); | 131 | } |
138 | if (iter != NULL && iter->valid) | 132 | |
139 | return iter; | 133 | /** |
134 | * netlbl_domhsh_search_def - Search for a domain entry | ||
135 | * @domain: the domain | ||
136 | * @def: return default if no match is found | ||
137 | * | ||
138 | * Description: | ||
139 | * Searches the domain hash table and returns a pointer to the hash table | ||
140 | * entry if an exact match is found, if an exact match is not present in the | ||
141 | * hash table then the default entry is returned if valid otherwise NULL is | ||
142 | * returned. The caller is responsibile for the rcu hash table locks | ||
143 | * (i.e. the caller much call rcu_read_[un]lock()). | ||
144 | * | ||
145 | */ | ||
146 | static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | ||
147 | { | ||
148 | struct netlbl_dom_map *entry; | ||
149 | |||
150 | entry = netlbl_domhsh_search(domain); | ||
151 | if (entry == NULL) { | ||
152 | entry = rcu_dereference(netlbl_domhsh_def); | ||
153 | if (entry != NULL && entry->valid) | ||
154 | return entry; | ||
140 | } | 155 | } |
141 | 156 | ||
142 | return NULL; | 157 | return NULL; |
@@ -221,24 +236,22 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, | |||
221 | INIT_RCU_HEAD(&entry->rcu); | 236 | INIT_RCU_HEAD(&entry->rcu); |
222 | 237 | ||
223 | rcu_read_lock(); | 238 | rcu_read_lock(); |
239 | spin_lock(&netlbl_domhsh_lock); | ||
224 | if (entry->domain != NULL) { | 240 | if (entry->domain != NULL) { |
225 | bkt = netlbl_domhsh_hash(entry->domain); | 241 | bkt = netlbl_domhsh_hash(entry->domain); |
226 | spin_lock(&netlbl_domhsh_lock); | 242 | if (netlbl_domhsh_search(entry->domain) == NULL) |
227 | if (netlbl_domhsh_search(entry->domain, 0) == NULL) | ||
228 | list_add_tail_rcu(&entry->list, | 243 | list_add_tail_rcu(&entry->list, |
229 | &rcu_dereference(netlbl_domhsh)->tbl[bkt]); | 244 | &rcu_dereference(netlbl_domhsh)->tbl[bkt]); |
230 | else | 245 | else |
231 | ret_val = -EEXIST; | 246 | ret_val = -EEXIST; |
232 | spin_unlock(&netlbl_domhsh_lock); | ||
233 | } else { | 247 | } else { |
234 | INIT_LIST_HEAD(&entry->list); | 248 | INIT_LIST_HEAD(&entry->list); |
235 | spin_lock(&netlbl_domhsh_def_lock); | ||
236 | if (rcu_dereference(netlbl_domhsh_def) == NULL) | 249 | if (rcu_dereference(netlbl_domhsh_def) == NULL) |
237 | rcu_assign_pointer(netlbl_domhsh_def, entry); | 250 | rcu_assign_pointer(netlbl_domhsh_def, entry); |
238 | else | 251 | else |
239 | ret_val = -EEXIST; | 252 | ret_val = -EEXIST; |
240 | spin_unlock(&netlbl_domhsh_def_lock); | ||
241 | } | 253 | } |
254 | spin_unlock(&netlbl_domhsh_lock); | ||
242 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); | 255 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); |
243 | if (audit_buf != NULL) { | 256 | if (audit_buf != NULL) { |
244 | audit_log_format(audit_buf, | 257 | audit_log_format(audit_buf, |
@@ -307,7 +320,10 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) | |||
307 | struct audit_buffer *audit_buf; | 320 | struct audit_buffer *audit_buf; |
308 | 321 | ||
309 | rcu_read_lock(); | 322 | rcu_read_lock(); |
310 | entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1)); | 323 | if (domain) |
324 | entry = netlbl_domhsh_search(domain); | ||
325 | else | ||
326 | entry = netlbl_domhsh_search_def(domain); | ||
311 | if (entry == NULL) | 327 | if (entry == NULL) |
312 | goto remove_return; | 328 | goto remove_return; |
313 | switch (entry->type) { | 329 | switch (entry->type) { |
@@ -316,23 +332,16 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info) | |||
316 | entry->domain); | 332 | entry->domain); |
317 | break; | 333 | break; |
318 | } | 334 | } |
319 | if (entry != rcu_dereference(netlbl_domhsh_def)) { | 335 | spin_lock(&netlbl_domhsh_lock); |
320 | spin_lock(&netlbl_domhsh_lock); | 336 | if (entry->valid) { |
321 | if (entry->valid) { | 337 | entry->valid = 0; |
322 | entry->valid = 0; | 338 | if (entry != rcu_dereference(netlbl_domhsh_def)) |
323 | list_del_rcu(&entry->list); | 339 | list_del_rcu(&entry->list); |
324 | ret_val = 0; | 340 | else |
325 | } | ||
326 | spin_unlock(&netlbl_domhsh_lock); | ||
327 | } else { | ||
328 | spin_lock(&netlbl_domhsh_def_lock); | ||
329 | if (entry->valid) { | ||
330 | entry->valid = 0; | ||
331 | rcu_assign_pointer(netlbl_domhsh_def, NULL); | 341 | rcu_assign_pointer(netlbl_domhsh_def, NULL); |
332 | ret_val = 0; | 342 | ret_val = 0; |
333 | } | ||
334 | spin_unlock(&netlbl_domhsh_def_lock); | ||
335 | } | 343 | } |
344 | spin_unlock(&netlbl_domhsh_lock); | ||
336 | 345 | ||
337 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); | 346 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info); |
338 | if (audit_buf != NULL) { | 347 | if (audit_buf != NULL) { |
@@ -377,7 +386,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) | |||
377 | */ | 386 | */ |
378 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) | 387 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) |
379 | { | 388 | { |
380 | return netlbl_domhsh_search(domain, 1); | 389 | return netlbl_domhsh_search_def(domain); |
381 | } | 390 | } |
382 | 391 | ||
383 | /** | 392 | /** |