--- a/usr/src/lib/libzfs/common/libzfs.h Thu Sep 18 16:14:35 2008 +0100
+++ b/usr/src/lib/libzfs/common/libzfs.h Thu Sep 18 16:15:30 2008 +0100
@@ -357,6 +357,10 @@
extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
extern int zfs_crypto_create(libzfs_handle_t *, nvlist_t *, const char *path,
struct zfs_cmd *);
+extern int zfs_crypto_clone(libzfs_handle_t *, const char *target,
+ const char *parent);
+extern int zfs_crypto_rename(libzfs_handle_t *, const char *target,
+ const char *parent);
extern int zpool_crypto_create(libzfs_handle_t *, nvlist_t *, struct zfs_cmd *);
extern int valid_keysource(char *);
extern int valid_set_keysource_change(zfs_crypt_t *, char *, char *);
--- a/usr/src/lib/libzfs/common/libzfs_crypto.c Thu Sep 18 16:14:35 2008 +0100
+++ b/usr/src/lib/libzfs/common/libzfs_crypto.c Thu Sep 18 16:15:30 2008 +0100
@@ -1387,6 +1387,79 @@
return (keysource_prop_parser(src, &format, &locator, &uri));
}
+/*
+ * zfs_crypto_clone/zfs_crypto_rename
+ *
+ * Validate that the clone/rename is okay to place in the tree at that
+ * location.
+ *
+ * Just like we don't allow an encryption=off dataset to be created below
+ * and encrypted one we shouldn't allow a clone of an encryption=off dataset
+ * to be placed below an encrypted dataset either.
+ *
+ * If in the future we allow clones to have different keys from their
+ * parents some key setup may be required in here and zfs_crypto_rename
+ * will likely need split off.
+ */
+#pragma weak zfs_crypto_rename = zfs_crypto_clone
+int
+zfs_crypto_clone(libzfs_handle_t *hdl, const char *snapshot, const char *parent)
+{
+ int ret = 0;
+ zfs_handle_t *pzhp = NULL, *szhp = NULL;
+ uint64_t pcrypt = ZIO_CRYPT_INHERIT, scrypt = ZIO_CRYPT_INHERIT;
+
+ ASSERT(snapshot != NULL);
+ ASSERT(parent != NULL);
+
+ do {
+ pzhp = make_dataset_handle(hdl, parent);
+ if (pzhp == NULL) {
+ break;
+ }
+ pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION);
+ } while (pcrypt == ZIO_CRYPT_INHERIT);
+
+ if (pcrypt == ZIO_CRYPT_INHERIT) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "failed to obtain parent encryption value."));
+ ret = -1;
+ goto out;
+ }
+
+ do {
+ szhp = make_dataset_handle(hdl, snapshot);
+ if (szhp == NULL) {
+ break;
+ }
+ scrypt = zfs_prop_get_int(szhp, ZFS_PROP_ENCRYPTION);
+ } while (scrypt == ZIO_CRYPT_INHERIT);
+
+ if (scrypt == ZIO_CRYPT_INHERIT) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "failed to obtain source encryption value."));
+ ret = -1;
+ goto out;
+ }
+
+ ASSERT(scrypt != ZIO_CRYPT_INHERIT);
+ ASSERT(pcrypt != ZIO_CRYPT_INHERIT);
+
+ if (pcrypt != ZIO_CRYPT_OFF && scrypt == ZIO_CRYPT_OFF) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "source must be encrypted."));
+ ret = -1;
+ }
+out:
+ if (pzhp != NULL) {
+ zfs_close(pzhp);
+ }
+ if (szhp != NULL) {
+ zfs_close(szhp);
+ }
+
+ return (ret);
+}
/*
* zfs_crypto_create
@@ -1520,7 +1593,7 @@
keysource = malloc(ZFS_MAXNAMELEN);
if (keysource == NULL) {
- (void) fprintf(stderr, "Error in keysource malloc.");
+ no_memory(hdl);
return (-1);
}
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c Thu Sep 18 16:14:35 2008 +0100
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c Thu Sep 18 16:15:30 2008 +0100
@@ -1984,7 +1984,8 @@
break;
case ERANGE:
- if (prop == ZFS_PROP_COMPRESSION) {
+ if (prop == ZFS_PROP_COMPRESSION ||
+ prop == ZFS_PROP_ENCRYPTION) {
(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"property setting is not allowed on "
"bootable datasets"));
@@ -3368,6 +3369,8 @@
nvlist_free(props);
}
+ if (zfs_crypto_clone(hdl, zhp->zfs_name, parent) != 0)
+ return (zfs_error(hdl, EZFS_KEYERR, errbuf));
(void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
@@ -4013,6 +4016,9 @@
else
zc.zc_objset_type = DMU_OST_ZFS;
+ if (zfs_crypto_rename(hdl, zhp->zfs_name, parent) != 0)
+ return (zfs_error(hdl, EZFS_KEYERR, errbuf));
+
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));