Kernel commit 1bbdb81a9836 ("devlink: Fix excessive stack usage in rate TC bandwidth parsing") introduced a dedicated attribute set (DEVLINK_RATE_TC_ATTR_*) for entries nested under DEVLINK_ATTR_RATE_TC_BWS. Update the parser to reflect this change by validating the nested attributes and sync the UAPI header to include the changes. Fixes: c83d1477f8b2 ("Add support for 'tc-bw' attribute in devlink-rate") Signed-off-by: Carolina Jubran --- devlink/devlink.c | 39 ++++++++++++++++++++++++++++-------- include/uapi/linux/devlink.h | 11 ++++++++-- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index fe0c3640..171b8532 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -2773,8 +2773,8 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) nla_tc_bw_entry = mnl_attr_nest_start(nlh, DEVLINK_ATTR_RATE_TC_BWS); - mnl_attr_put_u8(nlh, DEVLINK_ATTR_RATE_TC_INDEX, i); - mnl_attr_put_u32(nlh, DEVLINK_ATTR_RATE_TC_BW, + mnl_attr_put_u8(nlh, DEVLINK_RATE_TC_ATTR_INDEX, i); + mnl_attr_put_u32(nlh, DEVLINK_RATE_TC_ATTR_BW, opts->rate_tc_bw[i]); mnl_attr_nest_end(nlh, nla_tc_bw_entry); } @@ -5467,20 +5467,43 @@ static char *port_rate_type_name(uint16_t type) } } +static const enum mnl_attr_data_type +rate_tc_bws_policy[DEVLINK_RATE_TC_ATTR_BW + 1] = { + [DEVLINK_RATE_TC_ATTR_INDEX] = MNL_TYPE_U8, + [DEVLINK_RATE_TC_ATTR_BW] = MNL_TYPE_U32, +}; + +static int rate_tc_bw_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type; + + if (mnl_attr_type_valid(attr, DEVLINK_RATE_TC_ATTR_MAX) < 0) + return MNL_CB_OK; + + type = mnl_attr_get_type(attr); + + if (mnl_attr_validate(attr, rate_tc_bws_policy[type]) < 0) + return MNL_CB_ERROR; + + tb[type] = attr; + return MNL_CB_OK; +} + static int parse_rate_tc_bw(struct nlattr *nla_tc_bw, uint8_t *tc_index, uint32_t *tc_bw) { - struct nlattr *tb_tc_bw[DEVLINK_ATTR_MAX + 1] = {}; + struct nlattr *tb_tc_bw[DEVLINK_RATE_TC_ATTR_MAX + 1] = {}; - if (mnl_attr_parse_nested(nla_tc_bw, attr_cb, tb_tc_bw) != MNL_CB_OK) + if (mnl_attr_parse_nested(nla_tc_bw, rate_tc_bw_attr_cb, tb_tc_bw) != MNL_CB_OK) return MNL_CB_ERROR; - if (!tb_tc_bw[DEVLINK_ATTR_RATE_TC_INDEX] || - !tb_tc_bw[DEVLINK_ATTR_RATE_TC_BW]) + if (!tb_tc_bw[DEVLINK_RATE_TC_ATTR_INDEX] || + !tb_tc_bw[DEVLINK_RATE_TC_ATTR_BW]) return MNL_CB_ERROR; - *tc_index = mnl_attr_get_u8(tb_tc_bw[DEVLINK_ATTR_RATE_TC_INDEX]); - *tc_bw = mnl_attr_get_u32(tb_tc_bw[DEVLINK_ATTR_RATE_TC_BW]); + *tc_index = mnl_attr_get_u8(tb_tc_bw[DEVLINK_RATE_TC_ATTR_INDEX]); + *tc_bw = mnl_attr_get_u32(tb_tc_bw[DEVLINK_RATE_TC_ATTR_BW]); return MNL_CB_OK; } diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 78f505c1..a89df2a7 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -635,8 +635,6 @@ enum devlink_attr { DEVLINK_ATTR_REGION_DIRECT, /* flag */ DEVLINK_ATTR_RATE_TC_BWS, /* nested */ - DEVLINK_ATTR_RATE_TC_INDEX, /* u8 */ - DEVLINK_ATTR_RATE_TC_BW, /* u32 */ /* Add new attributes above here, update the spec in * Documentation/netlink/specs/devlink.yaml and re-generate @@ -647,6 +645,15 @@ enum devlink_attr { DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1 }; +enum devlink_rate_tc_attr { + DEVLINK_RATE_TC_ATTR_UNSPEC, + DEVLINK_RATE_TC_ATTR_INDEX, /* u8 */ + DEVLINK_RATE_TC_ATTR_BW, /* u32 */ + + __DEVLINK_RATE_TC_ATTR_MAX, + DEVLINK_RATE_TC_ATTR_MAX = __DEVLINK_RATE_TC_ATTR_MAX - 1 +}; + /* Mapping between internal resource described by the field and system * structure */ -- 2.38.1