diff --git a/SOURCES/0020-uapi-linux-update-kernel-UAPI-header-files.patch b/SOURCES/0020-uapi-linux-update-kernel-UAPI-header-files.patch new file mode 100644 index 0000000..f36f8b9 --- /dev/null +++ b/SOURCES/0020-uapi-linux-update-kernel-UAPI-header-files.patch @@ -0,0 +1,117 @@ +From 8fa6c3a1bc2536816e961a4ef865c67218683bf2 Mon Sep 17 00:00:00 2001 +From: Amit Cohen +Date: Thu, 2 Jul 2020 16:11:09 +0300 +Subject: [PATCH 20/26] uapi: linux: update kernel UAPI header files + +Add copies of kernel UAPI header files needed for link extended state: + uapi/linux/ethtool.h + uapi/linux/ethtool_netlink.h + +The copies are taken from net-next tree, +commit ecc31c60240b ("ethtool: Add link extended state") + +Signed-off-by: Amit Cohen +Signed-off-by: Michal Kubecek +(cherry picked from commit dc46dd315071190b880dba9b48dd4521cf7c133e) +--- + uapi/linux/ethtool.h | 70 ++++++++++++++++++++++++++++++++++++ + uapi/linux/ethtool_netlink.h | 2 ++ + 2 files changed, 72 insertions(+) + +diff --git a/uapi/linux/ethtool.h b/uapi/linux/ethtool.h +index 355e718a99fd..847ccd0b1fce 100644 +--- a/uapi/linux/ethtool.h ++++ b/uapi/linux/ethtool.h +@@ -577,6 +577,76 @@ struct ethtool_pauseparam { + __u32 tx_pause; + }; + ++/** ++ * enum ethtool_link_ext_state - link extended state ++ */ ++enum ethtool_link_ext_state { ++ ETHTOOL_LINK_EXT_STATE_AUTONEG, ++ ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, ++ ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, ++ ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, ++ ETHTOOL_LINK_EXT_STATE_NO_CABLE, ++ ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, ++ ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, ++ ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, ++ ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, ++ ETHTOOL_LINK_EXT_STATE_OVERHEAT, ++}; ++ ++/** ++ * enum ethtool_link_ext_substate_autoneg - more information in addition to ++ * ETHTOOL_LINK_EXT_STATE_AUTONEG. ++ */ ++enum ethtool_link_ext_substate_autoneg { ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE, ++ ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD, ++}; ++ ++/** ++ * enum ethtool_link_ext_substate_link_training - more information in addition to ++ * ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. ++ */ ++enum ethtool_link_ext_substate_link_training { ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT, ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY, ++ ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT, ++}; ++ ++/** ++ * enum ethtool_link_ext_substate_logical_mismatch - more information in addition ++ * to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. ++ */ ++enum ethtool_link_ext_substate_link_logical_mismatch { ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED, ++ ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED, ++}; ++ ++/** ++ * enum ethtool_link_ext_substate_bad_signal_integrity - more information in ++ * addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. ++ */ ++enum ethtool_link_ext_substate_bad_signal_integrity { ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, ++}; ++ ++/** ++ * enum ethtool_link_ext_substate_cable_issue - more information in ++ * addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. ++ */ ++enum ethtool_link_ext_substate_cable_issue { ++ ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1, ++ ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, ++}; ++ + #define ETH_GSTRING_LEN 32 + + /** +diff --git a/uapi/linux/ethtool_netlink.h b/uapi/linux/ethtool_netlink.h +index c1b4d67d35d1..cebdb52e6a05 100644 +--- a/uapi/linux/ethtool_netlink.h ++++ b/uapi/linux/ethtool_netlink.h +@@ -237,6 +237,8 @@ enum { + ETHTOOL_A_LINKSTATE_LINK, /* u8 */ + ETHTOOL_A_LINKSTATE_SQI, /* u32 */ + ETHTOOL_A_LINKSTATE_SQI_MAX, /* u32 */ ++ ETHTOOL_A_LINKSTATE_EXT_STATE, /* u8 */ ++ ETHTOOL_A_LINKSTATE_EXT_SUBSTATE, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_LINKSTATE_CNT, +-- +2.26.2 + diff --git a/SOURCES/0021-netlink-settings-expand-linkstate_reply_cb-to-suppor.patch b/SOURCES/0021-netlink-settings-expand-linkstate_reply_cb-to-suppor.patch new file mode 100644 index 0000000..1b5bcf3 --- /dev/null +++ b/SOURCES/0021-netlink-settings-expand-linkstate_reply_cb-to-suppor.patch @@ -0,0 +1,187 @@ +From abc33073ed6d4528d3c951cc719a155a6e1178cd Mon Sep 17 00:00:00 2001 +From: Amit Cohen +Date: Thu, 2 Jul 2020 16:11:11 +0300 +Subject: [PATCH 21/26] netlink: settings: expand linkstate_reply_cb() to + support link extended state + +Print extended state in addition to link state. + +In case that extended state is not provided, print state only. +If extended substate is provided in addition to the extended state, +print it also. + +Signed-off-by: Amit Cohen +Signed-off-by: Michal Kubecek +(cherry picked from commit ba6367d2bb32173166b91fbcc053865c99ca7c57) +--- + netlink/settings.c | 147 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 146 insertions(+), 1 deletion(-) + +diff --git a/netlink/settings.c b/netlink/settings.c +index 3a9518a7e12b..75db15e5069c 100644 +--- a/netlink/settings.c ++++ b/netlink/settings.c +@@ -565,6 +565,149 @@ int linkinfo_reply_cb(const struct nlmsghdr *nlhdr, void *data) + return MNL_CB_OK; + } + ++static const char *get_enum_string(const char *const *string_table, unsigned int n_string_table, ++ unsigned int val) ++{ ++ if (val >= n_string_table || !string_table[val]) ++ return NULL; ++ else ++ return string_table[val]; ++} ++ ++static const char *const names_link_ext_state[] = { ++ [ETHTOOL_LINK_EXT_STATE_AUTONEG] = "Autoneg", ++ [ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE] = "Link training failure", ++ [ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH] = "Logical mismatch", ++ [ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY] = "Bad signal integrity", ++ [ETHTOOL_LINK_EXT_STATE_NO_CABLE] = "No cable", ++ [ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE] = "Cable issue", ++ [ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE] = "EEPROM issue", ++ [ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE] = "Calibration failure", ++ [ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED] = "Power budget exceeded", ++ [ETHTOOL_LINK_EXT_STATE_OVERHEAT] = "Overheat", ++}; ++ ++static const char *const names_autoneg_link_ext_substate[] = { ++ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED] = ++ "No partner detected", ++ [ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED] = ++ "Ack not received", ++ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED] = ++ "Next page exchange failed", ++ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE] = ++ "No partner detected during force mode", ++ [ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE] = ++ "FEC mismatch during override", ++ [ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD] = ++ "No HCD", ++}; ++ ++static const char *const names_link_training_link_ext_substate[] = { ++ [ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED] = ++ "KR frame lock not acquired", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT] = ++ "KR link inhibit timeout", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY] = ++ "KR Link partner did not set receiver ready", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT] = ++ "Remote side is not ready yet", ++}; ++ ++static const char *const names_link_logical_mismatch_link_ext_substate[] = { ++ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK] = ++ "PCS did not acquire block lock", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK] = ++ "PCS did not acquire AM lock", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS] = ++ "PCS did not get align_status", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED] = ++ "FC FEC is not locked", ++ [ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED] = ++ "RS FEC is not locked", ++}; ++ ++static const char *const names_bad_signal_integrity_link_ext_substate[] = { ++ [ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS] = ++ "Large number of physical errors", ++ [ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE] = ++ "Unsupported rate", ++}; ++ ++static const char *const names_cable_issue_link_ext_substate[] = { ++ [ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE] = ++ "Unsupported cable", ++ [ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE] = ++ "Cable test failure", ++}; ++ ++static const char *link_ext_substate_get(uint8_t link_ext_state_val, uint8_t link_ext_substate_val) ++{ ++ switch (link_ext_state_val) { ++ case ETHTOOL_LINK_EXT_STATE_AUTONEG: ++ return get_enum_string(names_autoneg_link_ext_substate, ++ ARRAY_SIZE(names_autoneg_link_ext_substate), ++ link_ext_substate_val); ++ case ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE: ++ return get_enum_string(names_link_training_link_ext_substate, ++ ARRAY_SIZE(names_link_training_link_ext_substate), ++ link_ext_substate_val); ++ case ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH: ++ return get_enum_string(names_link_logical_mismatch_link_ext_substate, ++ ARRAY_SIZE(names_link_logical_mismatch_link_ext_substate), ++ link_ext_substate_val); ++ case ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY: ++ return get_enum_string(names_bad_signal_integrity_link_ext_substate, ++ ARRAY_SIZE(names_bad_signal_integrity_link_ext_substate), ++ link_ext_substate_val); ++ case ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE: ++ return get_enum_string(names_cable_issue_link_ext_substate, ++ ARRAY_SIZE(names_cable_issue_link_ext_substate), ++ link_ext_substate_val); ++ default: ++ return NULL; ++ } ++} ++ ++static void linkstate_link_ext_substate_print(const struct nlattr *tb[], struct nl_context *nlctx, ++ uint8_t link_ext_state_val) ++{ ++ uint8_t link_ext_substate_val; ++ const char *link_ext_substate_str; ++ ++ if (!tb[ETHTOOL_A_LINKSTATE_EXT_SUBSTATE]) ++ return; ++ ++ link_ext_substate_val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_EXT_SUBSTATE]); ++ ++ link_ext_substate_str = link_ext_substate_get(link_ext_state_val, link_ext_substate_val); ++ if (!link_ext_substate_str) ++ printf(", %u", link_ext_substate_val); ++ else ++ printf(", %s", link_ext_substate_str); ++} ++ ++static void linkstate_link_ext_state_print(const struct nlattr *tb[], struct nl_context *nlctx) ++{ ++ uint8_t link_ext_state_val; ++ const char *link_ext_state_str; ++ ++ if (!tb[ETHTOOL_A_LINKSTATE_EXT_STATE]) ++ return; ++ ++ link_ext_state_val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_EXT_STATE]); ++ ++ link_ext_state_str = get_enum_string(names_link_ext_state, ++ ARRAY_SIZE(names_link_ext_state), ++ link_ext_state_val); ++ if (!link_ext_state_str) ++ printf(" (%u", link_ext_state_val); ++ else ++ printf(" (%s", link_ext_state_str); ++ ++ linkstate_link_ext_substate_print(tb, nlctx, link_ext_state_val); ++ printf(")"); ++} ++ + int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data) + { + const struct nlattr *tb[ETHTOOL_A_LINKSTATE_MAX + 1] = {}; +@@ -585,7 +728,9 @@ int linkstate_reply_cb(const struct nlmsghdr *nlhdr, void *data) + uint8_t val = mnl_attr_get_u8(tb[ETHTOOL_A_LINKSTATE_LINK]); + + print_banner(nlctx); +- printf("\tLink detected: %s\n", val ? "yes" : "no"); ++ printf("\tLink detected: %s", val ? "yes" : "no"); ++ linkstate_link_ext_state_print(tb, nlctx); ++ printf("\n"); + } + + if (tb[ETHTOOL_A_LINKSTATE_SQI]) { +-- +2.26.2 + diff --git a/SOURCES/0022-netlink-prepare-for-more-per-op-info.patch b/SOURCES/0022-netlink-prepare-for-more-per-op-info.patch new file mode 100644 index 0000000..4b3a008 --- /dev/null +++ b/SOURCES/0022-netlink-prepare-for-more-per-op-info.patch @@ -0,0 +1,126 @@ +From 15e57173470b0929fd649bc7b0376d41c786ddbe Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Sun, 18 Oct 2020 14:31:49 -0700 +Subject: [PATCH 22/26] netlink: prepare for more per-op info + +We stored an array of op flags, to check if operations are +supported. Make that array a structure rather than plain +uint32_t in preparation for storing more state. + +v3: new patch + +Signed-off-by: Jakub Kicinski +Signed-off-by: Michal Kubecek +(cherry picked from commit 8d36270be3c06b99eba281ccf341ebfab555c6b6) +--- + netlink/netlink.c | 25 +++++++++++++------------ + netlink/netlink.h | 6 +++++- + 2 files changed, 18 insertions(+), 13 deletions(-) + +diff --git a/netlink/netlink.c b/netlink/netlink.c +index e42d57076a4b..86dc1efdf5ce 100644 +--- a/netlink/netlink.c ++++ b/netlink/netlink.c +@@ -120,19 +120,19 @@ bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd, + nlctx->wildcard_unsupported = true; + return true; + } +- if (!nlctx->ops_flags) { ++ if (!nlctx->ops_info) { + nlctx->ioctl_fallback = true; + return false; + } +- if (cmd > ETHTOOL_MSG_USER_MAX || !nlctx->ops_flags[cmd]) { ++ if (cmd > ETHTOOL_MSG_USER_MAX || !nlctx->ops_info[cmd].op_flags) { + nlctx->ioctl_fallback = true; + return true; + } + +- if (is_dump && !(nlctx->ops_flags[cmd] & GENL_CMD_CAP_DUMP)) ++ if (is_dump && !(nlctx->ops_info[cmd].op_flags & GENL_CMD_CAP_DUMP)) + nlctx->wildcard_unsupported = true; + +- return !(nlctx->ops_flags[cmd] & cap); ++ return !(nlctx->ops_info[cmd].op_flags & cap); + } + + /* initialization */ +@@ -140,12 +140,12 @@ bool netlink_cmd_check(struct cmd_context *ctx, unsigned int cmd, + static int genl_read_ops(struct nl_context *nlctx, + const struct nlattr *ops_attr) + { ++ struct nl_op_info *ops_info; + struct nlattr *op_attr; +- uint32_t *ops_flags; + int ret; + +- ops_flags = calloc(__ETHTOOL_MSG_USER_CNT, sizeof(ops_flags[0])); +- if (!ops_flags) ++ ops_info = calloc(__ETHTOOL_MSG_USER_CNT, sizeof(ops_info[0])); ++ if (!ops_info) + return -ENOMEM; + + mnl_attr_for_each_nested(op_attr, ops_attr) { +@@ -163,13 +163,14 @@ static int genl_read_ops(struct nl_context *nlctx, + if (op_id >= __ETHTOOL_MSG_USER_CNT) + continue; + +- ops_flags[op_id] = mnl_attr_get_u32(tb[CTRL_ATTR_OP_FLAGS]); ++ ops_info[op_id].op_flags = ++ mnl_attr_get_u32(tb[CTRL_ATTR_OP_FLAGS]); + } + +- nlctx->ops_flags = ops_flags; ++ nlctx->ops_info = ops_info; + return 0; + err: +- free(ops_flags); ++ free(ops_info); + return ret; + } + +@@ -273,7 +274,7 @@ int netlink_init(struct cmd_context *ctx) + out_nlsk: + nlsock_done(nlctx->ethnl_socket); + out_free: +- free(nlctx->ops_flags); ++ free(nlctx->ops_info); + free(nlctx); + return ret; + } +@@ -283,7 +284,7 @@ static void netlink_done(struct cmd_context *ctx) + if (!ctx->nlctx) + return; + +- free(ctx->nlctx->ops_flags); ++ free(ctx->nlctx->ops_info); + free(ctx->nlctx); + ctx->nlctx = NULL; + cleanup_all_strings(); +diff --git a/netlink/netlink.h b/netlink/netlink.h +index dd4a02bcc916..61a072db8ed9 100644 +--- a/netlink/netlink.h ++++ b/netlink/netlink.h +@@ -25,6 +25,10 @@ enum link_mode_class { + LM_CLASS_FEC, + }; + ++struct nl_op_info { ++ uint32_t op_flags; ++}; ++ + struct nl_context { + struct cmd_context *ctx; + void *cmd_private; +@@ -34,7 +38,7 @@ struct nl_context { + unsigned int suppress_nlerr; + uint16_t ethnl_fam; + uint32_t ethnl_mongrp; +- uint32_t *ops_flags; ++ struct nl_op_info *ops_info; + struct nl_socket *ethnl_socket; + struct nl_socket *ethnl2_socket; + struct nl_socket *rtnl_socket; +-- +2.26.2 + diff --git a/SOURCES/0023-netlink-fix-use-after-free-in-netlink_run_handler.patch b/SOURCES/0023-netlink-fix-use-after-free-in-netlink_run_handler.patch new file mode 100644 index 0000000..45cfd61 --- /dev/null +++ b/SOURCES/0023-netlink-fix-use-after-free-in-netlink_run_handler.patch @@ -0,0 +1,53 @@ +From ef1675823905ff09cb5e551700a124d0133648b7 Mon Sep 17 00:00:00 2001 +From: Michal Kubecek +Date: Mon, 9 Nov 2020 13:30:54 +0100 +Subject: [PATCH 23/26] netlink: fix use after free in netlink_run_handler() + +Valgrind detected use after free in netlink_run_handler(): some members of +struct nl_context are accessed after the netlink context is freed by +netlink_done(). Use local variables to store the two flags and check them +instead. + +Fixes: 6c19c0d559c8 ("netlink: use genetlink ops information to decide about fallback") +Signed-off-by: Michal Kubecek +(cherry picked from commit 29b38ea218bd978d1950e12cc24da98215a1eeef) +--- + netlink/netlink.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/netlink/netlink.c b/netlink/netlink.c +index 86dc1efdf5ce..2a12bb8b1759 100644 +--- a/netlink/netlink.c ++++ b/netlink/netlink.c +@@ -303,6 +303,7 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc, + bool no_fallback) + { + bool wildcard = ctx->devname && !strcmp(ctx->devname, WILDCARD_DEVNAME); ++ bool wildcard_unsupported, ioctl_fallback; + struct nl_context *nlctx; + const char *reason; + int ret; +@@ -324,14 +325,17 @@ void netlink_run_handler(struct cmd_context *ctx, nl_func_t nlfunc, + nlctx = ctx->nlctx; + + ret = nlfunc(ctx); ++ wildcard_unsupported = nlctx->wildcard_unsupported; ++ ioctl_fallback = nlctx->ioctl_fallback; + netlink_done(ctx); +- if (no_fallback || ret != -EOPNOTSUPP || !nlctx->ioctl_fallback) { +- if (nlctx->wildcard_unsupported) ++ ++ if (no_fallback || ret != -EOPNOTSUPP || !ioctl_fallback) { ++ if (wildcard_unsupported) + fprintf(stderr, "%s\n", + "subcommand does not support wildcard dump"); + exit(ret >= 0 ? ret : 1); + } +- if (nlctx->wildcard_unsupported) ++ if (wildcard_unsupported) + reason = "subcommand does not support wildcard dump"; + else + reason = "kernel netlink support for subcommand missing"; +-- +2.26.2 + diff --git a/SOURCES/0024-netlink-fix-leaked-instances-of-struct-nl_socket.patch b/SOURCES/0024-netlink-fix-leaked-instances-of-struct-nl_socket.patch new file mode 100644 index 0000000..8d6b809 --- /dev/null +++ b/SOURCES/0024-netlink-fix-leaked-instances-of-struct-nl_socket.patch @@ -0,0 +1,64 @@ +From 5fad40a007b61092161d1e4fd0ffbbc3e7b8ba6c Mon Sep 17 00:00:00 2001 +From: Michal Kubecek +Date: Mon, 9 Nov 2020 13:30:57 +0100 +Subject: [PATCH 24/26] netlink: fix leaked instances of struct nl_socket + +Valgrind detected memory leaks caused by missing cleanup of netlink +context's ethnl_socket, ethnl2_socket and rtnl_socket. Also, contrary to +its description, nlsock_done() does not free struct nl_socket itself. +Fix nlsock_done() to free the structure and use it to dispose of sockets +pointed to by struct nl_context members. + +Fixes: 50efb3cdd2bb ("netlink: netlink socket wrapper and helpers") +Fixes: 87307c30724d ("netlink: initialize ethtool netlink socket") +Fixes: 7f3585b22a4b ("netlink: add handler for permaddr (-P)") +Signed-off-by: Michal Kubecek +(cherry picked from commit d85f57499d75da5c98b73652488f3f62c6f6d8ea) +--- + netlink/netlink.c | 11 ++++++++--- + netlink/nlsock.c | 3 +++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/netlink/netlink.c b/netlink/netlink.c +index 2a12bb8b1759..5677274c2fce 100644 +--- a/netlink/netlink.c ++++ b/netlink/netlink.c +@@ -281,11 +281,16 @@ out_free: + + static void netlink_done(struct cmd_context *ctx) + { +- if (!ctx->nlctx) ++ struct nl_context *nlctx = ctx->nlctx; ++ ++ if (!nlctx) + return; + +- free(ctx->nlctx->ops_info); +- free(ctx->nlctx); ++ nlsock_done(nlctx->ethnl_socket); ++ nlsock_done(nlctx->ethnl2_socket); ++ nlsock_done(nlctx->rtnl_socket); ++ free(nlctx->ops_info); ++ free(nlctx); + ctx->nlctx = NULL; + cleanup_all_strings(); + } +diff --git a/netlink/nlsock.c b/netlink/nlsock.c +index ef31d8c33b29..0ec2738d81d2 100644 +--- a/netlink/nlsock.c ++++ b/netlink/nlsock.c +@@ -395,8 +395,11 @@ out_msgbuff: + */ + void nlsock_done(struct nl_socket *nlsk) + { ++ if (!nlsk) ++ return; + if (nlsk->sk) + mnl_socket_close(nlsk->sk); + msgbuff_done(&nlsk->msgbuff); + memset(nlsk, '\0', sizeof(*nlsk)); ++ free(nlsk); + } +-- +2.26.2 + diff --git a/SOURCES/0025-netlink-do-not-send-messages-and-process-replies-in-.patch b/SOURCES/0025-netlink-do-not-send-messages-and-process-replies-in-.patch new file mode 100644 index 0000000..e5866c2 --- /dev/null +++ b/SOURCES/0025-netlink-do-not-send-messages-and-process-replies-in-.patch @@ -0,0 +1,301 @@ +From fc5f2a6bb2911a951bf5a1364dc5732e521d735a Mon Sep 17 00:00:00 2001 +From: Michal Kubecek +Date: Mon, 9 Nov 2020 14:29:56 +0100 +Subject: [PATCH 25/26] netlink: do not send messages and process replies in + nl_parser() + +When called with group_style = PARSER_GROUP_MSG, nl_parser() not only +parses the command line and composes the messages but also sends them to +kernel and processes the replies. This is inconsistent with other modes and +also impractical as it takes the control over the process from caller where +it belongs. + +Modify nl_parser() to pass composed messages back to caller (which is only +nl_sset() at the moment) and let it send requests and process replies. This +will be needed for an upcoming backward compatibility patch which will need +to inspect and possibly modify one of the composed messages. + +Signed-off-by: Michal Kubecek +(cherry picked from commit acd9730d1e794f85caf1192fe8788876e6f96305) +--- + netlink/cable_test.c | 2 +- + netlink/channels.c | 2 +- + netlink/coalesce.c | 2 +- + netlink/eee.c | 2 +- + netlink/parser.c | 43 ++++++++++++++++++++++++++++--------------- + netlink/parser.h | 3 ++- + netlink/pause.c | 2 +- + netlink/rings.c | 2 +- + netlink/settings.c | 35 ++++++++++++++++++++++++++++++----- + 9 files changed, 66 insertions(+), 27 deletions(-) + +diff --git a/netlink/cable_test.c b/netlink/cable_test.c +index d39b7d82efb0..e05b67c4e231 100644 +--- a/netlink/cable_test.c ++++ b/netlink/cable_test.c +@@ -574,7 +574,7 @@ int nl_cable_test_tdr(struct cmd_context *ctx) + ctx->devname, 0)) + return -EMSGSIZE; + +- ret = nl_parser(nlctx, tdr_params, NULL, PARSER_GROUP_NEST); ++ ret = nl_parser(nlctx, tdr_params, NULL, PARSER_GROUP_NEST, NULL); + if (ret < 0) + return ret; + +diff --git a/netlink/channels.c b/netlink/channels.c +index c6002ceeb121..894c74bcc11a 100644 +--- a/netlink/channels.c ++++ b/netlink/channels.c +@@ -126,7 +126,7 @@ int nl_schannels(struct cmd_context *ctx) + ctx->devname, 0)) + return -EMSGSIZE; + +- ret = nl_parser(nlctx, schannels_params, NULL, PARSER_GROUP_NONE); ++ ret = nl_parser(nlctx, schannels_params, NULL, PARSER_GROUP_NONE, NULL); + if (ret < 0) + return 1; + +diff --git a/netlink/coalesce.c b/netlink/coalesce.c +index 65f75cf9a8dd..0223f8e3484e 100644 +--- a/netlink/coalesce.c ++++ b/netlink/coalesce.c +@@ -254,7 +254,7 @@ int nl_scoalesce(struct cmd_context *ctx) + ctx->devname, 0)) + return -EMSGSIZE; + +- ret = nl_parser(nlctx, scoalesce_params, NULL, PARSER_GROUP_NONE); ++ ret = nl_parser(nlctx, scoalesce_params, NULL, PARSER_GROUP_NONE, NULL); + if (ret < 0) + return 1; + +diff --git a/netlink/eee.c b/netlink/eee.c +index d3135b2094a4..04d8f0bbe3fc 100644 +--- a/netlink/eee.c ++++ b/netlink/eee.c +@@ -174,7 +174,7 @@ int nl_seee(struct cmd_context *ctx) + ctx->devname, 0)) + return -EMSGSIZE; + +- ret = nl_parser(nlctx, seee_params, NULL, PARSER_GROUP_NONE); ++ ret = nl_parser(nlctx, seee_params, NULL, PARSER_GROUP_NONE, NULL); + if (ret < 0) + return 1; + +diff --git a/netlink/parser.c b/netlink/parser.c +index 3b25f5d5a88e..c2eae93efb69 100644 +--- a/netlink/parser.c ++++ b/netlink/parser.c +@@ -920,7 +920,7 @@ static void __parser_set(uint64_t *map, unsigned int idx) + } + + struct tmp_buff { +- struct nl_msg_buff msgbuff; ++ struct nl_msg_buff *msgbuff; + unsigned int id; + unsigned int orig_len; + struct tmp_buff *next; +@@ -951,7 +951,12 @@ static struct tmp_buff *tmp_buff_find_or_create(struct tmp_buff **phead, + if (!new_buff) + return NULL; + new_buff->id = id; +- msgbuff_init(&new_buff->msgbuff); ++ new_buff->msgbuff = malloc(sizeof(*new_buff->msgbuff)); ++ if (!new_buff->msgbuff) { ++ free(new_buff); ++ return NULL; ++ } ++ msgbuff_init(new_buff->msgbuff); + new_buff->next = NULL; + *pbuff = new_buff; + +@@ -965,7 +970,10 @@ static void tmp_buff_destroy(struct tmp_buff *head) + + while (buff) { + next = buff->next; +- msgbuff_done(&buff->msgbuff); ++ if (buff->msgbuff) { ++ msgbuff_done(buff->msgbuff); ++ free(buff->msgbuff); ++ } + free(buff); + buff = next; + } +@@ -980,13 +988,22 @@ static void tmp_buff_destroy(struct tmp_buff *head) + * param_parser::offset) + * @group_style: defines if identifiers in .group represent separate messages, + * nested attributes or are not allowed ++ * @msgbuffs: (only used for @group_style = PARSER_GROUP_MSG) array to store ++ * pointers to composed messages; caller must make sure this ++ * array is sufficient, i.e. that it has at least as many entries ++ * as the number of different .group values in params array; ++ * entries are filled from the start, remaining entries are not ++ * modified; caller should zero initialize the array before ++ * calling nl_parser() + */ + int nl_parser(struct nl_context *nlctx, const struct param_parser *params, +- void *dest, enum parser_group_style group_style) ++ void *dest, enum parser_group_style group_style, ++ struct nl_msg_buff **msgbuffs) + { + struct nl_socket *nlsk = nlctx->ethnl_socket; + const struct param_parser *parser; + struct tmp_buff *buffs = NULL; ++ unsigned int n_msgbuffs = 0; + struct tmp_buff *buff; + unsigned int n_params; + uint64_t *params_seen; +@@ -1004,7 +1021,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params, + buff = tmp_buff_find_or_create(&buffs, parser->group); + if (!buff) + goto out_free_buffs; +- msgbuff = &buff->msgbuff; ++ msgbuff = buff->msgbuff; + ret = msg_init(nlctx, msgbuff, parser->group, + NLM_F_REQUEST | NLM_F_ACK); + if (ret < 0) +@@ -1013,7 +1030,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params, + switch (group_style) { + case PARSER_GROUP_NEST: + ret = -EMSGSIZE; +- nest = ethnla_nest_start(&buff->msgbuff, parser->group); ++ nest = ethnla_nest_start(buff->msgbuff, parser->group); + if (!nest) + goto out_free_buffs; + break; +@@ -1062,7 +1079,7 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params, + buff = NULL; + if (parser->group) + buff = tmp_buff_find(buffs, parser->group); +- msgbuff = buff ? &buff->msgbuff : &nlsk->msgbuff; ++ msgbuff = buff ? buff->msgbuff : &nlsk->msgbuff; + + param_dest = dest ? ((char *)dest + parser->dest_offset) : NULL; + ret = parser->handler(nlctx, parser->type, parser->handler_data, +@@ -1074,12 +1091,12 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params, + if (group_style == PARSER_GROUP_MSG) { + ret = -EOPNOTSUPP; + for (buff = buffs; buff; buff = buff->next) +- if (msgbuff_len(&buff->msgbuff) > buff->orig_len && ++ if (msgbuff_len(buff->msgbuff) > buff->orig_len && + netlink_cmd_check(nlctx->ctx, buff->id, false)) + goto out_free; + } + for (buff = buffs; buff; buff = buff->next) { +- struct nl_msg_buff *msgbuff = &buff->msgbuff; ++ struct nl_msg_buff *msgbuff = buff->msgbuff; + + if (group_style == PARSER_GROUP_NONE || + msgbuff_len(msgbuff) == buff->orig_len) +@@ -1092,12 +1109,8 @@ int nl_parser(struct nl_context *nlctx, const struct param_parser *params, + goto out_free; + break; + case PARSER_GROUP_MSG: +- ret = nlsock_sendmsg(nlsk, msgbuff); +- if (ret < 0) +- goto out_free; +- ret = nlsock_process_reply(nlsk, nomsg_reply_cb, NULL); +- if (ret < 0) +- goto out_free; ++ msgbuffs[n_msgbuffs++] = msgbuff; ++ buff->msgbuff = NULL; + break; + default: + break; +diff --git a/netlink/parser.h b/netlink/parser.h +index fd55bc768d42..28f26ccc2a1c 100644 +--- a/netlink/parser.h ++++ b/netlink/parser.h +@@ -143,6 +143,7 @@ int nl_parse_char_bitset(struct nl_context *nlctx, uint16_t type, + + /* main entry point called to parse the command line */ + int nl_parser(struct nl_context *nlctx, const struct param_parser *params, +- void *dest, enum parser_group_style group_style); ++ void *dest, enum parser_group_style group_style, ++ struct nl_msg_buff **msgbuffs); + + #endif /* ETHTOOL_NETLINK_PARSER_H__ */ +diff --git a/netlink/pause.c b/netlink/pause.c +index 7b6b3a1d2c10..048320b123d2 100644 +--- a/netlink/pause.c ++++ b/netlink/pause.c +@@ -208,7 +208,7 @@ int nl_spause(struct cmd_context *ctx) + ctx->devname, 0)) + return -EMSGSIZE; + +- ret = nl_parser(nlctx, spause_params, NULL, PARSER_GROUP_NONE); ++ ret = nl_parser(nlctx, spause_params, NULL, PARSER_GROUP_NONE, NULL); + if (ret < 0) + return 1; + +diff --git a/netlink/rings.c b/netlink/rings.c +index 4061520212d5..b8c458fce25f 100644 +--- a/netlink/rings.c ++++ b/netlink/rings.c +@@ -126,7 +126,7 @@ int nl_sring(struct cmd_context *ctx) + ctx->devname, 0)) + return -EMSGSIZE; + +- ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE); ++ ret = nl_parser(nlctx, sring_params, NULL, PARSER_GROUP_NONE, NULL); + if (ret < 0) + return 1; + +diff --git a/netlink/settings.c b/netlink/settings.c +index 75db15e5069c..fac192e2fbb7 100644 +--- a/netlink/settings.c ++++ b/netlink/settings.c +@@ -1108,9 +1108,16 @@ static const struct param_parser sset_params[] = { + {} + }; + ++/* Maximum number of request messages sent to kernel; must be equal to the ++ * number of different .group values in sset_params[] array. ++ */ ++#define SSET_MAX_MSGS 4 ++ + int nl_sset(struct cmd_context *ctx) + { ++ struct nl_msg_buff *msgbuffs[SSET_MAX_MSGS] = {}; + struct nl_context *nlctx = ctx->nlctx; ++ unsigned int i; + int ret; + + nlctx->cmd = "-s"; +@@ -1118,11 +1125,29 @@ int nl_sset(struct cmd_context *ctx) + nlctx->argc = ctx->argc; + nlctx->devname = ctx->devname; + +- ret = nl_parser(nlctx, sset_params, NULL, PARSER_GROUP_MSG); +- if (ret < 0) +- return 1; ++ ret = nl_parser(nlctx, sset_params, NULL, PARSER_GROUP_MSG, msgbuffs); ++ if (ret < 0) { ++ ret = 1; ++ goto out_free; ++ } ++ ++ for (i = 0; i < SSET_MAX_MSGS && msgbuffs[i]; i++) { ++ struct nl_socket *nlsk = nlctx->ethnl_socket; + +- if (ret == 0) +- return 0; ++ ret = nlsock_sendmsg(nlsk, msgbuffs[i]); ++ if (ret < 0) ++ goto out_free; ++ ret = nlsock_process_reply(nlsk, nomsg_reply_cb, NULL); ++ if (ret < 0) ++ goto out_free; ++ } ++ ++out_free: ++ for (i = 0; i < SSET_MAX_MSGS && msgbuffs[i]; i++) { ++ msgbuff_done(msgbuffs[i]); ++ free(msgbuffs[i]); ++ } ++ if (ret >= 0) ++ return ret; + return nlctx->exit_code ?: 75; + } +-- +2.26.2 + diff --git a/SOURCES/0026-ethtool-Improve-compatibility-between-netlink-and-io.patch b/SOURCES/0026-ethtool-Improve-compatibility-between-netlink-and-io.patch new file mode 100644 index 0000000..bb2e9da --- /dev/null +++ b/SOURCES/0026-ethtool-Improve-compatibility-between-netlink-and-io.patch @@ -0,0 +1,191 @@ +From f16bc54fe82b9129d6852273d02e044b9cb28789 Mon Sep 17 00:00:00 2001 +From: Ido Schimmel +Date: Mon, 9 Nov 2020 14:29:59 +0100 +Subject: [PATCH 26/26] ethtool: Improve compatibility between netlink and + ioctl interfaces + +With the ioctl interface, when autoneg is enabled, but without +specifying speed, duplex or link modes, the advertised link modes are +set to the supported link modes by the ethtool user space utility. + +This does not happen when using the netlink interface. Fix this +incompatibility problem by having ethtool query the supported link modes +from the kernel and advertise all the "real" ones when only "autoneg on" +is specified. + +Before: + +Settings for eth0: + Supported ports: [ TP ] + Supported link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + Supported pause frame use: No + Supports auto-negotiation: Yes + Supported FEC modes: Not reported + Advertised link modes: 100baseT/Half 100baseT/Full + Advertised pause frame use: No + Advertised auto-negotiation: Yes + Advertised FEC modes: Not reported + Speed: 1000Mb/s + Duplex: Full + Auto-negotiation: on + Port: Twisted Pair + PHYAD: 0 + Transceiver: internal + MDI-X: off (auto) + Supports Wake-on: umbg + Wake-on: d + Current message level: 0x00000007 (7) + drv probe link + Link detected: yes + +After: + +Settings for eth0: + Supported ports: [ TP ] + Supported link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + Supported pause frame use: No + Supports auto-negotiation: Yes + Supported FEC modes: Not reported + Advertised link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + Advertised pause frame use: No + Advertised auto-negotiation: Yes + Advertised FEC modes: Not reported + Speed: 1000Mb/s + Duplex: Full + Auto-negotiation: on + Port: Twisted Pair + PHYAD: 0 + Transceiver: internal + MDI-X: on (auto) + Supports Wake-on: umbg + Wake-on: d + Current message level: 0x00000007 (7) + drv probe link + Link detected: yes + +Signed-off-by: Ido Schimmel +Signed-off-by: Michal Kubecek +(cherry picked from commit 124a3c06d1c34b125d84a9eb312fddd365bb7bf6) +--- + netlink/settings.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 92 insertions(+) + +diff --git a/netlink/settings.c b/netlink/settings.c +index fac192e2fbb7..01c1d38d323f 100644 +--- a/netlink/settings.c ++++ b/netlink/settings.c +@@ -1113,6 +1113,93 @@ static const struct param_parser sset_params[] = { + */ + #define SSET_MAX_MSGS 4 + ++static int linkmodes_reply_advert_all_cb(const struct nlmsghdr *nlhdr, ++ void *data) ++{ ++ const struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1] = {}; ++ DECLARE_ATTR_TB_INFO(tb); ++ struct nl_msg_buff *req_msgbuff = data; ++ const struct nlattr *ours_attr; ++ struct nlattr *req_bitset; ++ uint32_t *supported_modes; ++ unsigned int modes_count; ++ unsigned int i; ++ int ret; ++ ++ ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info); ++ if (ret < 0) ++ return MNL_CB_ERROR; ++ ours_attr = tb[ETHTOOL_A_LINKMODES_OURS]; ++ if (!ours_attr) ++ return MNL_CB_ERROR; ++ modes_count = bitset_get_count(tb[ETHTOOL_A_LINKMODES_OURS], &ret); ++ if (ret < 0) ++ return MNL_CB_ERROR; ++ supported_modes = get_compact_bitset_mask(tb[ETHTOOL_A_LINKMODES_OURS]); ++ if (!supported_modes) ++ return MNL_CB_ERROR; ++ ++ /* keep only "real" link modes */ ++ for (i = 0; i < modes_count; i++) ++ if (!lm_class_match(i, LM_CLASS_REAL)) ++ supported_modes[i / 32] &= ~((uint32_t)1 << (i % 32)); ++ ++ req_bitset = ethnla_nest_start(req_msgbuff, ETHTOOL_A_LINKMODES_OURS); ++ if (!req_bitset) ++ return MNL_CB_ERROR; ++ ++ if (ethnla_put_u32(req_msgbuff, ETHTOOL_A_BITSET_SIZE, modes_count) || ++ ethnla_put(req_msgbuff, ETHTOOL_A_BITSET_VALUE, ++ DIV_ROUND_UP(modes_count, 32) * sizeof(uint32_t), ++ supported_modes) || ++ ethnla_put(req_msgbuff, ETHTOOL_A_BITSET_MASK, ++ DIV_ROUND_UP(modes_count, 32) * sizeof(uint32_t), ++ supported_modes)) { ++ ethnla_nest_cancel(req_msgbuff, req_bitset); ++ return MNL_CB_ERROR; ++ } ++ ++ ethnla_nest_end(req_msgbuff, req_bitset); ++ return MNL_CB_OK; ++} ++ ++/* For compatibility reasons with ioctl-based ethtool, when "autoneg on" is ++ * specified without "advertise", "speed" and "duplex", we need to query the ++ * supported link modes from the kernel and advertise all the "real" ones. ++ */ ++static int nl_sset_compat_linkmodes(struct nl_context *nlctx, ++ struct nl_msg_buff *msgbuff) ++{ ++ const struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1] = {}; ++ DECLARE_ATTR_TB_INFO(tb); ++ struct nl_socket *nlsk = nlctx->ethnl_socket; ++ int ret; ++ ++ ret = mnl_attr_parse(msgbuff->nlhdr, GENL_HDRLEN, attr_cb, &tb_info); ++ if (ret < 0) ++ return ret; ++ if (!tb[ETHTOOL_A_LINKMODES_AUTONEG] || tb[ETHTOOL_A_LINKMODES_OURS] || ++ tb[ETHTOOL_A_LINKMODES_SPEED] || tb[ETHTOOL_A_LINKMODES_DUPLEX]) ++ return 0; ++ if (!mnl_attr_get_u8(tb[ETHTOOL_A_LINKMODES_AUTONEG])) ++ return 0; ++ ++ /* all conditions satisfied, create ETHTOOL_A_LINKMODES_OURS */ ++ if (netlink_cmd_check(nlctx->ctx, ETHTOOL_MSG_LINKMODES_GET, false) || ++ netlink_cmd_check(nlctx->ctx, ETHTOOL_MSG_LINKMODES_SET, false)) ++ return -EOPNOTSUPP; ++ ret = nlsock_prep_get_request(nlsk, ETHTOOL_MSG_LINKMODES_GET, ++ ETHTOOL_A_LINKMODES_HEADER, ++ ETHTOOL_FLAG_COMPACT_BITSETS); ++ if (ret < 0) ++ return ret; ++ ret = nlsock_sendmsg(nlsk, NULL); ++ if (ret < 0) ++ return ret; ++ return nlsock_process_reply(nlsk, linkmodes_reply_advert_all_cb, ++ msgbuff); ++} ++ + int nl_sset(struct cmd_context *ctx) + { + struct nl_msg_buff *msgbuffs[SSET_MAX_MSGS] = {}; +@@ -1134,6 +1221,11 @@ int nl_sset(struct cmd_context *ctx) + for (i = 0; i < SSET_MAX_MSGS && msgbuffs[i]; i++) { + struct nl_socket *nlsk = nlctx->ethnl_socket; + ++ if (msgbuffs[i]->genlhdr->cmd == ETHTOOL_MSG_LINKMODES_SET) { ++ ret = nl_sset_compat_linkmodes(nlctx, msgbuffs[i]); ++ if (ret < 0) ++ goto out_free; ++ } + ret = nlsock_sendmsg(nlsk, msgbuffs[i]); + if (ret < 0) + goto out_free; +-- +2.26.2 + diff --git a/SPECS/ethtool.spec b/SPECS/ethtool.spec index 2ad4bbd..874fba0 100644 --- a/SPECS/ethtool.spec +++ b/SPECS/ethtool.spec @@ -1,7 +1,7 @@ Name: ethtool Epoch: 2 Version: 5.8 -Release: 3%{?dist} +Release: 5%{?dist} Summary: Settings tool for Ethernet NICs License: GPLv2 Group: Applications/System @@ -26,6 +26,13 @@ Patch16: 0016-netlink-return-ENOMEM-when-calloc-fails.patch Patch17: 0017-netlink-fix-memory-leak.patch Patch18: 0018-fix-memory-leaks-in-do_sfeatures.patch Patch19: 0019-netlink-fix-copy-paste-error-in-rtm_link_summary.patch +Patch20: 0020-uapi-linux-update-kernel-UAPI-header-files.patch +Patch21: 0021-netlink-settings-expand-linkstate_reply_cb-to-suppor.patch +Patch22: 0022-netlink-prepare-for-more-per-op-info.patch +Patch23: 0023-netlink-fix-use-after-free-in-netlink_run_handler.patch +Patch24: 0024-netlink-fix-leaked-instances-of-struct-nl_socket.patch +Patch25: 0025-netlink-do-not-send-messages-and-process-replies-in-.patch +Patch26: 0026-ethtool-Improve-compatibility-between-netlink-and-io.patch BuildRequires: libmnl-devel Conflicts: filesystem < 3 @@ -55,6 +62,13 @@ network devices, especially of Ethernet devices. %patch17 -p1 %patch18 -p1 %patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 %build %configure @@ -71,6 +85,12 @@ make DESTDIR=%{buildroot} INSTALL='install -p' install %{_datadir}/bash-completion/completions/ethtool %changelog +* Thu Nov 12 2020 Ivan Vecera - 2:5.8-5 +- Fixed a regression + +* Fri Nov 06 2020 Ivan Vecera - 2:5.8-4 +- Added support for extended link state reporting + * Fri Sep 25 2020 Ivan Vecera - 2:5.8-3 - Fixed memory leak