Cluster: sanity checks on the cluster bus message length.

This commit is contained in:
antirez 2013-02-15 16:44:39 +01:00
parent 6b9c661838
commit 02796ba7a7
2 changed files with 25 additions and 8 deletions

View File

@ -758,20 +758,33 @@ void clusterReadHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
ssize_t nread; ssize_t nread;
clusterMsg *hdr; clusterMsg *hdr;
clusterLink *link = (clusterLink*) privdata; clusterLink *link = (clusterLink*) privdata;
int readlen; int readlen, rcvbuflen;
REDIS_NOTUSED(el); REDIS_NOTUSED(el);
REDIS_NOTUSED(mask); REDIS_NOTUSED(mask);
again: again:
if (sdslen(link->rcvbuf) >= 4) { rcvbuflen = sdslen(link->rcvbuf);
hdr = (clusterMsg*) link->rcvbuf; if (rcvbuflen < 4) {
readlen = ntohl(hdr->totlen) - sdslen(link->rcvbuf); /* First, obtain the first four bytes to get the full message
* length. */
readlen = 4 - rcvbuflen;
} else { } else {
readlen = 4 - sdslen(link->rcvbuf); /* Finally read the full message. */
hdr = (clusterMsg*) link->rcvbuf;
if (rcvbuflen == 4) {
/* Perform some sanity check on the message length. */
if (ntohl(hdr->totlen) < CLUSTERMSG_MIN_LEN) {
redisLog(REDIS_WARNING,
"Bad message length received from Cluster bus.");
handleLinkIOError(link);
return;
}
}
readlen = ntohl(hdr->totlen) - rcvbuflen;
} }
nread = read(fd,buf,readlen); nread = read(fd,buf,readlen);
if (nread == -1 && errno == EAGAIN) return; /* Just no data */ if (nread == -1 && errno == EAGAIN) return; /* No more data ready. */
if (nread <= 0) { if (nread <= 0) {
/* I/O error... */ /* I/O error... */
@ -783,17 +796,19 @@ again:
/* Read data and recast the pointer to the new buffer. */ /* Read data and recast the pointer to the new buffer. */
link->rcvbuf = sdscatlen(link->rcvbuf,buf,nread); link->rcvbuf = sdscatlen(link->rcvbuf,buf,nread);
hdr = (clusterMsg*) link->rcvbuf; hdr = (clusterMsg*) link->rcvbuf;
rcvbuflen += nread;
} }
/* Total length obtained? read the payload now instead of burning /* Total length obtained? read the payload now instead of burning
* cycles waiting for a new event to fire. */ * cycles waiting for a new event to fire. */
if (sdslen(link->rcvbuf) == 4) goto again; if (rcvbuflen == 4) goto again;
/* Whole packet in memory? We can process it. */ /* Whole packet in memory? We can process it. */
if (sdslen(link->rcvbuf) == ntohl(hdr->totlen)) { if (rcvbuflen == ntohl(hdr->totlen)) {
if (clusterProcessPacket(link)) { if (clusterProcessPacket(link)) {
sdsfree(link->rcvbuf); sdsfree(link->rcvbuf);
link->rcvbuf = sdsempty(); link->rcvbuf = sdsempty();
rcvbuflen = 0; /* Useless line of code currently... defensive. */
} }
} }
} }

View File

@ -637,6 +637,8 @@ typedef struct {
union clusterMsgData data; union clusterMsgData data;
} clusterMsg; } clusterMsg;
#define CLUSTERMSG_MIN_LEN (sizeof(clusterMsg)-sizeof(union clusterMsgData))
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
* Global server state * Global server state
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/