overflow: Change DEFINE_FLEX to take __counted_by member
authorKees Cook <keescook@chromium.org>
Wed, 6 Mar 2024 23:51:36 +0000 (15:51 -0800)
committerKees Cook <keescook@chromium.org>
Fri, 22 Mar 2024 23:25:31 +0000 (16:25 -0700)
The norm should be flexible array structures with __counted_by
annotations, so DEFINE_FLEX() is updated to expect that. Rename
the non-annotated version to DEFINE_RAW_FLEX(), and update the
few existing users. Additionally add selftests for the macros.

Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://lore.kernel.org/r/20240306235128.it.933-kees@kernel.org
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
drivers/net/ethernet/intel/ice/ice_base.c
drivers/net/ethernet/intel/ice/ice_common.c
drivers/net/ethernet/intel/ice/ice_ddp.c
drivers/net/ethernet/intel/ice/ice_lag.c
drivers/net/ethernet/intel/ice/ice_sched.c
drivers/net/ethernet/intel/ice/ice_switch.c
include/linux/overflow.h
lib/overflow_kunit.c

index d2fd315556a39dc7da84abdf69b68e918ef16191..a545a7917e4fc1098f504a88e6f76a0929fb3027 100644 (file)
@@ -956,7 +956,7 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
 int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings,
                           u16 q_idx)
 {
-       DEFINE_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
 
        if (q_idx >= vsi->alloc_txq || !tx_rings || !tx_rings[q_idx])
                return -EINVAL;
@@ -978,7 +978,7 @@ int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings,
 static int
 ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_tx_ring **rings, u16 count)
 {
-       DEFINE_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
        int err = 0;
        u16 q_idx;
 
index 4d8111aeb0ff0ccf101ee1560b70ee2a9d064194..db4b2844e1f71820494ffe30cb67d87e8af91edc 100644 (file)
@@ -4695,7 +4695,7 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
                enum ice_disq_rst_src rst_src, u16 vmvf_num,
                struct ice_sq_cd *cd)
 {
-       DEFINE_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
        u16 i, buf_size = __struct_size(qg_list);
        struct ice_q_ctx *q_ctx;
        int status = -ENOENT;
@@ -4917,7 +4917,7 @@ int
 ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
                      u16 *q_id)
 {
-       DEFINE_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
        u16 qg_size = __struct_size(qg_list);
        struct ice_hw *hw;
        int status = 0;
index 7532d11ad7f337db473eb9e3a9edeee1d8f7e85b..fc91c4d411863ecd8bc446006e065694b26c4225 100644 (file)
@@ -1938,8 +1938,8 @@ static enum ice_ddp_state ice_init_pkg_info(struct ice_hw *hw,
  */
 static enum ice_ddp_state ice_get_pkg_info(struct ice_hw *hw)
 {
-       DEFINE_FLEX(struct ice_aqc_get_pkg_info_resp, pkg_info, pkg_info,
-                   ICE_PKG_CNT);
+       DEFINE_RAW_FLEX(struct ice_aqc_get_pkg_info_resp, pkg_info, pkg_info,
+                       ICE_PKG_CNT);
        u16 size = __struct_size(pkg_info);
        u32 i;
 
@@ -1990,8 +1990,8 @@ static enum ice_ddp_state ice_chk_pkg_compat(struct ice_hw *hw,
                                             struct ice_pkg_hdr *ospkg,
                                             struct ice_seg **seg)
 {
-       DEFINE_FLEX(struct ice_aqc_get_pkg_info_resp, pkg, pkg_info,
-                   ICE_PKG_CNT);
+       DEFINE_RAW_FLEX(struct ice_aqc_get_pkg_info_resp, pkg, pkg_info,
+                       ICE_PKG_CNT);
        u16 size = __struct_size(pkg);
        enum ice_ddp_state state;
        u32 i;
index 467372d541d21f9c26416275f945b12e684079ef..f97128b69f87ecb26d17d81a44486eab3d194470 100644 (file)
@@ -491,7 +491,7 @@ static void
 ice_lag_move_vf_node_tc(struct ice_lag *lag, u8 oldport, u8 newport,
                        u16 vsi_num, u8 tc)
 {
-       DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
        struct device *dev = ice_pf_to_dev(lag->pf);
        u16 numq, valq, num_moved, qbuf_size;
        u16 buf_size = __struct_size(buf);
@@ -849,7 +849,7 @@ static void
 ice_lag_reclaim_vf_tc(struct ice_lag *lag, struct ice_hw *src_hw, u16 vsi_num,
                      u8 tc)
 {
-       DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
        struct device *dev = ice_pf_to_dev(lag->pf);
        u16 numq, valq, num_moved, qbuf_size;
        u16 buf_size = __struct_size(buf);
@@ -1873,7 +1873,7 @@ static void
 ice_lag_move_vf_nodes_tc_sync(struct ice_lag *lag, struct ice_hw *dest_hw,
                              u16 vsi_num, u8 tc)
 {
-       DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
        struct device *dev = ice_pf_to_dev(lag->pf);
        u16 numq, valq, num_moved, qbuf_size;
        u16 buf_size = __struct_size(buf);
index d174a4eeb899ccdf45ea1f6c2bafdbd6193c1dea..a1525992d14bc791c1753fe6b60725a78009afca 100644 (file)
@@ -237,7 +237,7 @@ static int
 ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
                       u32 node_teid)
 {
-       DEFINE_FLEX(struct ice_aqc_delete_elem, buf, teid, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_delete_elem, buf, teid, 1);
        u16 buf_size = __struct_size(buf);
        u16 num_groups_removed = 0;
        int status;
@@ -2219,7 +2219,7 @@ int
 ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,
                     u16 num_items, u32 *list)
 {
-       DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
        u16 buf_len = __struct_size(buf);
        struct ice_sched_node *node;
        u16 i, grps_movd = 0;
index f84bab80ca42376482e2ea504aa90e3ebf6a8f98..d4baae8c3b720ae7fca91b87a43400b858c046b6 100644 (file)
@@ -1812,7 +1812,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
                           enum ice_sw_lkup_type lkup_type,
                           enum ice_adminq_opc opc)
 {
-       DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
        u16 buf_len = __struct_size(sw_buf);
        struct ice_aqc_res_elem *vsi_ele;
        int status;
@@ -2081,7 +2081,7 @@ ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
  */
 int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
 {
-       DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
        u16 buf_len = __struct_size(sw_buf);
        int status;
 
@@ -4418,7 +4418,7 @@ int
 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
                   u16 *counter_id)
 {
-       DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
        u16 buf_len = __struct_size(buf);
        int status;
 
@@ -4446,7 +4446,7 @@ int
 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
                  u16 counter_id)
 {
-       DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
        u16 buf_len = __struct_size(buf);
        int status;
 
@@ -4476,7 +4476,7 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
  */
 int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id)
 {
-       DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
+       DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
        u16 buf_len = __struct_size(buf);
        u16 res_type;
        int status;
index aa691f2119b0bbc8c3be7739c857f2f89775d784..0c7e3dcfe8670cb95f371a6f7d41bb8b63b1786c 100644 (file)
@@ -398,7 +398,7 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
  * @count: Number of elements in the array; must be compile-time const.
  * @initializer: initializer expression (could be empty for no init).
  */
-#define _DEFINE_FLEX(type, name, member, count, initializer)                   \
+#define _DEFINE_FLEX(type, name, member, count, initializer...)                        \
        _Static_assert(__builtin_constant_p(count),                             \
                       "onstack flex array members require compile-time const count"); \
        union {                                                                 \
@@ -408,8 +408,8 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
        type *name = (type *)&name##_u
 
 /**
- * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
- * flexible array member.
+ * DEFINE_RAW_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member, when it does not have a __counted_by annotation.
  *
  * @type: structure type name, including "struct" keyword.
  * @name: Name for a variable to define.
@@ -420,7 +420,24 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
  * flexible array member.
  * Use __struct_size(@name) to get compile-time size of it afterwards.
  */
-#define DEFINE_FLEX(type, name, member, count)                 \
+#define DEFINE_RAW_FLEX(type, name, member, count)     \
        _DEFINE_FLEX(type, name, member, count, = {})
 
+/**
+ * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member.
+ *
+ * @TYPE: structure type name, including "struct" keyword.
+ * @NAME: Name for a variable to define.
+ * @MEMBER: Name of the array member.
+ * @COUNTER: Name of the __counted_by member.
+ * @COUNT: Number of elements in the array; must be compile-time const.
+ *
+ * Define a zeroed, on-stack, instance of @TYPE structure with a trailing
+ * flexible array member.
+ * Use __struct_size(@NAME) to get compile-time size of it afterwards.
+ */
+#define DEFINE_FLEX(TYPE, NAME, MEMBER, COUNTER, COUNT)        \
+       _DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .obj.COUNTER = COUNT, })
+
 #endif /* __LINUX_OVERFLOW_H */
index 65e8a72a83bfaa9ccfd2c47b0290eedfa46520d3..4ef31b0bb74d682dbe83997609b2b259ddd600ae 100644 (file)
@@ -1172,6 +1172,24 @@ static void castable_to_type_test(struct kunit *test)
 #undef TEST_CASTABLE_TO_TYPE
 }
 
+struct foo {
+       int a;
+       u32 counter;
+       s16 array[] __counted_by(counter);
+};
+
+static void DEFINE_FLEX_test(struct kunit *test)
+{
+       DEFINE_RAW_FLEX(struct foo, two, array, 2);
+       DEFINE_FLEX(struct foo, eight, array, counter, 8);
+       DEFINE_FLEX(struct foo, empty, array, counter, 0);
+
+       KUNIT_EXPECT_EQ(test, __struct_size(two),
+                       sizeof(struct foo) + sizeof(s16) + sizeof(s16));
+       KUNIT_EXPECT_EQ(test, __struct_size(eight), 24);
+       KUNIT_EXPECT_EQ(test, __struct_size(empty), sizeof(struct foo));
+}
+
 static struct kunit_case overflow_test_cases[] = {
        KUNIT_CASE(u8_u8__u8_overflow_test),
        KUNIT_CASE(s8_s8__s8_overflow_test),
@@ -1194,6 +1212,7 @@ static struct kunit_case overflow_test_cases[] = {
        KUNIT_CASE(overflows_type_test),
        KUNIT_CASE(same_type_test),
        KUNIT_CASE(castable_to_type_test),
+       KUNIT_CASE(DEFINE_FLEX_test),
        {}
 };