libnvdimm: Annotate struct nd_region with __counted_by
authorKees Cook <keescook@chromium.org>
Fri, 22 Sep 2023 17:52:39 +0000 (10:52 -0700)
committerIra Weiny <ira.weiny@intel.com>
Wed, 27 Sep 2023 17:33:47 +0000 (10:33 -0700)
Prepare for the coming implementation by GCC and Clang of the __counted_by
attribute. Flexible array members annotated with __counted_by can have
their accesses bounds-checked at run-time checking via CONFIG_UBSAN_BOUNDS
(for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family
functions).

As found with Coccinelle[1], add __counted_by for struct nd_region.
Additionally, since the element count member must be set before accessing
the annotated flexible array member, move its initialization earlier.

[1] https://github.com/kees/kernel-tools/blob/trunk/coccinelle/examples/counted_by.cocci

Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: nvdimm@lists.linux.dev
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
drivers/nvdimm/nd.h
drivers/nvdimm/region_devs.c

index e8b9d27dbb3c3457927f2977f8d8e6aebcb4573b..ae2078eb6a6265eaf80a0d5ede8fcb03c8e054e6 100644 (file)
@@ -422,7 +422,7 @@ struct nd_region {
        struct nd_interleave_set *nd_set;
        struct nd_percpu_lane __percpu *lane;
        int (*flush)(struct nd_region *nd_region, struct bio *bio);
-       struct nd_mapping mapping[];
+       struct nd_mapping mapping[] __counted_by(ndr_mappings);
 };
 
 static inline bool nsl_validate_nlabel(struct nd_region *nd_region,
index e2f1fb99707fc48f83f394f1b94988e38bcfcd93..9e4f7ff024a00048fbe30d4e2080f41d3dc22567 100644 (file)
@@ -1028,6 +1028,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
 
        if (!nd_region)
                return NULL;
+       nd_region->ndr_mappings = ndr_desc->num_mappings;
        /* CXL pre-assigns memregion ids before creating nvdimm regions */
        if (test_bit(ND_REGION_CXL, &ndr_desc->flags)) {
                nd_region->id = ndr_desc->memregion;
@@ -1062,7 +1063,6 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
 
                get_device(&nvdimm->dev);
        }
-       nd_region->ndr_mappings = ndr_desc->num_mappings;
        nd_region->provider_data = ndr_desc->provider_data;
        nd_region->nd_set = ndr_desc->nd_set;
        nd_region->num_lanes = ndr_desc->num_lanes;