diff options
Diffstat (limited to 'src/networking.c')
-rw-r--r-- | src/networking.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/src/networking.c b/src/networking.c index ea54697df..25d2b4c34 100644 --- a/src/networking.c +++ b/src/networking.c @@ -134,7 +134,7 @@ client *createClient(connection *conn) { connSetReadHandler(conn, readQueryFromClient); connSetPrivateData(conn, c); } - c->buf = zmalloc(PROTO_REPLY_CHUNK_BYTES); + c->buf = zmalloc_usable(PROTO_REPLY_CHUNK_BYTES, &c->buf_usable_size); selectDb(c,0); uint64_t client_id; atomicGetIncr(server.next_client_id, client_id, 1); @@ -150,7 +150,6 @@ client *createClient(connection *conn) { c->lib_name = NULL; c->lib_ver = NULL; c->bufpos = 0; - c->buf_usable_size = zmalloc_usable_size(c->buf); c->buf_peak = c->buf_usable_size; c->buf_peak_last_reset_time = server.unixtime; c->ref_repl_buf_node = NULL; @@ -621,9 +620,9 @@ void addReplyErrorSdsSafe(client *c, sds err) { addReplyErrorSdsEx(c, err, 0); } -/* Internal function used by addReplyErrorFormat and addReplyErrorFormatEx. +/* Internal function used by addReplyErrorFormat, addReplyErrorFormatEx and RM_ReplyWithErrorFormat. * Refer to afterErrorReply for more information about the flags. */ -static void addReplyErrorFormatInternal(client *c, int flags, const char *fmt, va_list ap) { +void addReplyErrorFormatInternal(client *c, int flags, const char *fmt, va_list ap) { va_list cpy; va_copy(cpy,ap); sds s = sdscatvprintf(sdsempty(),fmt,cpy); @@ -701,11 +700,12 @@ void trimReplyUnusedTailSpace(client *c) { if (tail->size - tail->used > tail->size / 4 && tail->used < PROTO_REPLY_CHUNK_BYTES) { + size_t usable_size; size_t old_size = tail->size; - tail = zrealloc(tail, tail->used + sizeof(clientReplyBlock)); + tail = zrealloc_usable(tail, tail->used + sizeof(clientReplyBlock), &usable_size); /* take over the allocation's internal fragmentation (at least for * memory usage tracking) */ - tail->size = zmalloc_usable_size(tail) - sizeof(clientReplyBlock); + tail->size = usable_size - sizeof(clientReplyBlock); c->reply_bytes = c->reply_bytes + tail->size - old_size; listNodeValue(ln) = tail; } @@ -785,9 +785,10 @@ void setDeferredReply(client *c, void *node, const char *s, size_t length) { listDelNode(c->reply,ln); } else { /* Create a new node */ - clientReplyBlock *buf = zmalloc(length + sizeof(clientReplyBlock)); + size_t usable_size; + clientReplyBlock *buf = zmalloc_usable(length + sizeof(clientReplyBlock), &usable_size); /* Take over the allocation's internal fragmentation */ - buf->size = zmalloc_usable_size(buf) - sizeof(clientReplyBlock); + buf->size = usable_size - sizeof(clientReplyBlock); buf->used = length; memcpy(buf->buf, s, length); listNodeValue(ln) = buf; @@ -872,6 +873,7 @@ void addReplyDouble(client *c, double d) { const int dlen = d2string(dbuf+7,sizeof(dbuf)-7,d); int digits = digits10(dlen); int start = 4 - digits; + serverAssert(start >= 0); dbuf[start] = '$'; /* Convert `dlen` to string, putting it's digits after '$' and before the @@ -1583,6 +1585,8 @@ void freeClient(client *c) { c->querybuf = NULL; /* Deallocate structures used to block on blocking ops. */ + /* If there is any in-flight command, we don't record their duration. */ + c->duration = 0; if (c->flags & CLIENT_BLOCKED) unblockClient(c, 1); dictRelease(c->bstate.keys); @@ -2039,8 +2043,10 @@ void resetClient(client *c) { c->multibulklen = 0; c->bulklen = -1; c->slot = -1; - c->duration = 0; c->flags &= ~CLIENT_EXECUTING_COMMAND; + + /* Make sure the duration has been recorded to some command. */ + serverAssert(c->duration == 0); #ifdef LOG_REQ_RES reqresReset(c, 1); #endif @@ -2337,6 +2343,9 @@ int processMultibulkBuffer(client *c) { /* Hint the sds library about the amount of bytes this string is * going to contain. */ c->querybuf = sdsMakeRoomForNonGreedy(c->querybuf,ll+2-sdslen(c->querybuf)); + /* We later set the peak to the used portion of the buffer, but here we over + * allocated because we know what we need, make sure it'll not be shrunk before used. */ + if (c->querybuf_peak < (size_t)ll + 2) c->querybuf_peak = ll + 2; } } c->bulklen = ll; @@ -2631,6 +2640,9 @@ void readQueryFromClient(connection *conn) { * the query buffer, we also don't wanna use the greedy growth, in order * to avoid collision with the RESIZE_THRESHOLD mechanism. */ c->querybuf = sdsMakeRoomForNonGreedy(c->querybuf, readlen); + /* We later set the peak to the used portion of the buffer, but here we over + * allocated because we know what we need, make sure it'll not be shrunk before used. */ + if (c->querybuf_peak < qblen + readlen) c->querybuf_peak = qblen + readlen; } else { c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); @@ -2997,6 +3009,10 @@ void clientCommand(client *c) { " Control the replies sent to the current connection.", "SETNAME <name>", " Assign the name <name> to the current connection.", +"SETINFO <option> <value>", +" Set client meta attr. Options are:", +" * LIB-NAME: the client lib name.", +" * LIB-VER: the client lib version.", "UNBLOCK <clientid> [TIMEOUT|ERROR]", " Unblock the specified blocked client.", "TRACKING (ON|OFF) [REDIRECT <id>] [BCAST] [PREFIX <prefix> [...]]", @@ -3606,7 +3622,13 @@ void securityWarningCommand(client *c) { time_t now = time(NULL); if (llabs(now-logged_time) > 60) { - serverLog(LL_WARNING,"Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted."); + char ip[NET_IP_STR_LEN]; + int port; + if (connAddrPeerName(c->conn, ip, sizeof(ip), &port) == -1) { + serverLog(LL_WARNING,"Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted."); + } else { + serverLog(LL_WARNING,"Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection from %s:%d aborted.", ip, port); + } logged_time = now; } freeClientAsync(c); @@ -3959,7 +3981,7 @@ void updatePausedActions(void) { /* Unblock all paused clients (ones that where blocked by BLOCKED_POSTPONE (possibly in processCommand). * This means they'll get re-processed in beforeSleep, and may get paused again if needed. */ -void unblockPostponedClients() { +void unblockPostponedClients(void) { listNode *ln; listIter li; listRewind(server.postponed_clients, &li); |