Upgrade lldpd to 1.0.16

This fixes lldpcli hitting some error related to being unable to get a
lock on /var/run/lldpd.socket. This version is the version in Debian
Bookworm, even though lldpd is in the lldp container, and that is on
Bullseye. This is because there is a change that went into 1.0.12 that
uses a separate lock file for the lldpd socket instead of locking the
socket file itself. This appears to cause problems in an unprivileged
docker container for unknown reasons (privileged docker container is
fine). Bullseye is on 1.0.11, which isn't new enough to have this
change.

I can't see any specific system capability that might address this.
Rather than debugging this further, just upgrade to the Bookworm
version.

Signed-off-by: Saikrishna Arcot <sarcot@microsoft.com>
This commit is contained in:
Saikrishna Arcot 2023-10-11 16:50:59 -07:00 committed by Ying Xie
parent cae42998dd
commit 3d0a0da24f
10 changed files with 7 additions and 458 deletions

View File

@ -1,7 +1,7 @@
# lldpd package
LLDPD_VERSION = 1.0.4
LLDPD_VERSION_SUFFIX = 1
LLDPD_VERSION = 1.0.16
LLDPD_VERSION_SUFFIX = 1+deb12u1
LLDPD_VERSION_FULL = $(LLDPD_VERSION)-$(LLDPD_VERSION_SUFFIX)
LLDPD = lldpd_$(LLDPD_VERSION_FULL)_$(CONFIGURED_ARCH).deb

View File

@ -20,10 +20,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
rm -rf lldpd-$(LLDPD_VERSION)
# download debian LLDPDD
wget -NO "$(DSC_FILE)" $(DSC_FILE_URL)
wget -NO "$(ORIG_FILE)" $(ORIG_FILE_URL)
wget -NO "$(DEBIAN_FILE)" $(DEBIAN_FILE_URL)
dpkg-source -x lldpd_$(LLDPD_VERSION_FULL).dsc
dget $(DSC_FILE_URL)
pushd lldpd-$(LLDPD_VERSION)
git init

View File

@ -18,11 +18,11 @@ index c16219b..b51e4eb 100644
+ const char *portname = cmdenv_get(env, "ports");
+ int find_port = 0;
log_debug("lldpctl", "lldp PortID TLV Subtype Local port-id '%s' port-descr '%s'", id, descr);
log_debug("lldpctl",
"lldp PortID TLV Subtype Local port-id '%s' port-descr '%s'", id, descr);
@@ -165,6 +167,12 @@ cmd_portid_type_local(struct lldpctl_conn_t *conn, struct writer *w,
log_warnx("lldpctl", "unable to set LLDP Port Description for %s."
" %s", name, lldpctl_last_strerror(conn));
" %s",
name, lldpctl_last_strerror(conn));
}
+ find_port = 1;
+ }

View File

@ -1,169 +0,0 @@
From 46aa45d0fa3e8879ecdca1c156cb2d91194c45e9 Mon Sep 17 00:00:00 2001
From: Pavel Shirshov <pavelsh@microsoft.com>
Date: Thu, 12 Dec 2019 13:47:17 -0800
Subject: [PATCH 1/1] lldpctl: put a lock around some commands to avoid race
conditions
---
src/client/client.h | 3 +++
src/client/commands.c | 58 ++++++++++++++++++++++++++++++++++++++++---
src/client/conf.c | 4 +--
3 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/src/client/client.h b/src/client/client.h
index e3ee352..6c3e30d 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -62,6 +62,8 @@ extern void add_history ();
#endif
#undef NEWLINE
+extern const char *ctlname;
+
/* commands.c */
#define NEWLINE "<CR>"
struct cmd_node;
@@ -76,6 +78,7 @@ struct cmd_node *commands_new(
struct cmd_env*, void *),
void *);
struct cmd_node* commands_privileged(struct cmd_node *);
+struct cmd_node* commands_lock(struct cmd_node *);
struct cmd_node* commands_hidden(struct cmd_node *);
void commands_free(struct cmd_node *);
const char *cmdenv_arg(struct cmd_env*);
diff --git a/src/client/commands.c b/src/client/commands.c
index beedbf1..58df4a7 100644
--- a/src/client/commands.c
+++ b/src/client/commands.c
@@ -18,6 +18,9 @@
#include "client.h"
#include <string.h>
#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
/**
* An element of the environment (a key and a value).
@@ -68,6 +71,7 @@ struct cmd_node {
const char *token; /**< Token to enter this cnode */
const char *doc; /**< Documentation string */
int privileged; /**< Privileged command? */
+ int lock; /**< Lock required for execution? */
int hidden; /**< Hidden command? */
/**
@@ -113,6 +117,21 @@ commands_privileged(struct cmd_node *node)
return node;
}
+/**
+ * Make a node accessible only with a lock.
+ *
+ * @param node node to use lock to execute
+ * @return the modified node
+ *
+ * The node is modified. It is returned to ease chaining.
+ */
+struct cmd_node*
+commands_lock(struct cmd_node *node)
+{
+ if (node) node->lock = 1;
+ return node;
+}
+
/**
* Hide a node from help or completion.
*
@@ -344,6 +363,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
int n, rc = 0, completion = (word != NULL);
int help = 0; /* Are we asking for help? */
int complete = 0; /* Are we asking for possible completions? */
+ int needlock = 0; /* Do we need a lock? */
struct cmd_env env = {
.elements = TAILQ_HEAD_INITIALIZER(env.elements),
.stack = TAILQ_HEAD_INITIALIZER(env.stack),
@@ -351,6 +371,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
.argv = argv,
.argp = 0
};
+ static int lockfd = -1;
cmdenv_push(&env, root);
if (!completion)
for (n = 0; n < argc; n++)
@@ -388,6 +409,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
!strcmp(candidate->token, token)) {
/* Exact match */
best = candidate;
+ needlock = needlock || candidate->lock;
break;
}
if (!best) best = candidate;
@@ -406,6 +428,7 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
if (!candidate->token &&
CAN_EXECUTE(candidate)) {
best = candidate;
+ needlock = needlock || candidate->lock;
break;
}
}
@@ -421,9 +444,38 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
/* Push and execute */
cmdenv_push(&env, best);
- if (best->execute && best->execute(conn, w, &env, best->arg) != 1) {
- rc = -1;
- goto end;
+ if (best->execute) {
+ struct sockaddr_un su;
+ if (needlock) {
+ if (lockfd == -1) {
+ log_debug("lldpctl", "reopen %s for locking", ctlname);
+ if ((lockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
+ log_warn("lldpctl", "cannot open for lock %s", ctlname);
+ rc = -1;
+ goto end;
+ }
+ su.sun_family = AF_UNIX;
+ strlcpy(su.sun_path, ctlname, sizeof(su.sun_path));
+ if (connect(lockfd, (struct sockaddr *)&su, sizeof(struct sockaddr_un)) == -1) {
+ log_warn("lldpctl", "cannot connect to socket %s", ctlname);
+ rc = -1;
+ close(lockfd); lockfd = -1;
+ goto end;
+ }
+ }
+ if (lockf(lockfd, F_LOCK, 0) == -1) {
+ log_warn("lldpctl", "cannot get lock on %s", ctlname);
+ rc = -1;
+ close(lockfd); lockfd = -1;
+ goto end;
+ }
+ }
+ rc = best->execute(conn, w, &env, best->arg) != 1 ? -1 : rc;
+ if (needlock && lockf(lockfd, F_ULOCK, 0) == -1) {
+ log_warn("lldpctl", "cannot unlock %s", ctlname);
+ close(lockfd); lockfd = -1;
+ }
+ if (rc == -1) goto end;
}
env.argp++;
}
diff --git a/src/client/conf.c b/src/client/conf.c
index 1a14981..ba5743f 100644
--- a/src/client/conf.c
+++ b/src/client/conf.c
@@ -37,8 +37,8 @@ register_commands_configure(struct cmd_node *root)
"unconfigure",
"Unconfigure system settings",
NULL, NULL, NULL);
- commands_privileged(configure);
- commands_privileged(unconfigure);
+ commands_privileged(commands_lock(configure));
+ commands_privileged(commands_lock(unconfigure));
cmd_restrict_ports(configure);
cmd_restrict_ports(unconfigure);
--
2.17.1.windows.2

View File

@ -1,24 +0,0 @@
From 833653dffb9be40110142af2a7cb4076a0dd24f5 Mon Sep 17 00:00:00 2001
From: Pavel Shirshov <pavelsh@microsoft.com>
Date: Thu, 12 Dec 2019 12:48:47 -0800
Subject: [PATCH 1/1] lib: fix memory leak
---
src/lib/connection.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/lib/connection.c b/src/lib/connection.c
index 88bbc99..aa88dad 100644
--- a/src/lib/connection.c
+++ b/src/lib/connection.c
@@ -114,6 +114,7 @@ lldpctl_new_name(const char *ctlname, lldpctl_send_callback send, lldpctl_recv_c
}
if (!send && !recv) {
if ((data = malloc(sizeof(struct lldpctl_conn_sync_t))) == NULL) {
+ free(conn->ctlname);
free(conn);
return NULL;
}
--
2.17.1.windows.2

View File

@ -1,85 +0,0 @@
From f6086575e63b5e089814ca116aa637d7588bfcd3 Mon Sep 17 00:00:00 2001
From: Pavel Shirshov <pavelsh@microsoft.com>
Date: Thu, 12 Dec 2019 13:52:42 -0800
Subject: [PATCH 1/1] lib: fix memory leak when handling I/O.
---
src/lib/atom.c | 11 ++++++-----
src/lib/atom.h | 9 ++++-----
src/lib/atoms/port.c | 2 +-
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/lib/atom.c b/src/lib/atom.c
index 955f434..f81d3bb 100644
--- a/src/lib/atom.c
+++ b/src/lib/atom.c
@@ -322,10 +322,12 @@ _lldpctl_do_something(lldpctl_conn_t *conn,
return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION);
conn->state = state_send;
if (state_data)
- conn->state_data = strdup(state_data);
+ strlcpy(conn->state_data, state_data, sizeof(conn->state_data));
+ else
+ conn->state_data[0] = 0;
}
if (conn->state == state_send &&
- (state_data == NULL || !strcmp(conn->state_data, state_data))) {
+ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) {
/* We need to send the currently built message */
rc = lldpctl_send(conn);
if (rc < 0)
@@ -333,7 +335,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn,
conn->state = state_recv;
}
if (conn->state == state_recv &&
- (state_data == NULL || !strcmp(conn->state_data, state_data))) {
+ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) {
/* We need to receive the answer */
while ((rc = ctl_msg_recv_unserialized(&conn->input_buffer,
&conn->input_buffer_len,
@@ -347,8 +349,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn,
return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION);
/* rc == 0 */
conn->state = CONN_STATE_IDLE;
- free(conn->state_data);
- conn->state_data = NULL;
+ conn->state_data[0] = 0;
return 0;
} else
return SET_ERROR(conn, LLDPCTL_ERR_INVALID_STATE);
diff --git a/src/lib/atom.h b/src/lib/atom.h
index 265c0a7..ab7037d 100644
--- a/src/lib/atom.h
+++ b/src/lib/atom.h
@@ -55,11 +55,10 @@ struct lldpctl_conn_t {
#define CONN_STATE_GET_DEFAULT_PORT_SEND 14
#define CONN_STATE_GET_DEFAULT_PORT_RECV 15
int state; /* Current state */
- char *state_data; /* Data attached to the state. It is used to
- * check that we are using the same data as a
- * previous call until the state machine goes to
- * CONN_STATE_IDLE. */
-
+ /* Data attached to the state. It is used to check that we are using the
+ * same data as a previous call until the state machine goes to
+ * CONN_STATE_IDLE. */
+ char state_data[IFNAMSIZ + 64];
/* Error handling */
lldpctl_error_t error; /* Last error */
diff --git a/src/lib/atoms/port.c b/src/lib/atoms/port.c
index 545155c..d902188 100644
--- a/src/lib/atoms/port.c
+++ b/src/lib/atoms/port.c
@@ -329,7 +329,7 @@ _lldpctl_atom_set_atom_port(lldpctl_atom_t *atom, lldpctl_key_t key, lldpctl_ato
struct lldpd_hardware *hardware = p->hardware;
struct lldpd_port_set set = {};
int rc;
- char *canary;
+ char *canary = NULL;
#ifdef ENABLE_DOT3
struct _lldpctl_atom_dot3_power_t *dpow;
--
2.17.1.windows.2

View File

@ -1,35 +0,0 @@
From fdb789c348fdcde6d5ef8b837d7f33718bc0862b Mon Sep 17 00:00:00 2001
From: sudhanshukumar22 <sudhanshu.kumar@broadcom.com>
Date: Mon, 23 Nov 2020 20:47:28 -0800
Subject: [PATCH] Ported fix for https://github.com/lldpd/lldpd/issues/408 from
community
---
src/lib/atom.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/lib/atom.c b/src/lib/atom.c
index f81d3bb..75c1275 100644
--- a/src/lib/atom.c
+++ b/src/lib/atom.c
@@ -327,7 +327,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn,
conn->state_data[0] = 0;
}
if (conn->state == state_send &&
- (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) {
+ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data) - 1))) {
/* We need to send the currently built message */
rc = lldpctl_send(conn);
if (rc < 0)
@@ -335,7 +335,7 @@ _lldpctl_do_something(lldpctl_conn_t *conn,
conn->state = state_recv;
}
if (conn->state == state_recv &&
- (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data)))) {
+ (state_data == NULL || !strncmp(conn->state_data, state_data, sizeof(conn->state_data) - 1))) {
/* We need to receive the answer */
while ((rc = ctl_msg_recv_unserialized(&conn->input_buffer,
&conn->input_buffer_len,
--
2.12.2

View File

@ -1,47 +0,0 @@
From e9bf329eee94d6d49a17da35aea189179aeed3c6 Mon Sep 17 00:00:00 2001
From: sudhanshukumar22 <sudhanshu.kumar@broadcom.com>
Date: Thu, 24 Dec 2020 09:27:49 -0800
Subject: [PATCH] From 5c3479463a919193213213e2d8634c754c09aa51 Mon Sep 17
00:00:00 2001 From: Vincent Bernat <vincent@bernat.ch> Date: Sun, 6 Dec 2020
14:21:04 +0100 Subject: [PATCH] lib: fix LLDP-MED location parsing in
liblldpctl
Some bounds were not checked correctly when parsing LLDP-MED civic
location fields. This triggers out-of-bound reads (no write) in
lldpcli, ultimately leading to a crash.
Fix #420
Signed-off-by: sudhanshukumar22 <sudhanshu.kumar@broadcom.com>
---
src/lib/atoms/med.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/lib/atoms/med.c b/src/lib/atoms/med.c
index e1b20fd..595dba4 100644
--- a/src/lib/atoms/med.c
+++ b/src/lib/atoms/med.c
@@ -540,6 +540,7 @@ _lldpctl_atom_get_str_med_location(lldpctl_atom_t *atom, lldpctl_key_t key)
return NULL;
case lldpctl_k_med_location_country:
if (m->location->format != LLDP_MED_LOCFORMAT_CIVIC) break;
+ if (m->location->data_len < 4) return NULL;
value = _lldpctl_alloc_in_atom(atom, 3);
if (!value) return NULL;
memcpy(value, m->location->data + 2, 2);
@@ -732,8 +733,11 @@ _lldpctl_atom_iter_med_caelements_list(lldpctl_atom_t *atom)
{
struct _lldpctl_atom_med_caelements_list_t *plist =
(struct _lldpctl_atom_med_caelements_list_t *)atom;
- struct ca_iter *iter = _lldpctl_alloc_in_atom(atom, sizeof(struct ca_iter));
- if (!iter) return NULL;
+ struct ca_iter *iter;
+ if (plist->parent->location->data_len < 4 ||
+ *(uint8_t*)plist->parent->location->data < 3 ||
+ !(iter = _lldpctl_alloc_in_atom(atom, sizeof(struct ca_iter))))
+ return NULL;
iter->data = (uint8_t*)plist->parent->location->data + 4;
iter->data_len = *(uint8_t*)plist->parent->location->data - 3;
return (lldpctl_atom_iter_t*)iter;
--
2.12.2

View File

@ -1,82 +0,0 @@
diff --git a/src/daemon/interfaces-linux.c b/src/daemon/interfaces-linux.c
index a8280c8..a51440a 100644
--- a/src/daemon/interfaces-linux.c
+++ b/src/daemon/interfaces-linux.c
@@ -775,7 +775,7 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces
created = 1;
}
if (hardware->h_flags) continue;
- if (hardware->h_ops != &bond_ops) {
+ if (hardware->h_ops != &bond_ops || hardware->h_ifindex_changed) {
if (!created) {
log_debug("interfaces",
"bond %s is converted from another type of interface",
@@ -794,7 +794,7 @@ iflinux_handle_bond(struct lldpd *cfg, struct interfaces_device_list *interfaces
} else bmaster = hardware->h_data;
bmaster->index = master->index;
strlcpy(bmaster->name, master->name, IFNAMSIZ);
- if (hardware->h_ops != &bond_ops) {
+ if (hardware->h_ops != &bond_ops || hardware->h_ifindex_changed) {
if (iface_bond_init(cfg, hardware) != 0) {
log_warn("interfaces", "unable to initialize %s",
hardware->h_ifname);
diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c
index 3c6c255..58db018 100644
--- a/src/daemon/interfaces.c
+++ b/src/daemon/interfaces.c
@@ -623,7 +623,7 @@ interfaces_helper_physical(struct lldpd *cfg,
}
if (hardware->h_flags)
continue;
- if (hardware->h_ops != ops) {
+ if (hardware->h_ops != ops || hardware->h_ifindex_changed) {
if (!created) {
log_debug("interfaces",
"interface %s is converted from another type of interface",
diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c
index 1d92dd3..f3e82e5 100644
--- a/src/daemon/lldpd.c
+++ b/src/daemon/lldpd.c
@@ -147,6 +147,12 @@ lldpd_get_hardware(struct lldpd *cfg, char *name, int index)
TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
if (strcmp(hardware->h_ifname, name) == 0) {
if (hardware->h_flags == 0) {
+ if (hardware->h_ifindex != 0 &&
+ hardware->h_ifindex != index) {
+ log_debug("interfaces", "%s changed index: from %d to %d",
+ hardware->h_ifname, hardware->h_ifindex, index);
+ hardware->h_ifindex_changed = 1;
+ }
hardware->h_ifindex = index;
break;
}
@@ -392,7 +398,8 @@ lldpd_reset_timer(struct lldpd *cfg)
}
/* Compare with the previous value */
- if (hardware->h_lport_previous &&
+ if (!hardware->h_ifindex_changed &&
+ hardware->h_lport_previous &&
output_len == hardware->h_lport_previous_len &&
!memcmp(output, hardware->h_lport_previous, output_len)) {
log_debug("localchassis",
@@ -402,6 +409,7 @@ lldpd_reset_timer(struct lldpd *cfg)
log_debug("localchassis",
"change detected for port %s, resetting its timer",
hardware->h_ifname);
+ hardware->h_ifindex_changed = 0;
levent_schedule_pdu(hardware);
}
diff --git a/src/lldpd-structs.h b/src/lldpd-structs.h
index f6b03d7..213f306 100644
--- a/src/lldpd-structs.h
+++ b/src/lldpd-structs.h
@@ -454,6 +454,7 @@ struct lldpd_hardware {
removed if this is left
to 0. */
int h_ifindex; /* Interface index, used by SNMP */
+ int h_ifindex_changed; /* Interface index has changed */
char h_ifname[IFNAMSIZ]; /* Should be unique */
u_int8_t h_lladdr[ETHER_ADDR_LEN];

View File

@ -1,8 +1,2 @@
# This series applies on GIT commit 396961a038a38675d46f96eaa7b430b2a1f8701b
0001-return-error-when-port-does-not-exist.patch
0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch
0006-lib-fix-memory-leak.patch
0007-lib-fix-memory-leak-when-handling-I-O.patch
0010-Ported-fix-for-length-exceeded-from-lldp-community.patch
0011-fix-med-location-len.patch
0012-fix-recreate-socket-on-ifindex-change.patch