From: Matthew Dillon Date: Wed, 6 Jun 2018 15:34:43 +0000 (-0700) Subject: cpdup - Fix NULL pointer indirection on lost socket X-Git-Tag: v5.5.0~536 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/8bf5b238b6869b07d32313f388d8d715ae7c284d cpdup - Fix NULL pointer indirection on lost socket * Fix a crash which can occur due to a lost socket. Generate a nice error message and exit() instead. --- diff --git a/bin/cpdup/hclink.c b/bin/cpdup/hclink.c index c0edf1cace..46198841ba 100644 --- a/bin/cpdup/hclink.c +++ b/bin/cpdup/hclink.c @@ -151,13 +151,15 @@ hcc_slave(int fdin, int fdout, struct HCDesc *descs, int count) struct HCHead * hcc_read_command(struct HostConf *hc, hctransaction_t trans) { - hctransaction_t fill; struct HCHead tmp; int aligned_bytes; int need_swap; int n; int r; + if (trans == NULL) + fatal("cpdup hlink protocol error with %s", hc->host); + n = 0; while (n < (int)sizeof(struct HCHead)) { r = read(hc->fdin, (char *)&tmp + n, sizeof(struct HCHead) - n); @@ -166,9 +168,9 @@ hcc_read_command(struct HostConf *hc, hctransaction_t trans) n += r; } - if (tmp.magic == HCMAGIC) + if (tmp.magic == HCMAGIC) { need_swap = 0; - else { + } else { tmp.magic = hc_bswap32(tmp.magic); if (tmp.magic != HCMAGIC) fatal("magic mismatch with %s (%04x)", hc->host, tmp.id); @@ -181,15 +183,12 @@ hcc_read_command(struct HostConf *hc, hctransaction_t trans) assert(tmp.bytes >= (int)sizeof(tmp) && tmp.bytes < HC_BUFSIZE); - if (!(fill = trans)) - fatal("cpdup hlink protocol error with %s (%04x)", hc->host, tmp.id); - - fill->swap = need_swap; - bcopy(&tmp, fill->rbuf, n); + trans->swap = need_swap; + bcopy(&tmp, trans->rbuf, n); aligned_bytes = HCC_ALIGN(tmp.bytes); while (n < aligned_bytes) { - r = read(hc->fdin, fill->rbuf + n, aligned_bytes - n); + r = read(hc->fdin, trans->rbuf + n, aligned_bytes - n); if (r <= 0) goto fail; n += r; @@ -197,9 +196,10 @@ hcc_read_command(struct HostConf *hc, hctransaction_t trans) #ifdef DEBUG hcc_debug_dump(trans, head); #endif - fill->state = HCT_REPLIED; - return((void *)fill->rbuf); + trans->state = HCT_REPLIED; + return((void *)trans->rbuf); fail: + trans->state = HCT_FAIL; return(NULL); } @@ -270,7 +270,7 @@ hcc_finish_command(hctransaction_t trans) errno = EIO; #endif if (whead->cmd < 0x0010) - return(NULL); + return(NULL); fatal("cpdup lost connection to %s", hc->host); } diff --git a/bin/cpdup/hclink.h b/bin/cpdup/hclink.h index 672d4821d7..89eb1acb3c 100644 --- a/bin/cpdup/hclink.h +++ b/bin/cpdup/hclink.h @@ -26,7 +26,7 @@ typedef struct HCTransaction { uint16_t id; /* assigned transaction id */ int swap; /* have to swap byte order */ int windex; /* output buffer index */ - enum { HCT_IDLE, HCT_SENT, HCT_REPLIED, HCT_DONE } state; + enum { HCT_IDLE, HCT_SENT, HCT_REPLIED, HCT_DONE, HCT_FAIL } state; } *hctransaction_t; struct HostConf { diff --git a/bin/cpdup/hcproto.c b/bin/cpdup/hcproto.c index 6424074ad6..3a29504d6c 100644 --- a/bin/cpdup/hcproto.c +++ b/bin/cpdup/hcproto.c @@ -510,6 +510,8 @@ hc_readdir(struct HostConf *hc, DIR *dir, struct stat **statpp) free(*statpp); *statpp = NULL; } + if (hc->trans.state == HCT_FAIL) + return NULL; return (denbuf.d_name[0] ? &denbuf : NULL); } @@ -569,7 +571,7 @@ hc_closedir(struct HostConf *hc, DIR *dir) /* skip any remaining items if the directory is closed prematurely */ while (hcc_nextchaineditem(hc, head) != NULL) /*nothing*/ ; - if (head->error) + if (hc->trans.state == HCT_FAIL || head->error) return (-1); return (0); } @@ -782,7 +784,7 @@ hc_close(struct HostConf *hc, int fd) /* skip any remaining items if the file is closed prematurely */ while (hcc_nextchaineditem(hc, head) != NULL) /*nothing*/ ; - if (head->error) + if (hc->trans.state == HCT_FAIL || head->error) return (-1); return (0); } @@ -852,12 +854,16 @@ hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes) if (fd == 1 && hc->version >= 4) { /* using HC_READFILE */ head = (void *)hc->trans.rbuf; while (bytes) { - if ((offset = head->magic) != 0) + if ((offset = head->magic) != 0) { item = hcc_currentchaineditem(hc, head); - else + } else { item = hcc_nextchaineditem(hc, head); - if (item == NULL) + } + if (item == NULL) { + if (hc->trans.state == HCT_FAIL) + r = -1; return (r); + } if (item->leafid != LC_DATA) return (-1); x = item->bytes - sizeof(*item) - offset;