diff options
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_sendrecv.c')
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_sendrecv.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c index 2bfb49875d..7bdea7dc55 100644 --- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c +++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c @@ -929,6 +929,18 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) nvlist_free(sd->snapprops); nvlist_free(sd->snapholds); + /* Do not allow the size of the properties list to exceed the limit */ + if ((fnvlist_size(nvfs) + fnvlist_size(sd->fss)) > + zhp->zfs_hdl->libzfs_max_nvlist) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "warning: cannot send %s@%s: the size of the list of " + "snapshots and properties is too large to be received " + "successfully.\n" + "Select a smaller number of snapshots to send.\n"), + zhp->zfs_name, sd->tosnap); + rv = EZFS_NOSPC; + goto out; + } /* add this fs to nvlist */ (void) snprintf(guidstring, sizeof (guidstring), "0x%llx", (longlong_t)guid); @@ -1926,8 +1938,31 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, flags->verbose, flags->backup, flags->holds, flags->props, &fss, &fsavl); - if (err) + if (err) { + nvlist_free(hdrnv); + goto err_out; + } + + /* + * Do not allow the size of the properties list to + * exceed the limit + */ + if ((fnvlist_size(fss) + fnvlist_size(hdrnv)) > + zhp->zfs_hdl->libzfs_max_nvlist) { + (void) snprintf(errbuf, sizeof (errbuf), + dgettext(TEXT_DOMAIN, + "warning: cannot send '%s': " + "the size of the list of snapshots and " + "properties is too large to be received " + "successfully.\n" + "Select a smaller number of snapshots to " + "send.\n"), + zhp->zfs_name); + nvlist_free(hdrnv); + err = zfs_error(zhp->zfs_hdl, EZFS_NOSPC, + errbuf); goto err_out; + } VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss)); err = nvlist_pack(hdrnv, &packbuf, &buflen, NV_ENCODE_XDR, 0); @@ -2198,8 +2233,6 @@ recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen, int rv; int len = ilen; - assert(ilen <= SPA_MAXBLOCKSIZE); - do { rv = read(fd, cp, len); cp += rv; @@ -2233,6 +2266,12 @@ recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp, if (buf == NULL) return (ENOMEM); + if (len > hdl->libzfs_max_nvlist) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "nvlist too large")); + free(buf); + return (ENOMEM); + } + err = recv_read(hdl, fd, buf, len, byteswap, zc); if (err != 0) { free(buf); @@ -3325,6 +3364,7 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap) } uint64_t payload_size = DRR_WRITE_PAYLOAD_SIZE(&drr->drr_u.drr_write); + assert(payload_size <= SPA_MAXBLOCKSIZE); (void) recv_read(hdl, fd, buf, payload_size, B_FALSE, NULL); break; |
