aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
authorpaul.moore@hp.com <paul.moore@hp.com>2006-10-04 11:46:31 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-10-12 02:59:29 -0400
commitffb733c65000ee701294f7b80c4eca2a5f335637 (patch)
treeedda8e25792fe4a7bf0c619787949291276b9ed7 /net/ipv4/cipso_ipv4.c
parentc25d5180441e344a3368d100c57f0a481c6944f7 (diff)
NetLabel: fix a cache race condition
Testing revealed a problem with the NetLabel cache where a cached entry could be freed while in use by the LSM layer causing an oops and other problems. This patch fixes that problem by introducing a reference counter to the cache entry so that it is only freed when it is no longer in use. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index a8e2e879a647..bde8ccaa1531 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -43,6 +43,7 @@
43#include <net/tcp.h> 43#include <net/tcp.h>
44#include <net/netlabel.h> 44#include <net/netlabel.h>
45#include <net/cipso_ipv4.h> 45#include <net/cipso_ipv4.h>
46#include <asm/atomic.h>
46#include <asm/bug.h> 47#include <asm/bug.h>
47 48
48struct cipso_v4_domhsh_entry { 49struct cipso_v4_domhsh_entry {
@@ -79,7 +80,7 @@ struct cipso_v4_map_cache_entry {
79 unsigned char *key; 80 unsigned char *key;
80 size_t key_len; 81 size_t key_len;
81 82
82 struct netlbl_lsm_cache lsm_data; 83 struct netlbl_lsm_cache *lsm_data;
83 84
84 u32 activity; 85 u32 activity;
85 struct list_head list; 86 struct list_head list;
@@ -188,13 +189,14 @@ static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
188 * @entry: the entry to free 189 * @entry: the entry to free
189 * 190 *
190 * Description: 191 * Description:
191 * This function frees the memory associated with a cache entry. 192 * This function frees the memory associated with a cache entry including the
193 * LSM cache data if there are no longer any users, i.e. reference count == 0.
192 * 194 *
193 */ 195 */
194static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) 196static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
195{ 197{
196 if (entry->lsm_data.free) 198 if (entry->lsm_data)
197 entry->lsm_data.free(entry->lsm_data.data); 199 netlbl_secattr_cache_free(entry->lsm_data);
198 kfree(entry->key); 200 kfree(entry->key);
199 kfree(entry); 201 kfree(entry);
200} 202}
@@ -315,8 +317,8 @@ static int cipso_v4_cache_check(const unsigned char *key,
315 entry->key_len == key_len && 317 entry->key_len == key_len &&
316 memcmp(entry->key, key, key_len) == 0) { 318 memcmp(entry->key, key, key_len) == 0) {
317 entry->activity += 1; 319 entry->activity += 1;
318 secattr->cache.free = entry->lsm_data.free; 320 atomic_inc(&entry->lsm_data->refcount);
319 secattr->cache.data = entry->lsm_data.data; 321 secattr->cache = entry->lsm_data;
320 if (prev_entry == NULL) { 322 if (prev_entry == NULL) {
321 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 323 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
322 return 0; 324 return 0;
@@ -383,8 +385,8 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
383 memcpy(entry->key, cipso_ptr, cipso_ptr_len); 385 memcpy(entry->key, cipso_ptr, cipso_ptr_len);
384 entry->key_len = cipso_ptr_len; 386 entry->key_len = cipso_ptr_len;
385 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); 387 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
386 entry->lsm_data.free = secattr->cache.free; 388 atomic_inc(&secattr->cache->refcount);
387 entry->lsm_data.data = secattr->cache.data; 389 entry->lsm_data = secattr->cache;
388 390
389 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); 391 bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
390 spin_lock_bh(&cipso_v4_cache[bkt].lock); 392 spin_lock_bh(&cipso_v4_cache[bkt].lock);