net: fix out-of-bounds access in ops_init
[linux-2.6-block.git] / net / core / net_namespace.c
index f0540c5575157135b1dc5dece2220f81a408fb7e..9d690d32da33a1d9fa5b26234ce063f395093fe3 100644 (file)
@@ -69,12 +69,15 @@ DEFINE_COOKIE(net_cookie);
 
 static struct net_generic *net_alloc_generic(void)
 {
+       unsigned int gen_ptrs = READ_ONCE(max_gen_ptrs);
+       unsigned int generic_size;
        struct net_generic *ng;
-       unsigned int generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
+
+       generic_size = offsetof(struct net_generic, ptr[gen_ptrs]);
 
        ng = kzalloc(generic_size, GFP_KERNEL);
        if (ng)
-               ng->s.len = max_gen_ptrs;
+               ng->s.len = gen_ptrs;
 
        return ng;
 }
@@ -1307,7 +1310,11 @@ static int register_pernet_operations(struct list_head *list,
                if (error < 0)
                        return error;
                *ops->id = error;
-               max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1);
+               /* This does not require READ_ONCE as writers already hold
+                * pernet_ops_rwsem. But WRITE_ONCE is needed to protect
+                * net_alloc_generic.
+                */
+               WRITE_ONCE(max_gen_ptrs, max(max_gen_ptrs, *ops->id + 1));
        }
        error = __register_pernet_operations(list, ops);
        if (error) {