[PATCH v1 net 13/16] cipso: Fix a data-race around cipso_v4_cache_bucketsize.

From: Kuniyuki Iwashima
Date: Wed Jul 06 2022 - 01:25:12 EST


While reading cipso_v4_cache_bucketsize, it can be changed concurrently.
So, we need to add READ_ONCE(). Then we can set proc_dointvec_lockless()
as the handler to mark it safe.

Fixes: 446fda4f2682 ("[NetLabel]: CIPSOv4 engine")
Signed-off-by: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx>
---
CC: Paul Moore <paul.moore@xxxxxx>
---
Documentation/networking/ip-sysctl.rst | 2 +-
net/ipv4/cipso_ipv4.c | 12 ++++++------
net/ipv4/sysctl_net_ipv4.c | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 9f41961d11d5..0e58001f8580 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -1085,7 +1085,7 @@ cipso_cache_enable - BOOLEAN
cipso_cache_bucket_size - INTEGER
The CIPSO label cache consists of a fixed size hash table with each
hash bucket containing a number of cache entries. This variable limits
- the number of entries in each hash bucket; the larger the value the
+ the number of entries in each hash bucket; the larger the value is, the
more CIPSO label mappings that can be cached. When the number of
entries in a given hash bucket reaches this limit adding new entries
causes the oldest entry in the bucket to be removed to make room.
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 62d5f99760aa..0600e9b06e1a 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -296,13 +296,13 @@ static int cipso_v4_cache_check(const unsigned char *key,
int cipso_v4_cache_add(const unsigned char *cipso_ptr,
const struct netlbl_lsm_secattr *secattr)
{
- int ret_val = -EPERM;
- u32 bkt;
- struct cipso_v4_map_cache_entry *entry = NULL;
+ int bkt_size = READ_ONCE(cipso_v4_cache_bucketsize);
struct cipso_v4_map_cache_entry *old_entry = NULL;
- u32 cipso_ptr_len;
+ struct cipso_v4_map_cache_entry *entry = NULL;
+ u32 bkt, cipso_ptr_len;
+ int ret_val = -EPERM;

- if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
+ if (!cipso_v4_cache_enabled || bkt_size <= 0)
return 0;

cipso_ptr_len = cipso_ptr[1];
@@ -322,7 +322,7 @@ int cipso_v4_cache_add(const unsigned char *cipso_ptr,

bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETS - 1);
spin_lock_bh(&cipso_v4_cache[bkt].lock);
- if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
+ if (cipso_v4_cache[bkt].size < bkt_size) {
list_add(&entry->list, &cipso_v4_cache[bkt].list);
cipso_v4_cache[bkt].size += 1;
} else {
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 0287d55f9230..5cd32b33bbac 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -527,7 +527,7 @@ static struct ctl_table ipv4_table[] = {
.data = &cipso_v4_cache_bucketsize,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_lockless,
},
{
.procname = "cipso_rbm_optfmt",
--
2.30.2