diff options
| author | Dan McDonald <danmcd@joyent.com> | 2021-02-22 11:23:05 -0500 |
|---|---|---|
| committer | Dan McDonald <danmcd@joyent.com> | 2021-02-22 11:23:05 -0500 |
| commit | 68f8cc88139189fdc033b24b48588c2e47ffe60e (patch) | |
| tree | 4908720aeab0a41997eda2ba56bb456aa41d172f /usr/src/lib/libzfs | |
| parent | 3e2541c04964508e92c825796649f5cd5f8bf299 (diff) | |
| parent | 6859ab0054a96093394fe85f055fac9cf93b38ee (diff) | |
| download | illumos-joyent-68f8cc88139189fdc033b24b48588c2e47ffe60e.tar.gz | |
[illumos-gate merge]
commit 6859ab0054a96093394fe85f055fac9cf93b38ee
13557 pf[k]sh fails to properly resolve paths (missing diffs)
commit 944411b5616a6d498985ec4579bd6448b8baacfe
13557 pf[k]sh fails to properly resolve paths
commit 56ffda179176d14e2fb160bdc85f6da601f1eac7
13559 remove lingering references to usr/closed
commit 3aa6c13072f3d4792a18693e916aed260a496c1f
13558 remove support for optional subdirectories in the build
commit 1f0845f1dfb179d6aa598ad89bb44d432f4e1020
13515 panic with bad mutex in smb_ofile_hold_olbrk
commit 174aa483b26ab13af096f2d478f7c15afdaf9784
13514 smbsrv panic in smb2_dh_read_nvlist
commit 8bf842e01303492318712f55e3f715097c4df992
13561 nfs: implicit conversion from 'enum nfsstat4' to 'enum clnt_stat'
commit 0189c0b054f5460e8b23f56112cd0763c993cd05
13523 libsmbns: symbol 'smb_node_type' is multiply-defined
commit c5286370b84c690a18e8100a5237a1000d7e29c6
6729 incremental replication stream of a fs tree with lots of snapshots trips assert in zfs recv
Diffstat (limited to 'usr/src/lib/libzfs')
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_impl.h | 1 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_sendrecv.c | 46 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_util.c | 16 |
3 files changed, 60 insertions, 3 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h index bca1fc8a93..bec66afc5a 100644 --- a/usr/src/lib/libzfs/common/libzfs_impl.h +++ b/usr/src/lib/libzfs/common/libzfs_impl.h @@ -95,6 +95,7 @@ struct libzfs_handle { boolean_t libzfs_prop_debug; di_devlink_handle_t libzfs_devlink; regex_t libzfs_urire; + uint64_t libzfs_max_nvlist; }; struct zfs_handle { 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; diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c index 3ccefa5585..5e24635179 100644 --- a/usr/src/lib/libzfs/common/libzfs_util.c +++ b/usr/src/lib/libzfs/common/libzfs_util.c @@ -714,6 +714,8 @@ libzfs_handle_t * libzfs_init(void) { libzfs_handle_t *hdl; + int error; + char *env; if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) { return (NULL); @@ -757,6 +759,20 @@ libzfs_init(void) if (getenv("ZFS_PROP_DEBUG") != NULL) { hdl->libzfs_prop_debug = B_TRUE; } + if ((env = getenv("ZFS_SENDRECV_MAX_NVLIST")) != NULL) { + if ((error = zfs_nicestrtonum(hdl, env, + &hdl->libzfs_max_nvlist))) { + errno = error; + (void) close(hdl->libzfs_fd); + (void) fclose(hdl->libzfs_mnttab); + (void) fclose(hdl->libzfs_sharetab); + regfree(&hdl->libzfs_urire); + free(hdl); + return (NULL); + } + } else { + hdl->libzfs_max_nvlist = (SPA_MAXBLOCKSIZE * 4); + } return (hdl); } |
