diff options
author | Ryan Moeller <[email protected]> | 2020-03-18 15:54:12 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-18 12:54:12 -0700 |
commit | 22df2457a7b8265d999a2fe48f3e8e941c8fdde5 (patch) | |
tree | 78a33a544b885b5cdbfcff1d2c7c16c44e35f529 /lib | |
parent | 4df8b2c3739c50be2e0a5aa5b6d0d131e8b8e3f3 (diff) |
Avoid core dump on invalid redaction bookmark
libzfs aborts and dumps core on EINVAL from the kernel when trying to
do a redacted send with a bookmark that is not a redaction bookmark.
Move redacted bookmark validation into libzfs.
Check if the bookmark given for redactions is actually a redaction
bookmark. Print an error message and exit gracefully if it is not.
Don't abort on EINVAL in zfs_send_one.
Reviewed-by: Paul Dagnelie <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Ryan Moeller <[email protected]>
Closes #10138
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs_sendrecv.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 457154171..ce6a2737b 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -2816,6 +2816,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, { int err; libzfs_handle_t *hdl = zhp->zfs_hdl; + char *name = zhp->zfs_name; int orig_fd = fd; pthread_t ddtid, ptid; progress_arg_t pa = { 0 }; @@ -2823,7 +2824,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, char errbuf[1024]; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, - "warning: cannot send '%s'"), zhp->zfs_name); + "warning: cannot send '%s'"), name); if (from != NULL && strchr(from, '@')) { zfs_handle_t *from_zhp = zfs_open(hdl, from, @@ -2839,6 +2840,44 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, zfs_close(from_zhp); } + if (redactbook != NULL) { + char bookname[ZFS_MAX_DATASET_NAME_LEN]; + nvlist_t *redact_snaps; + zfs_handle_t *book_zhp; + char *at, *pound; + int dsnamelen; + + pound = strchr(redactbook, '#'); + if (pound != NULL) + redactbook = pound + 1; + at = strchr(name, '@'); + if (at == NULL) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "cannot do a redacted send to a filesystem")); + return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); + } + dsnamelen = at - name; + if (snprintf(bookname, sizeof (bookname), "%.*s#%s", + dsnamelen, name, redactbook) + >= sizeof (bookname)) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "invalid bookmark name")); + return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); + } + book_zhp = zfs_open(hdl, bookname, ZFS_TYPE_BOOKMARK); + if (book_zhp == NULL) + return (-1); + if (nvlist_lookup_nvlist(book_zhp->zfs_props, + zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS), + &redact_snaps) != 0 || redact_snaps == NULL) { + zfs_close(book_zhp); + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "not a redaction bookmark")); + return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); + } + zfs_close(book_zhp); + } + /* * Send fs properties */ @@ -2909,7 +2948,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, } } - err = lzc_send_redacted(zhp->zfs_name, from, fd, + err = lzc_send_redacted(name, from, fd, lzc_flags_from_sendflags(flags), redactbook); if (flags->progress) { @@ -2948,7 +2987,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, case ENOENT: case ESRCH: - if (lzc_exists(zhp->zfs_name)) { + if (lzc_exists(name)) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "incremental source (%s) does not exist"), from); @@ -2967,7 +3006,9 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, return (zfs_error(hdl, EZFS_BUSY, errbuf)); case EDQUOT: + case EFAULT: case EFBIG: + case EINVAL: case EIO: case ENOLINK: case ENOSPC: @@ -2975,7 +3016,6 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, case ENXIO: case EPIPE: case ERANGE: - case EFAULT: case EROFS: zfs_error_aux(hdl, strerror(errno)); return (zfs_error(hdl, EZFS_BADBACKUP, errbuf)); |