diff options
author | Milan Broz <mbroz@redhat.com> | 2011-09-16 14:40:06 +0000 |
---|---|---|
committer | Milan Broz <mbroz@redhat.com> | 2011-09-16 14:40:06 +0000 |
commit | 63b8ed7c37d166efd6f7e24bad8f64a2bc3239ef (patch) | |
tree | 47bf5cd1ae6f581e4dcd7877d1e8830922b71c21 /daemons/clvmd | |
parent | 5170efd1ee2ca80bbfcaa36b5e6801de53c3b3c3 (diff) | |
download | lvm2-63b8ed7c37d166efd6f7e24bad8f64a2bc3239ef.tar.gz lvm2-63b8ed7c37d166efd6f7e24bad8f64a2bc3239ef.tar.xz lvm2-63b8ed7c37d166efd6f7e24bad8f64a2bc3239ef.zip |
Fix clvmd processing of invalid request on local socket. (rommer)
Code now detects small packet and wrong arglen and reply with
error intead of infinite loop.
https://bugzilla.redhat.com/show_bug.cgi?id=738484
Diffstat (limited to 'daemons/clvmd')
-rw-r--r-- | daemons/clvmd/clvmd.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c index 02994ef2..3fef68c8 100644 --- a/daemons/clvmd/clvmd.c +++ b/daemons/clvmd/clvmd.c @@ -1061,6 +1061,7 @@ static int read_from_local_sock(struct local_client *thisfd) int missing_len; char buffer[PIPE_BUF]; + memset(buffer, 0, PIPE_BUF); len = read(thisfd->fd, buffer, sizeof(buffer)); if (len == -1 && errno == EINTR) return 1; @@ -1169,9 +1170,6 @@ static int read_from_local_sock(struct local_client *thisfd) return len; } - /* Free any old buffer space */ - free(thisfd->bits.localsock.cmd); - /* See if we have the whole message */ argslen = len - strlen(inheader->node) - sizeof(struct clvm_header); @@ -1180,6 +1178,22 @@ static int read_from_local_sock(struct local_client *thisfd) if (missing_len < 0) missing_len = 0; + /* We need at least sizeof(struct clvm_header) bytes in buffer */ + if (len < sizeof(struct clvm_header) || argslen < 0) { + struct clvm_header reply; + reply.cmd = CLVMD_CMD_REPLY; + reply.status = EINVAL; + reply.arglen = 0; + reply.flags = 0; + send_message(&reply, sizeof(reply), our_csid, + thisfd->fd, + "Error sending EINVAL reply to local user"); + return 0; + } + + /* Free any old buffer space */ + free(thisfd->bits.localsock.cmd); + /* Save the message */ thisfd->bits.localsock.cmd = malloc(len + missing_len); @@ -1203,15 +1217,23 @@ static int read_from_local_sock(struct local_client *thisfd) char *argptr = inheader->node + strlen(inheader->node) + 1; - while (missing_len > 0 && len >= 0) { + while (missing_len > 0) { DEBUGLOG ("got %d bytes, need another %d (total %d)\n", argslen, missing_len, inheader->arglen); len = read(thisfd->fd, argptr + argslen, missing_len); - if (len >= 0) { + if (len == -1 && errno == EINTR) + continue; + if (len > 0) { missing_len -= len; argslen += len; + } else { + /* EOF or error on socket */ + DEBUGLOG("EOF on local socket\n"); + free(thisfd->bits.localsock.cmd); + thisfd->bits.localsock.cmd = NULL; + return 0; } } } |