diff --git a/src/networking.c b/src/networking.c index c24a95019b..e823ee0473 100644 --- a/src/networking.c +++ b/src/networking.c @@ -167,6 +167,7 @@ client *createClient(connection *conn) { c->nread = 0; c->read_flags = 0; c->write_flags = 0; + c->io_checked = 0; c->cmd = c->lastcmd = c->realcmd = c->io_parsed_cmd = NULL; c->cur_script = NULL; c->multibulklen = 0; @@ -4832,6 +4833,13 @@ void ioThreadReadQueryFromClient(void *data) { goto done; } + /* Handle possible security attacks. */ + if (!strcasecmp(c->argv[0]->ptr, "host:") || !strcasecmp(c->argv[0]->ptr, "post")) { + c->io_checked = IO_CHECKED_NOT_SECURITY; + } else { + c->io_checked = IO_CHECKED_SECURITY; + } + /* Lookup command offload */ c->io_parsed_cmd = lookupCommand(c->argv, c->argc); if (c->io_parsed_cmd && commandCheckArity(c->io_parsed_cmd, c->argc, NULL) == 0) { diff --git a/src/server.c b/src/server.c index ab95f84346..a8940b2550 100644 --- a/src/server.c +++ b/src/server.c @@ -3829,7 +3829,8 @@ int processCommand(client *c) { } /* Handle possible security attacks. */ - if (!strcasecmp(c->argv[0]->ptr, "host:") || !strcasecmp(c->argv[0]->ptr, "post")) { + if (c->io_checked == IO_CHECKED_NOT_SECURITY || + (!c->io_checked && (!strcasecmp(c->argv[0]->ptr, "host:") || !strcasecmp(c->argv[0]->ptr, "post")))) { securityWarningCommand(c); return C_ERR; } diff --git a/src/server.h b/src/server.h index 4fad8d2508..25988f4e9c 100644 --- a/src/server.h +++ b/src/server.h @@ -1148,6 +1148,12 @@ typedef enum { CLIENT_COMPLETED_IO = 2 /* IO-thread sets this state after completing IO operation. */ } clientIOState; +typedef enum { + IO_NOT_CHECKED = 0, /* Initial state: io thread doesn't check anything yet. */ + IO_CHECKED_SECURITY = 1, /* IO checked, there is no possible security attacks. */ + IO_CHECKED_NOT_SECURITY = 2 /* IO checked, there is possible security attacks. */ +} ioCheckedState; + typedef struct ClientFlags { uint64_t primary : 1; /* This client is a primary */ uint64_t replica : 1; /* This client is a replica */ @@ -1251,6 +1257,9 @@ typedef struct client { size_t argv_len_sum; /* Sum of lengths of objects in argv list. */ volatile uint8_t io_read_state; /* Indicate the IO read state of the client */ volatile uint8_t io_write_state; /* Indicate the IO write state of the client */ + uint8_t io_checked; /* Indicate if the logic is already covered in io-thread, + * then reduce the logic in main thread. + * For example, the possible security attacks check of command. */ uint8_t cur_tid; /* ID of IO thread currently performing IO for this client */ int nread; /* Number of bytes of the last read. */ int nwritten; /* Number of bytes of the last write. */