From bfbb7db6a9dcfa22ad83c43d27c0962c655c9fa1 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Mon, 20 Jan 2025 10:45:52 +0800 Subject: [PATCH] Update to 1.1.1-4 lldpad: do not remove config when stopping lldpad Resolves: RHEL-84979 Signed-off-by: Hangbin Liu --- 0002-do-not-remove-config.patch | 101 ++++++++++++++++++++++ 0003-Protect-uses-of-select.patch | 91 +++++++++++++++++++ 0004-fix-lldpad-netlink-heap-access.patch | 72 +++++++++++++++ lldpad.spec | 8 +- 4 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 0002-do-not-remove-config.patch create mode 100644 0003-Protect-uses-of-select.patch create mode 100644 0004-fix-lldpad-netlink-heap-access.patch diff --git a/0002-do-not-remove-config.patch b/0002-do-not-remove-config.patch new file mode 100644 index 0000000..10488c0 --- /dev/null +++ b/0002-do-not-remove-config.patch @@ -0,0 +1,101 @@ +From cfef0032247f9a3950a9909d59db88e948741ee3 Mon Sep 17 00:00:00 2001 +From: Hangbin Liu +Date: Wed, 9 Oct 2024 03:53:16 +0000 +Subject: [PATCH 2/2] lldpad: do not remove config when stopping lldpad + +When lldpad is terminated by systemd or kill, the remove_all_adapters() +function is called. However, this function is intended to release port +resources, and the configuration file should not be destroyed. We only +need to remove the port when it is explicitly deleted. Otherwise, all +configurations will be lost when lldpad is stopped. + +Fixes: a75e35a0cb36 ("lldpad: remove device from config file when ports are removed") +Reported-by: Fei Liu +Signed-off-by: Hangbin Liu +Signed-off-by: Aaron Conole +--- + config.c | 2 +- + event_iface.c | 2 +- + lldp/ports.c | 5 +++-- + lldp/ports.h | 2 +- + lldpad.c | 2 +- + 5 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/config.c b/config.c +index 13ee7aa7ba47..e046f94fe911 100644 +--- a/config.c ++++ b/config.c +@@ -135,7 +135,7 @@ void scan_port(UNUSED void *eloop_data, UNUSED void *user_ctx) + } + next = port->next; + if (!found) +- remove_port(port->ifname); ++ remove_port(port->ifname, true); + } + + /* Walk port list looking for devices that should have been added +diff --git a/event_iface.c b/event_iface.c +index 916bf4b4cbe8..65f1f83bf8e7 100644 +--- a/event_iface.c ++++ b/event_iface.c +@@ -297,7 +297,7 @@ static void event_if_decode_nlmsg(int route_type, void *data, int len) + if (route_type == RTM_DELLINK) { + LLDPAD_INFO("%s: %s: device removed!\n", + __func__, device_name); +- remove_port(device_name); ++ remove_port(device_name, true); + } + break; + case IF_OPER_DORMANT: +diff --git a/lldp/ports.c b/lldp/ports.c +index 3eab71f8eff1..284f8f6c7108 100644 +--- a/lldp/ports.c ++++ b/lldp/ports.c +@@ -297,7 +297,7 @@ fail: + return NULL; + } + +-int remove_port(const char *ifname) ++int remove_port(const char *ifname, bool remove_config) + { + int ifindex = get_ifidx(ifname); + struct port *port; /* Pointer to port to remove */ +@@ -356,7 +356,8 @@ int remove_port(const char *ifname) + + LIST_REMOVE(agent, entry); + +- remove_config_device(ifname, agent->type); ++ if (remove_config) ++ remove_config_device(ifname, agent->type); + + free(agent); + } +diff --git a/lldp/ports.h b/lldp/ports.h +index 21280e0ef0e2..a5006fa86a74 100644 +--- a/lldp/ports.h ++++ b/lldp/ports.h +@@ -97,7 +97,7 @@ extern struct port *porthead; + extern "C" { + #endif + struct port *add_port(int ifindex, const char *); +-int remove_port(const char *); ++int remove_port(const char *, bool remove_config); + #ifdef __cplusplus + } + #endif +diff --git a/lldpad.c b/lldpad.c +index 65e92c703c42..ddc8b631e0e5 100644 +--- a/lldpad.c ++++ b/lldpad.c +@@ -167,7 +167,7 @@ static void remove_all_adapters(void) + + for (port = porthead; port; port = next) { + next = port->next; +- remove_port(port->ifname); ++ remove_port(port->ifname, false); + } + + return; +-- +2.39.5 (Apple Git-154) + diff --git a/0003-Protect-uses-of-select.patch b/0003-Protect-uses-of-select.patch new file mode 100644 index 0000000..d6e2512 --- /dev/null +++ b/0003-Protect-uses-of-select.patch @@ -0,0 +1,91 @@ +From 00b3c78f867ccae6fcca8089e6ae5099c86ffffe Mon Sep 17 00:00:00 2001 +From: "Loren M. Lang" +Date: Thu, 26 Dec 2024 21:24:46 -0800 +Subject: [PATCH 1/2] Protect uses of select() from crash on too many file + descriptors + +The fd_set macros don't check for overflow and will cause an +out-of-bounds access when given a file description >= FD_SETSIZE (1024) + +This doesn't fix the fundamental issue, but prevents a crash and should +allow partial functionality. The full fix requires switching to poll() +instead. + +Signed-off-by: "Loren M. Lang" +Signed-off-by: Aaron Conole +--- + eloop.c | 29 +++++++++++++++++++++++++++-- + 1 file changed, 27 insertions(+), 2 deletions(-) + +diff --git a/eloop.c b/eloop.c +index 06b90afc9c17..a20165791ede 100644 +--- a/eloop.c ++++ b/eloop.c +@@ -180,6 +180,17 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, + } + + ++static inline void warn_too_many_fds() ++{ ++ static bool warned = false; ++ ++ if (!warned) { ++ fprintf(stderr, "unable to handle more than %d file descriptors\n", FD_SETSIZE); ++ fprintf(stderr, "too many interfaces being watched\n"); ++ warned = true; ++ } ++} ++ + static void eloop_sock_table_set_fds(struct eloop_sock_table *table, + fd_set *fds) + { +@@ -190,8 +201,13 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table, + if (table->table == NULL) + return; + +- for (i = 0; i < table->count; i++) ++ for (i = 0; i < table->count; i++) { ++ if (table->table[i].sock >= FD_SETSIZE) { ++ warn_too_many_fds(); ++ continue; ++ } + FD_SET(table->table[i].sock, fds); ++ } + } + + +@@ -205,6 +221,9 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table, + + table->changed = 0; + for (i = 0; i < table->count; i++) { ++ if (table->table[i].sock >= FD_SETSIZE) { ++ return; ++ } + if (FD_ISSET(table->table[i].sock, fds)) { + table->table[i].handler(table->table[i].sock, + table->table[i].eloop_data, +@@ -497,7 +516,8 @@ void eloop_run(void) + eloop_sock_table_set_fds(&eloop.readers, rfds); + eloop_sock_table_set_fds(&eloop.writers, wfds); + eloop_sock_table_set_fds(&eloop.exceptions, efds); +- res = select(eloop.max_sock + 1, rfds, wfds, efds, ++ res = select(eloop.max_sock < FD_SETSIZE ? eloop.max_sock + 1 : FD_SETSIZE, ++ rfds, wfds, efds, + eloop.timeout ? &_tv : NULL); + if (res < 0 && errno != EINTR && errno != 0) { + perror("select"); +@@ -571,6 +591,11 @@ void eloop_wait_for_read_sock(int sock) + if (sock < 0) + return; + ++ if (sock >= FD_SETSIZE) { ++ warn_too_many_fds(); ++ return; ++ } ++ + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + select(sock + 1, &rfds, NULL, NULL, NULL); +-- +2.46.0 + diff --git a/0004-fix-lldpad-netlink-heap-access.patch b/0004-fix-lldpad-netlink-heap-access.patch new file mode 100644 index 0000000..d5ce103 --- /dev/null +++ b/0004-fix-lldpad-netlink-heap-access.patch @@ -0,0 +1,72 @@ +From ad0aaf147f63a5ff585c8bfbebe77871cf12e0e6 Mon Sep 17 00:00:00 2001 +From: Chunjie Zhu +Date: Thu, 20 Feb 2025 14:52:24 +0800 +Subject: [PATCH 2/2] fix lldpad netlink heap access overrun + +Fixes: d43abb0267f36 ("lldpad: do not use macv[tap/lan] interfaces as ports") +Signed-off-by: Chunjie Zhu +Signed-off-by: Aaron Conole +--- + lldp_util.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/lldp_util.c b/lldp_util.c +index 510d2ef78b63..61fb0bcd3ac9 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -672,8 +672,9 @@ static struct nla_policy ifla_info_policy[IFLA_INFO_MAX + 1] = + + int is_macvtap(const char *ifname) + { +- int ret, s; ++ int ret, s, realsize; + struct nlmsghdr *nlh; ++ void *temp; + struct ifinfomsg *ifinfo; + struct nlattr *tb[IFLA_MAX+1], + *tb2[IFLA_INFO_MAX+1]; +@@ -684,14 +685,12 @@ int is_macvtap(const char *ifname) + return false; + } + +- nlh = malloc(NLMSG_SIZE); ++ nlh = calloc(1, NLMSG_SIZE); + + if (!nlh) { + goto out; + } + +- memset(nlh, 0, NLMSG_SIZE); +- + nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + nlh->nlmsg_type = RTM_GETLINK; + nlh->nlmsg_flags = NLM_F_REQUEST; +@@ -706,10 +705,23 @@ int is_macvtap(const char *ifname) + goto out_free; + } + +- memset(nlh, 0, NLMSG_SIZE); ++ do { ++ realsize = recv(s, NULL, 0, MSG_DONTWAIT | MSG_PEEK | MSG_TRUNC); ++ } while ((realsize < 0) && errno == EINTR); ++ ++ if (realsize < 0) { ++ goto out_free; ++ } ++ ++ temp = realloc(nlh, realsize); ++ if (!temp) { ++ goto out_free; ++ } ++ memset(temp, 0, realsize); ++ nlh = temp; + + do { +- ret = recv(s, (void *) nlh, NLMSG_SIZE, MSG_DONTWAIT); ++ ret = recv(s, (void *) nlh, realsize, MSG_DONTWAIT); + } while ((ret < 0) && errno == EINTR); + + if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), +-- +2.46.0 + diff --git a/lldpad.spec b/lldpad.spec index f2f94e8..916143f 100644 --- a/lldpad.spec +++ b/lldpad.spec @@ -12,7 +12,7 @@ Name: lldpad Version: 1.1.1 -Release: 3.git%{shortcommit}%{?dist} +Release: 4.git%{shortcommit}%{?dist} Summary: Intel LLDP Agent %forgemeta @@ -23,6 +23,9 @@ Source0: %{forgesource}#/%{name}-%{version}.tar.gz # When 1.1.2 or later is released, simply remove this # patch and generate a new one. Patch1: 0001-patch-to-latest.patch +Patch2: 0002-do-not-remove-config.patch +Patch3: 0003-Protect-uses-of-select.patch +Patch4: 0004-fix-lldpad-netlink-heap-access.patch BuildRequires: automake autoconf BuildRequires: flex @@ -97,6 +100,9 @@ rm -f %{buildroot}%{_libdir}/liblldp_clif.la %{_libdir}/liblldp_clif.so %changelog +* Mon Jan 20 2025 Hangbin Liu - 1.1.1-4.gitf1dd9eb +- do not remove config when stopping lldpad (RHEL-84979) + * Thu Apr 17 2025 Hangbin Liu - 1.1.1-3.gitf1dd9eb - Rebase to latest upstream code (RHEL-84979)