summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2020-05-27 11:45:49 +0200
committerantirez <antirez@gmail.com>2020-05-27 11:45:49 +0200
commit325409a011d0155513a71b92dc09cac06b90b261 (patch)
treefe9f8aa20c2fcbf041857353a051bfade8c228c8
parent94c026cd1971d1f0680c20f550e3094717d3b55e (diff)
downloadredis-325409a011d0155513a71b92dc09cac06b90b261.tar.gz
Set a protocol error if master use the inline protocol.
We want to react a bit more aggressively if we sense that the master is sending us some corrupted stream. By setting the protocol error we both ensure that the replica will disconnect, and avoid caching the master so that a full SYNC will be required. This is protective against replication bugs.
-rw-r--r--src/networking.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/networking.c b/src/networking.c
index 364654642..bb682db4c 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1553,6 +1553,19 @@ int processInlineBuffer(client *c) {
if (querylen == 0 && getClientType(c) == CLIENT_TYPE_SLAVE)
c->repl_ack_time = server.unixtime;
+ /* Masters should never send us inline protocol to run actual
+ * commands. If this happens, it is likely due to a bug in Redis where
+ * we got some desynchronization in the protocol, for example
+ * beause of a PSYNC gone bad.
+ *
+ * However the is an exception: masters may send us just a newline
+ * to keep the connection active. */
+ if (querylen != 0 && c->flags & CLIENT_MASTER) {
+ serverLog(LL_WARNING,"WARNING: Receiving inline protocol from master, master stream corruption? Closing the master connection and discarding the cached master.");
+ setProtocolError("Master using the inline protocol. Desync?",c);
+ return C_ERR;
+ }
+
/* Move querybuffer position to the next query in the buffer. */
c->qb_pos += querylen+linefeed_chars;
@@ -1576,7 +1589,7 @@ int processInlineBuffer(client *c) {
* CLIENT_PROTOCOL_ERROR. */
#define PROTO_DUMP_LEN 128
static void setProtocolError(const char *errstr, client *c) {
- if (server.verbosity <= LL_VERBOSE) {
+ if (server.verbosity <= LL_VERBOSE || c->flags & CLIENT_MASTER) {
sds client = catClientInfoString(sdsempty(),c);
/* Sample some protocol to given an idea about what was inside. */
@@ -1595,7 +1608,9 @@ static void setProtocolError(const char *errstr, client *c) {
}
/* Log all the client and protocol info. */
- serverLog(LL_VERBOSE,
+ int loglevel = (c->flags & CLIENT_MASTER) ? LL_WARNING :
+ LL_VERBOSE;
+ serverLog(loglevel,
"Protocol error (%s) from client: %s. %s", errstr, client, buf);
sdsfree(client);
}