You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

188 lines
5.4 KiB

commit 0dbaa252df906cc9c1d0dc7a075c16e039ab1c5b
Author: Willy Tarreau <w@1wt.eu>
Date: Tue Aug 21 15:35:31 2018 +0200
BUG/MEDIUM: cli/threads: protect some server commands against concurrent operations
The server-specific CLI commands "set weight", "set maxconn",
"disable agent", "enable agent", "disable health", "enable health",
"disable server" and "enable server" were not protected against
concurrent accesses. Now they take the server lock around the
sensitive part.
This patch must be backported to 1.8.
(cherry picked from commit 3bcc2699ba08dd3971ae7a56631994b2524d2acb)
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/server.c b/src/server.c
index 36a05e27..98dae535 100644
--- a/src/server.c
+++ b/src/server.c
@@ -4299,6 +4299,10 @@ static int cli_parse_get_weight(char **args, struct appctx *appctx, void *privat
return 1;
}
+/* Parse a "set weight" command.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_set_weight(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4311,16 +4315,24 @@ static int cli_parse_set_weight(char **args, struct appctx *appctx, void *privat
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
+
warning = server_parse_weight_change_request(sv, args[3]);
if (warning) {
appctx->ctx.cli.severity = LOG_ERR;
appctx->ctx.cli.msg = warning;
appctx->st0 = CLI_ST_PRINT;
}
+
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
+
return 1;
}
-/* parse a "set maxconn server" command. It always returns 1. */
+/* parse a "set maxconn server" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_set_maxconn_server(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4333,16 +4345,24 @@ static int cli_parse_set_maxconn_server(char **args, struct appctx *appctx, void
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
+
warning = server_parse_maxconn_change_request(sv, args[4]);
if (warning) {
appctx->ctx.cli.severity = LOG_ERR;
appctx->ctx.cli.msg = warning;
appctx->st0 = CLI_ST_PRINT;
}
+
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
+
return 1;
}
-/* parse a "disable agent" command. It always returns 1. */
+/* parse a "disable agent" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_disable_agent(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4354,11 +4374,16 @@ static int cli_parse_disable_agent(char **args, struct appctx *appctx, void *pri
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
sv->agent.state &= ~CHK_ST_ENABLED;
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
-/* parse a "disable health" command. It always returns 1. */
+/* parse a "disable health" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_disable_health(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4370,11 +4395,16 @@ static int cli_parse_disable_health(char **args, struct appctx *appctx, void *pr
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
sv->check.state &= ~CHK_ST_ENABLED;
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
-/* parse a "disable server" command. It always returns 1. */
+/* parse a "disable server" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_disable_server(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4386,11 +4416,16 @@ static int cli_parse_disable_server(char **args, struct appctx *appctx, void *pr
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
srv_adm_set_maint(sv);
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
-/* parse a "enable agent" command. It always returns 1. */
+/* parse a "enable agent" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_enable_agent(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4409,11 +4444,16 @@ static int cli_parse_enable_agent(char **args, struct appctx *appctx, void *priv
return 1;
}
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
sv->agent.state |= CHK_ST_ENABLED;
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
-/* parse a "enable health" command. It always returns 1. */
+/* parse a "enable health" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_enable_health(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4425,11 +4465,16 @@ static int cli_parse_enable_health(char **args, struct appctx *appctx, void *pri
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
sv->check.state |= CHK_ST_ENABLED;
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}
-/* parse a "enable server" command. It always returns 1. */
+/* parse a "enable server" command. It always returns 1.
+ *
+ * Grabs the server lock.
+ */
static int cli_parse_enable_server(char **args, struct appctx *appctx, void *private)
{
struct server *sv;
@@ -4441,11 +4486,13 @@ static int cli_parse_enable_server(char **args, struct appctx *appctx, void *pri
if (!sv)
return 1;
+ HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
srv_adm_set_ready(sv);
if (!(sv->flags & SRV_F_COOKIESET)
&& (sv->proxy->ck_opts & PR_CK_DYNAMIC) &&
sv->cookie)
srv_check_for_dup_dyncookie(sv);
+ HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
return 1;
}