aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netlabel/netlabel_domainhash.c28
-rw-r--r--net/netlabel/netlabel_unlabeled.c66
2 files changed, 37 insertions, 57 deletions
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index 0bfeaab88ef5..06ab41b6b57a 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -50,9 +50,12 @@ struct netlbl_domhsh_tbl {
50}; 50};
51 51
52/* Domain hash table */ 52/* Domain hash table */
53/* XXX - updates should be so rare that having one spinlock for the entire 53/* updates should be so rare that having one spinlock for the entire hash table
54 * hash table should be okay */ 54 * should be okay */
55static DEFINE_SPINLOCK(netlbl_domhsh_lock); 55static DEFINE_SPINLOCK(netlbl_domhsh_lock);
56#define netlbl_domhsh_rcu_deref(p) \
57 rcu_dereference_check(p, rcu_read_lock_held() || \
58 lockdep_is_held(&netlbl_domhsh_lock))
56static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; 59static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
57static struct netlbl_dom_map *netlbl_domhsh_def = NULL; 60static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
58 61
@@ -106,7 +109,8 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry)
106 * Description: 109 * Description:
107 * This is the hashing function for the domain hash table, it returns the 110 * This is the hashing function for the domain hash table, it returns the
108 * correct bucket number for the domain. The caller is responsibile for 111 * correct bucket number for the domain. The caller is responsibile for
109 * calling the rcu_read_[un]lock() functions. 112 * ensuring that the hash table is protected with either a RCU read lock or the
113 * hash table lock.
110 * 114 *
111 */ 115 */
112static u32 netlbl_domhsh_hash(const char *key) 116static u32 netlbl_domhsh_hash(const char *key)
@@ -120,7 +124,7 @@ static u32 netlbl_domhsh_hash(const char *key)
120 124
121 for (iter = 0, val = 0, len = strlen(key); iter < len; iter++) 125 for (iter = 0, val = 0, len = strlen(key); iter < len; iter++)
122 val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; 126 val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter];
123 return val & (rcu_dereference(netlbl_domhsh)->size - 1); 127 return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1);
124} 128}
125 129
126/** 130/**
@@ -130,7 +134,8 @@ static u32 netlbl_domhsh_hash(const char *key)
130 * Description: 134 * Description:
131 * Searches the domain hash table and returns a pointer to the hash table 135 * Searches the domain hash table and returns a pointer to the hash table
132 * entry if found, otherwise NULL is returned. The caller is responsibile for 136 * entry if found, otherwise NULL is returned. The caller is responsibile for
133 * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). 137 * ensuring that the hash table is protected with either a RCU read lock or the
138 * hash table lock.
134 * 139 *
135 */ 140 */
136static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) 141static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)
@@ -141,7 +146,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)
141 146
142 if (domain != NULL) { 147 if (domain != NULL) {
143 bkt = netlbl_domhsh_hash(domain); 148 bkt = netlbl_domhsh_hash(domain);
144 bkt_list = &rcu_dereference(netlbl_domhsh)->tbl[bkt]; 149 bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt];
145 list_for_each_entry_rcu(iter, bkt_list, list) 150 list_for_each_entry_rcu(iter, bkt_list, list)
146 if (iter->valid && strcmp(iter->domain, domain) == 0) 151 if (iter->valid && strcmp(iter->domain, domain) == 0)
147 return iter; 152 return iter;
@@ -159,8 +164,8 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)
159 * Searches the domain hash table and returns a pointer to the hash table 164 * Searches the domain hash table and returns a pointer to the hash table
160 * entry if an exact match is found, if an exact match is not present in the 165 * entry if an exact match is found, if an exact match is not present in the
161 * hash table then the default entry is returned if valid otherwise NULL is 166 * hash table then the default entry is returned if valid otherwise NULL is
162 * returned. The caller is responsibile for the rcu hash table locks 167 * returned. The caller is responsibile ensuring that the hash table is
163 * (i.e. the caller much call rcu_read_[un]lock()). 168 * protected with either a RCU read lock or the hash table lock.
164 * 169 *
165 */ 170 */
166static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) 171static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
@@ -169,7 +174,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
169 174
170 entry = netlbl_domhsh_search(domain); 175 entry = netlbl_domhsh_search(domain);
171 if (entry == NULL) { 176 if (entry == NULL) {
172 entry = rcu_dereference(netlbl_domhsh_def); 177 entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def);
173 if (entry != NULL && !entry->valid) 178 if (entry != NULL && !entry->valid)
174 entry = NULL; 179 entry = NULL;
175 } 180 }
@@ -306,8 +311,11 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
306 struct netlbl_af6list *tmp6; 311 struct netlbl_af6list *tmp6;
307#endif /* IPv6 */ 312#endif /* IPv6 */
308 313
314 /* XXX - we can remove this RCU read lock as the spinlock protects the
315 * entire function, but before we do we need to fixup the
316 * netlbl_af[4,6]list RCU functions to do "the right thing" with
317 * respect to rcu_dereference() when only a spinlock is held. */
309 rcu_read_lock(); 318 rcu_read_lock();
310
311 spin_lock(&netlbl_domhsh_lock); 319 spin_lock(&netlbl_domhsh_lock);
312 if (entry->domain != NULL) 320 if (entry->domain != NULL)
313 entry_old = netlbl_domhsh_search(entry->domain); 321 entry_old = netlbl_domhsh_search(entry->domain);
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 852d9d7976b9..3b4fde7622a3 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -114,6 +114,9 @@ struct netlbl_unlhsh_walk_arg {
114/* updates should be so rare that having one spinlock for the entire 114/* updates should be so rare that having one spinlock for the entire
115 * hash table should be okay */ 115 * hash table should be okay */
116static DEFINE_SPINLOCK(netlbl_unlhsh_lock); 116static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
117#define netlbl_unlhsh_rcu_deref(p) \
118 rcu_dereference_check(p, rcu_read_lock_held() || \
119 lockdep_is_held(&netlbl_unlhsh_lock))
117static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL; 120static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
118static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; 121static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
119 122
@@ -235,15 +238,13 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
235 * Description: 238 * Description:
236 * This is the hashing function for the unlabeled hash table, it returns the 239 * This is the hashing function for the unlabeled hash table, it returns the
237 * bucket number for the given device/interface. The caller is responsible for 240 * bucket number for the given device/interface. The caller is responsible for
238 * calling the rcu_read_[un]lock() functions. 241 * ensuring that the hash table is protected with either a RCU read lock or
242 * the hash table lock.
239 * 243 *
240 */ 244 */
241static u32 netlbl_unlhsh_hash(int ifindex) 245static u32 netlbl_unlhsh_hash(int ifindex)
242{ 246{
243 /* this is taken _almost_ directly from 247 return ifindex & (netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->size - 1);
244 * security/selinux/netif.c:sel_netif_hasfn() as they do pretty much
245 * the same thing */
246 return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1);
247} 248}
248 249
249/** 250/**
@@ -253,7 +254,8 @@ static u32 netlbl_unlhsh_hash(int ifindex)
253 * Description: 254 * Description:
254 * Searches the unlabeled connection hash table and returns a pointer to the 255 * Searches the unlabeled connection hash table and returns a pointer to the
255 * interface entry which matches @ifindex, otherwise NULL is returned. The 256 * interface entry which matches @ifindex, otherwise NULL is returned. The
256 * caller is responsible for calling the rcu_read_[un]lock() functions. 257 * caller is responsible for ensuring that the hash table is protected with
258 * either a RCU read lock or the hash table lock.
257 * 259 *
258 */ 260 */
259static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) 261static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
@@ -263,7 +265,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
263 struct netlbl_unlhsh_iface *iter; 265 struct netlbl_unlhsh_iface *iter;
264 266
265 bkt = netlbl_unlhsh_hash(ifindex); 267 bkt = netlbl_unlhsh_hash(ifindex);
266 bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; 268 bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
267 list_for_each_entry_rcu(iter, bkt_list, list) 269 list_for_each_entry_rcu(iter, bkt_list, list)
268 if (iter->valid && iter->ifindex == ifindex) 270 if (iter->valid && iter->ifindex == ifindex)
269 return iter; 271 return iter;
@@ -272,33 +274,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
272} 274}
273 275
274/** 276/**
275 * netlbl_unlhsh_search_iface_def - Search for a matching interface entry
276 * @ifindex: the network interface
277 *
278 * Description:
279 * Searches the unlabeled connection hash table and returns a pointer to the
280 * interface entry which matches @ifindex. If an exact match can not be found
281 * and there is a valid default entry, the default entry is returned, otherwise
282 * NULL is returned. The caller is responsible for calling the
283 * rcu_read_[un]lock() functions.
284 *
285 */
286static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
287{
288 struct netlbl_unlhsh_iface *entry;
289
290 entry = netlbl_unlhsh_search_iface(ifindex);
291 if (entry != NULL)
292 return entry;
293
294 entry = rcu_dereference(netlbl_unlhsh_def);
295 if (entry != NULL && entry->valid)
296 return entry;
297
298 return NULL;
299}
300
301/**
302 * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table 277 * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table
303 * @iface: the associated interface entry 278 * @iface: the associated interface entry
304 * @addr: IPv4 address in network byte order 279 * @addr: IPv4 address in network byte order
@@ -308,8 +283,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
308 * Description: 283 * Description:
309 * Add a new address entry into the unlabeled connection hash table using the 284 * Add a new address entry into the unlabeled connection hash table using the
310 * interface entry specified by @iface. On success zero is returned, otherwise 285 * interface entry specified by @iface. On success zero is returned, otherwise
311 * a negative value is returned. The caller is responsible for calling the 286 * a negative value is returned.
312 * rcu_read_[un]lock() functions.
313 * 287 *
314 */ 288 */
315static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, 289static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
@@ -349,8 +323,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
349 * Description: 323 * Description:
350 * Add a new address entry into the unlabeled connection hash table using the 324 * Add a new address entry into the unlabeled connection hash table using the
351 * interface entry specified by @iface. On success zero is returned, otherwise 325 * interface entry specified by @iface. On success zero is returned, otherwise
352 * a negative value is returned. The caller is responsible for calling the 326 * a negative value is returned.
353 * rcu_read_[un]lock() functions.
354 * 327 *
355 */ 328 */
356static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, 329static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
@@ -391,8 +364,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
391 * Description: 364 * Description:
392 * Add a new, empty, interface entry into the unlabeled connection hash table. 365 * Add a new, empty, interface entry into the unlabeled connection hash table.
393 * On success a pointer to the new interface entry is returned, on failure NULL 366 * On success a pointer to the new interface entry is returned, on failure NULL
394 * is returned. The caller is responsible for calling the rcu_read_[un]lock() 367 * is returned.
395 * functions.
396 * 368 *
397 */ 369 */
398static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) 370static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
@@ -415,10 +387,10 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
415 if (netlbl_unlhsh_search_iface(ifindex) != NULL) 387 if (netlbl_unlhsh_search_iface(ifindex) != NULL)
416 goto add_iface_failure; 388 goto add_iface_failure;
417 list_add_tail_rcu(&iface->list, 389 list_add_tail_rcu(&iface->list,
418 &rcu_dereference(netlbl_unlhsh)->tbl[bkt]); 390 &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]);
419 } else { 391 } else {
420 INIT_LIST_HEAD(&iface->list); 392 INIT_LIST_HEAD(&iface->list);
421 if (rcu_dereference(netlbl_unlhsh_def) != NULL) 393 if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL)
422 goto add_iface_failure; 394 goto add_iface_failure;
423 rcu_assign_pointer(netlbl_unlhsh_def, iface); 395 rcu_assign_pointer(netlbl_unlhsh_def, iface);
424 } 396 }
@@ -548,8 +520,7 @@ unlhsh_add_return:
548 * 520 *
549 * Description: 521 * Description:
550 * Remove an IP address entry from the unlabeled connection hash table. 522 * Remove an IP address entry from the unlabeled connection hash table.
551 * Returns zero on success, negative values on failure. The caller is 523 * Returns zero on success, negative values on failure.
552 * responsible for calling the rcu_read_[un]lock() functions.
553 * 524 *
554 */ 525 */
555static int netlbl_unlhsh_remove_addr4(struct net *net, 526static int netlbl_unlhsh_remove_addr4(struct net *net,
@@ -611,8 +582,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
611 * 582 *
612 * Description: 583 * Description:
613 * Remove an IP address entry from the unlabeled connection hash table. 584 * Remove an IP address entry from the unlabeled connection hash table.
614 * Returns zero on success, negative values on failure. The caller is 585 * Returns zero on success, negative values on failure.
615 * responsible for calling the rcu_read_[un]lock() functions.
616 * 586 *
617 */ 587 */
618static int netlbl_unlhsh_remove_addr6(struct net *net, 588static int netlbl_unlhsh_remove_addr6(struct net *net,
@@ -1547,8 +1517,10 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
1547 struct netlbl_unlhsh_iface *iface; 1517 struct netlbl_unlhsh_iface *iface;
1548 1518
1549 rcu_read_lock(); 1519 rcu_read_lock();
1550 iface = netlbl_unlhsh_search_iface_def(skb->skb_iif); 1520 iface = netlbl_unlhsh_search_iface(skb->skb_iif);
1551 if (iface == NULL) 1521 if (iface == NULL)
1522 iface = rcu_dereference(netlbl_unlhsh_def);
1523 if (iface == NULL || !iface->valid)
1552 goto unlabel_getattr_nolabel; 1524 goto unlabel_getattr_nolabel;
1553 switch (family) { 1525 switch (family) {
1554 case PF_INET: { 1526 case PF_INET: {