[lldpd]: Ports few fixes from lldpd master (#3889)
* lldpctl: put a lock around some commands to avoid race conditions * Read all notifications in lldpctl_recv * lib: fix memory leak * lib: fix memory leak when handling I/O * Update series
This commit is contained in:
parent
f126258d5f
commit
86e23f9ede
@ -0,0 +1,169 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
From b8e66b52f40103fd3abea77031c4634742c31860 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pavel Shirshov <pavelsh@microsoft.com>
|
||||||
|
Date: Thu, 12 Dec 2019 12:47:42 -0800
|
||||||
|
Subject: [PATCH 1/1] Read all notifications in lldpctl_recv
|
||||||
|
|
||||||
|
---
|
||||||
|
src/lib/connection.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib/connection.c b/src/lib/connection.c
|
||||||
|
index 591d9e9..88bbc99 100644
|
||||||
|
--- a/src/lib/connection.c
|
||||||
|
+++ b/src/lib/connection.c
|
||||||
|
@@ -253,8 +253,8 @@ lldpctl_recv(lldpctl_conn_t *conn, const uint8_t *data, size_t length)
|
||||||
|
memcpy(conn->input_buffer + conn->input_buffer_len, data, length);
|
||||||
|
conn->input_buffer_len += length;
|
||||||
|
|
||||||
|
- /* Is it a notification? */
|
||||||
|
- check_for_notification(conn);
|
||||||
|
+ /* Read all notifications */
|
||||||
|
+ while(!check_for_notification(conn));
|
||||||
|
|
||||||
|
RESET_ERROR(conn);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.1.windows.2
|
||||||
|
|
24
src/lldpd/patch/0006-lib-fix-memory-leak.patch
Normal file
24
src/lldpd/patch/0006-lib-fix-memory-leak.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
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
|
||||||
|
|
@ -2,3 +2,7 @@
|
|||||||
0001-return-error-when-port-does-not-exist.patch
|
0001-return-error-when-port-does-not-exist.patch
|
||||||
0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch
|
0002-Let-linux-kernel-to-find-appropriate-nl_pid-automa.patch
|
||||||
0003-update-tx-interval-immediately.patch
|
0003-update-tx-interval-immediately.patch
|
||||||
|
0004-lldpctl-put-a-lock-around-some-commands-to-avoid-rac.patch
|
||||||
|
0005-Read-all-notifications-in-lldpctl_recv.patch
|
||||||
|
0006-lib-fix-memory-leak.patch
|
||||||
|
0007-lib-fix-memory-leak-when-handling-I-O.patch
|
||||||
|
Reference in New Issue
Block a user