summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzfs
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2021-02-22 11:23:05 -0500
committerDan McDonald <danmcd@joyent.com>2021-02-22 11:23:05 -0500
commit68f8cc88139189fdc033b24b48588c2e47ffe60e (patch)
tree4908720aeab0a41997eda2ba56bb456aa41d172f /usr/src/lib/libzfs
parent3e2541c04964508e92c825796649f5cd5f8bf299 (diff)
parent6859ab0054a96093394fe85f055fac9cf93b38ee (diff)
downloadillumos-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.h1
-rw-r--r--usr/src/lib/libzfs/common/libzfs_sendrecv.c46
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c16
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);
}