Module Name:    src
Committed By:   martin
Date:           Fri Oct 11 08:54:39 UTC 2024

Modified Files:
        src/sbin/cgdconfig [netbsd-10]: Makefile cgdconfig.8 cgdconfig.c
            params.c params.h

Log Message:
Pull up following revision(s) (requested by riastradh in ticket #941):

        sbin/cgdconfig/params.c: revision 1.35
        sbin/cgdconfig/params.h: revision 1.15
        sbin/cgdconfig/cgdconfig.c: revision 1.62
        sbin/cgdconfig/cgdconfig.c: revision 1.63
        sbin/cgdconfig/cgdconfig.8: revision 1.58
        sbin/cgdconfig/cgdconfig.8: revision 1.59
        sbin/cgdconfig/Makefile: revision 1.23

cgdconfig(8): KNF in cgdconfig.c.
No functional change intended.

PR/58212: Malte Dehling: Add zfs verification method

cgdconfig(8): Estimate verify methods' false accept probabilities.
An addendum following discussion around:
PR bin/58212: cgdconfig(8): Add zfs verification method


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.22.2.1 src/sbin/cgdconfig/Makefile
cvs rdiff -u -r1.57 -r1.57.2.1 src/sbin/cgdconfig/cgdconfig.8
cvs rdiff -u -r1.61 -r1.61.2.1 src/sbin/cgdconfig/cgdconfig.c
cvs rdiff -u -r1.34 -r1.34.2.1 src/sbin/cgdconfig/params.c
cvs rdiff -u -r1.14 -r1.14.2.1 src/sbin/cgdconfig/params.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/cgdconfig/Makefile
diff -u src/sbin/cgdconfig/Makefile:1.22 src/sbin/cgdconfig/Makefile:1.22.2.1
--- src/sbin/cgdconfig/Makefile:1.22	Fri Aug 12 10:49:17 2022
+++ src/sbin/cgdconfig/Makefile	Fri Oct 11 08:54:39 2024
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.22 2022/08/12 10:49:17 riastradh Exp $
+# $NetBSD: Makefile,v 1.22.2.1 2024/10/11 08:54:39 martin Exp $
 
 RUMPPRG=cgdconfig
 MAN=	cgdconfig.8
@@ -29,4 +29,19 @@ ARGON2_NO_THREADS=1
 .include "${NETBSDSRCDIR}/external/apache2/argon2/lib/libargon2/Makefile.inc"
 .endif
 
+.if ${MKZFS} != "no"
+CPPFLAGS+=	-DHAVE_ZFS
+
+OSNET=${NETBSDSRCDIR}/external/cddl/osnet
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/include
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/sys
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/head
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/lib/libzpool/common
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/uts/common
+CPPFLAGS.cgdconfig.c+=	-I${OSNET}/dist/uts/common/fs/zfs
+
+COPTS.cgdconfig.c+=	-Wno-unknown-pragmas
+COPTS.cgdconfig.c+=	-Wno-strict-prototypes
+.endif
+
 .include <bsd.prog.mk>

Index: src/sbin/cgdconfig/cgdconfig.8
diff -u src/sbin/cgdconfig/cgdconfig.8:1.57 src/sbin/cgdconfig/cgdconfig.8:1.57.2.1
--- src/sbin/cgdconfig/cgdconfig.8:1.57	Fri Aug 12 10:49:47 2022
+++ src/sbin/cgdconfig/cgdconfig.8	Fri Oct 11 08:54:39 2024
@@ -1,4 +1,4 @@
-.\" $NetBSD: cgdconfig.8,v 1.57 2022/08/12 10:49:47 riastradh Exp $
+.\" $NetBSD: cgdconfig.8,v 1.57.2.1 2024/10/11 08:54:39 martin Exp $
 .\"
 .\" Copyright (c) 2002, The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 4, 2021
+.Dd May 12, 2024
 .Dt CGDCONFIG 8
 .Os
 .Sh NAME
@@ -270,12 +270,115 @@ scan for a valid Master Boot Record.
 scan for a valid GUID partition table.
 .It ffs
 scan for a valid FFS file system.
+.It zfs
+scan for a valid ZFS vdev label (if compiled with MKZFS).
 .It re-enter
 prompt for passphrase twice, and ensure entered passphrases are
 identical.
 This method only works with the argon2id, pkcs5_pbkdf2/sha1, and
 pkcs5_pbkdf2 key generators.
 .El
+.Pp
+If a wrong key is generated, e.g. if the passphrase is entered
+incorrectly, the disk content will appear to be randomized.
+Assuming uniform random disk content, each verification method has some
+probability of falsely accepting a wrong key anyway.
+The probability for each method is as follows:
+.Bl -column "disklabel" "matching \*(Ge160-bit hashes" "1 - (1 - 1/2^80)^1946 < 1/6e20"
+.It Sy method Ta Sy verifies Ta Sy "P(false accept)"
+.It Li none Ta No nothing Ta "1" Ta
+.\" disklabel:
+.\" - scans SCANSIZE=8192 bytes with disklabel_scan, which...
+.\" - checks {0, 4, 8, 12, ..., SCANSIZE=8192 - sizeof(struct
+.\"   disklabel)=408}, 1946 options total, for a matching 64-bit
+.\"   quantity (d_magic=DISKMAGIC, d_magic2=DISKMAGIC) plus a matching
+.\"   16-bit cksum (plus a plausible d_npartitions but let's ignore
+.\"   that)
+.\" Pr[false accept] = Pr[exists i. scan[i] matches 80-bit magic/cksum]
+.\"   = 1 - Pr[not exists i. scan[i] does not match 80-bit magic/cksum]
+.\"   = 1 - Pr[forall i. scan[i] does not match 80-bit magic/cksum]
+.\"   = 1 - \prod_i Pr[scan[i] does not match 80-bit magic/cksum]
+.\"   = 1 - \prod_i (1 - Pr[scan[i] matches 80-bit magic/cksum])
+.\"   = 1 - \prod_i (1 - 1/2^80)
+.\"   = 1 - (1 - 1/2^80)^1946
+.\"   = 1 - exp(1946*log(1 - 1/2^80))
+.\"   = -expm1(1946*log1p(-1/2^80))
+.\"  <= 1/621e18 <= 1/6e20 (one in six hundred quintillion)
+.It Li disklabel Ta No 64-bit magic strings w/16-bit cksum in any of 1946 places Ta "1 - (1 - 1/2^80)^1946 < 1/6e20"
+.\" mbr:
+.\" - checks exactly one location
+.\" - checks for exactly one magic 16-bit constant
+.\" Pr[false accept] = 1/2^16 = 1/65536
+.It Li mbr Ta No 16-bit magic string Ta "1/65536"
+.\" gpt:
+.\" - scans SCANSIZE=8192 bytes
+.\" - checks blksizes DEV_BSIZE=512, 1024, 2048, 4096
+.\" - checks for 64-bit sig, 32-bit rev, 32-bit size, 32-bit cksum
+.\" Pr[false accept]
+.\"   = Pr[exists blksz. hdr[blksz] matches 160-bit magic/cksum]
+.\"   = 1 - Pr[not exists blksz. hdr[blksz] matches 160-bit magic/cksum]
+.\"   = 1 - Pr[forall blksz. hdr[blksz] does not match 160-bit magic/cksum]
+.\"   = 1 - \prod_blksz Pr[hdr[blksz] does not match 160-bit magic/cksum]
+.\"   = 1 - \prod_blksz (1 - Pr[hdr[blksz] matches 160-bit magic/cksum])
+.\"   = 1 - \prod_blksz (1 - 1/2^160)
+.\"   = 1 - (1 - 1/2^160)^4
+.\"   = 1 - exp(4*log(1 - 1/2^160))
+.\"   = -expm1(4*log1p(-1/2^160))
+.\"  <= 1/3e47
+.It Li gpt Ta No 128-bit magic string w/32-bit cksum in any of 4 places Ta "1 - (1 - 1/2^160)^4 < 1/3e47" Ta
+.\" ffs:
+.\" - checks four locations in SBLOCKSEARCH (sblock_try)
+.\" - checks for any of six magic 32-bit constants
+.\" Pr[false accept] = Pr[exists i. sblock_try[i] in {magic[0], ..., magic[5]}]
+.\"   = 1 - Pr[not exists i. sblock_try[i] in {magic[0], ..., magic[5]}]
+.\"   = 1 - Pr[forall i. sblock_try[i] not in {magic[0], ..., magic[5]}]
+.\"   = 1 - \prod_i Pr[sblock_try[i] not in {magic[0], ..., magic[5]}]
+.\"   = 1 - \prod_i (1 - Pr[sblock_try[i] in {magic[0], ..., magic[5]}])
+.\"   = 1 - \prod_i (1 - 6/2^32)
+.\"   = 1 - (1 - 6/2^32)^4
+.\"   = 1 - exp(4*log(1 - 6/2^32))
+.\"   = -expm1(4*log1p(-6/2^32))
+.\"  <= 1/178e6 <= 1/1e8 (one in a hundred million)
+.It Li ffs Ta No any of 6 32-bit magic strings in any of 4 places Ta "1 - (1 - 6/2^32)^4 < 1/1e8" Ta
+.\" zfs:
+.\" - checks four locations (VDEV_LABELS)
+.\" - checks for any of two magic 64-bit constants (ZEC_MAGIC or bswap)
+.\" - checks for 256-bit SHA256 hash
+.\" Pr[false accept] = Pr[exists i. label[i] matches 320-bit magic/cksum]
+.\"   = 1 - Pr[not exists i. label[i] matches 320-bit magic/cksum]
+.\"   = 1 - Pr[forall i. label[i] does not match 320-bit magic/cksum]
+.\"   = 1 - \prod_i Pr[label[i] does not match 320-bit magic/cksum]
+.\"   = 1 - \prod_i (1 - Pr[label[i] does matches 320-bit magic/cksum])
+.\"   = 1 - \prod_i (1 - 2/2^230)
+.\"   = 1 - (1 - 2/2^230)^4
+.\"   = -expm1(4*log1p(-2/2^230))
+.\"  <= 1/2e68
+.It Li zfs Ta No any of 2 64-bit magic strings w/256-bit cksum in any of 4 places Ta "1 - (1 - 2/2^320)^4 < 1/1e68"
+.\" re-enter:
+.\" - checks whether >=160-bit hash matches
+.\" Pr[false accept] = Pr[H(pw1) = H(pw2) | pw1 != pw2] <= 1/2^160 < 1/1e48
+.It Li re-enter Ta No matching \*(Ge160-bit hashes Ta "\*(Le 1/2^160 < 1/1e48"
+.El
+.Pp
+Note that aside from the
+.Ql none
+method, which accepts any key unconditionally, the
+.Ql mbr
+method and to a lesser extent the
+.Ql ffs
+method also accept a wrong key with a much higher probability than
+cryptography normally deals in.
+.Pp
+This is not a security vulnerability in the confidentiality of
+.Xr cgd 4
+against an adversary, but it may be alarming for a user if a disk is
+configured with a mistyped passphrase,
+.Nm
+.Em accepts the wrong key ,
+and the content appears to be garbage \(em for example, fsck may fail
+with scary warnings, and any writes to the disk configured with the
+wrong key will corrupt the original plaintext content under the right
+key.
 .Ss /etc/cgd/cgd.conf
 The file
 .Pa /etc/cgd/cgd.conf

Index: src/sbin/cgdconfig/cgdconfig.c
diff -u src/sbin/cgdconfig/cgdconfig.c:1.61 src/sbin/cgdconfig/cgdconfig.c:1.61.2.1
--- src/sbin/cgdconfig/cgdconfig.c:1.61	Thu Nov 17 06:40:38 2022
+++ src/sbin/cgdconfig/cgdconfig.c	Fri Oct 11 08:54:39 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: cgdconfig.c,v 1.61 2022/11/17 06:40:38 chs Exp $ */
+/* $NetBSD: cgdconfig.c,v 1.61.2.1 2024/10/11 08:54:39 martin Exp $ */
 
 /*-
  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 #ifndef lint
 __COPYRIGHT("@(#) Copyright (c) 2002, 2003\
  The NetBSD Foundation, Inc.  All rights reserved.");
-__RCSID("$NetBSD: cgdconfig.c,v 1.61 2022/11/17 06:40:38 chs Exp $");
+__RCSID("$NetBSD: cgdconfig.c,v 1.61.2.1 2024/10/11 08:54:39 martin Exp $");
 #endif
 
 #ifdef HAVE_ARGON2
@@ -73,6 +73,11 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.61 202
 
 #include <ufs/ffs/fs.h>
 
+#ifdef HAVE_ZFS
+#include <sys/vdev_impl.h>
+#include <sha2.h>
+#endif
+
 #include "params.h"
 #include "pkcs5_pbkdf2.h"
 #include "utils.h"
@@ -98,11 +103,11 @@ enum action {
 
 /* if nflag is set, do not configure/unconfigure the cgd's */
 
-int	nflag = 0;
+static int	nflag = 0;
 
 /* if Sflag is set, generate shared keys */
 
-int	Sflag = 0;
+static int	Sflag = 0;
 
 /* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */
 
@@ -110,7 +115,7 @@ int	Sflag = 0;
 #define	PFLAG_GETPASS_ECHO	0x02
 #define	PFLAG_GETPASS_MASK	0x03
 #define	PFLAG_STDIN		0x04
-int	pflag = PFLAG_GETPASS;
+static int	pflag = PFLAG_GETPASS;
 
 /*
  * When configuring all cgds, save a cache of shared keys for key
@@ -127,7 +132,7 @@ struct sharedkey {
 	SLIST_ENTRY(sharedkey)	 used;
 	int			 verified;
 };
-LIST_HEAD(, sharedkey) sharedkeys;
+static LIST_HEAD(, sharedkey) sharedkeys;
 SLIST_HEAD(sharedkeyhits, sharedkey);
 
 static int	configure(int, char **, struct params *, int);
@@ -170,11 +175,14 @@ static int	 verify_ffs(int);
 static int	 verify_reenter(struct params *);
 static int	 verify_mbr(int);
 static int	 verify_gpt(int);
+#ifdef HAVE_ZFS
+static int	 verify_zfs(int);
+#endif
 
 __dead static void	 usage(void);
 
 /* Verbose Framework */
-unsigned	verbose = 0;
+static unsigned	verbose = 0;
 
 #define VERBOSE(x,y)	if (verbose >= x) y
 #define VPRINTF(x,y)	if (verbose >= x) (void)printf y
@@ -636,12 +644,12 @@ getkey_argon2id(const char *target, stru
 	char *passp;
 	char buf[1024];
 	uint8_t	raw[256];
-	int err;
+	int error;
 
 	snprintf(buf, sizeof(buf), "%s's passphrase%s:", target,
 	    pflag & PFLAG_GETPASS_ECHO ? " (echo)" : "");
 	passp = maybe_getpass(buf);
-	if ((err = argon2_hash(kg->kg_iterations, kg->kg_memory,
+	if ((error = argon2_hash(kg->kg_iterations, kg->kg_memory,
 	    kg->kg_parallelism,
 	    passp, strlen(passp),
 	    bits_getbuf(kg->kg_salt),
@@ -649,7 +657,7 @@ getkey_argon2id(const char *target, stru
 	    raw, sizeof(raw),
 	    NULL, 0,
 	    Argon2_id, kg->kg_version)) != ARGON2_OK) {
-		warnx("failed to generate Argon2id key, error code %d", err);
+		warnx("failed to generate Argon2id key, error code %d", error);
 		return NULL;
 	}
 
@@ -1024,6 +1032,10 @@ verify(struct params *p, int fd)
 		return verify_mbr(fd);
 	case VERIFY_GPT:
 		return verify_gpt(fd);
+#ifdef HAVE_ZFS
+	case VERIFY_ZFS:
+		return verify_zfs(fd);
+#endif
 	default:
 		warnx("unimplemented verification method");
 		return -1;
@@ -1161,7 +1173,6 @@ verify_gpt(int fd)
 		return -1;
 	}
 
-	ret = 1;
 	for (blksize = DEV_BSIZE;
              (off = (blksize * GPT_HDR_BLKNO)) <= SCANSIZE - sizeof(hdr);
              blksize <<= 1) {
@@ -1173,15 +1184,114 @@ verify_gpt(int fd)
 
 			hdr.hdr_crc_self = 0;
 			if (crc32(&hdr, sizeof(hdr))) {
-				ret = 0;
-				break;
+				return 0;
 			}
 		}
 	}
 
-	return ret;
+	return 1;
+}
+
+#ifdef HAVE_ZFS
+
+#define ZIO_CHECKSUM_BE(zcp)					\
+{								\
+	(zcp)->zc_word[0] = BE_64((zcp)->zc_word[0]);		\
+	(zcp)->zc_word[1] = BE_64((zcp)->zc_word[1]);		\
+	(zcp)->zc_word[2] = BE_64((zcp)->zc_word[2]);		\
+	(zcp)->zc_word[3] = BE_64((zcp)->zc_word[3]);		\
+}
+
+static int
+verify_zfs(int fd)
+{
+	off_t vdev_size;
+	int rv = 1;
+
+	if (prog_ioctl(fd, DIOCGMEDIASIZE, &vdev_size) == -1) {
+		warn("%s: ioctl", __func__);
+		return rv;
+	}
+
+	vdev_phys_t *vdev_phys = emalloc(sizeof(*vdev_phys));
+	for (size_t i = 0; i < VDEV_LABELS; i++) {
+		off_t vdev_phys_off = (i < VDEV_LABELS / 2 ?
+		    i * sizeof(vdev_label_t) :
+		    vdev_size - (VDEV_LABELS - i) * sizeof(vdev_label_t))
+		    + offsetof(vdev_label_t, vl_vdev_phys);
+
+		ssize_t ret = prog_pread(fd, vdev_phys, sizeof(*vdev_phys),
+		    vdev_phys_off);
+		if (ret == -1) {
+			warn("%s: read failed", __func__);
+			goto out;
+		}
+		if ((size_t)ret < sizeof(*vdev_phys)) {
+			warnx("%s: incomplete block", __func__);
+			goto out;
+		}
+
+		bool byteswap;
+		switch (vdev_phys->vp_zbt.zec_magic) {
+		case BSWAP_64(ZEC_MAGIC):
+			byteswap = true;
+			break;
+		case ZEC_MAGIC:
+			byteswap = false;
+			break;
+		default:
+			goto out;
+		}
+
+		zio_cksum_t cksum_found = vdev_phys->vp_zbt.zec_cksum;
+		if (byteswap) {
+			ZIO_CHECKSUM_BSWAP(&cksum_found);
+		}
+
+		ZIO_SET_CHECKSUM(&vdev_phys->vp_zbt.zec_cksum,
+		    vdev_phys_off, 0, 0, 0);
+		if (byteswap) {
+			ZIO_CHECKSUM_BSWAP(&vdev_phys->vp_zbt.zec_cksum);
+		}
+
+		SHA256_CTX ctx;
+		zio_cksum_t cksum_real;
+
+		SHA256Init(&ctx);
+		SHA256Update(&ctx, (uint8_t *)vdev_phys, sizeof *vdev_phys);
+		SHA256Final(&cksum_real, &ctx);
+
+		/*
+		 * For historical reasons the on-disk sha256 checksums are
+		 * always in big endian format.
+		 * (see cddl/osnet/dist/uts/common/fs/zfs/sha256.c)
+		 */
+		ZIO_CHECKSUM_BE(&cksum_real);
+
+		if (!ZIO_CHECKSUM_EQUAL(cksum_found, cksum_real)) {
+			warnx("%s: checksum mismatch on vdev label %zu",
+			    __func__, i);
+			warnx("%s: found %#jx, %#jx, %#jx, %#jx", __func__,
+			    (uintmax_t)cksum_found.zc_word[0],
+			    (uintmax_t)cksum_found.zc_word[1],
+			    (uintmax_t)cksum_found.zc_word[2],
+			    (uintmax_t)cksum_found.zc_word[3]);
+			warnx("%s: expected %#jx, %#jx, %#jx, %#jx", __func__,
+			    (uintmax_t)cksum_real.zc_word[0],
+			    (uintmax_t)cksum_real.zc_word[1],
+			    (uintmax_t)cksum_real.zc_word[2],
+			    (uintmax_t)cksum_real.zc_word[3]);
+			goto out;
+		}
+	}
+	rv = 0;
+out:
+	free(vdev_phys);
+	return rv;
 }
 
+#endif
+
 static off_t sblock_try[] = SBLOCKSEARCH;
 
 static int
@@ -1507,7 +1617,8 @@ iv_method(int mode)
 
 
 static void
-show(const char *dev) {
+show(const char *dev)
+{
 	char path[64];
 	struct cgd_user cgu;
 	int fd;
@@ -1532,11 +1643,13 @@ show(const char *dev) {
 	}
 
 	dev = devname(cgu.cgu_dev, S_IFBLK);
-	if (dev != NULL)
+	if (dev != NULL) {
 		printf("%s ", dev);
-	else
-		printf("dev %llu,%llu ", (unsigned long long)major(cgu.cgu_dev),
+	} else {
+		printf("dev %llu,%llu ",
+		    (unsigned long long)major(cgu.cgu_dev),
 		    (unsigned long long)minor(cgu.cgu_dev));
+	}
 
 	if (verbose)
 		printf("%s ", cgu.cgu_alg);

Index: src/sbin/cgdconfig/params.c
diff -u src/sbin/cgdconfig/params.c:1.34 src/sbin/cgdconfig/params.c:1.34.2.1
--- src/sbin/cgdconfig/params.c:1.34	Fri Aug 12 10:49:35 2022
+++ src/sbin/cgdconfig/params.c	Fri Oct 11 08:54:39 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $ */
+/* $NetBSD: params.c,v 1.34.2.1 2024/10/11 08:54:39 martin Exp $ */
 
 /*-
  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $");
+__RCSID("$NetBSD: params.c,v 1.34.2.1 2024/10/11 08:54:39 martin Exp $");
 #endif
 
 #include <sys/types.h>
@@ -287,6 +287,10 @@ params_verify_method(string_t *in)
 		p->verify_method = VERIFY_MBR;
 	if (!strcmp("gpt", vm))
 		p->verify_method = VERIFY_GPT;
+#ifdef HAVE_ZFS
+	if (!strcmp("zfs", vm))
+		p->verify_method = VERIFY_ZFS;
+#endif
 
 	string_free(in);
 
@@ -1065,6 +1069,11 @@ params_fput(struct params *p, FILE *f)
 	case VERIFY_GPT:
 		print_kvpair_cstr(f, ts, "verify_method", "gpt");
 		break;
+#ifdef HAVE_ZFS
+	case VERIFY_ZFS:
+		print_kvpair_cstr(f, ts, "verify_method", "zfs");
+		break;
+#endif
 	default:
 		warnx("unsupported verify_method (%d)", p->verify_method);
 		return -1;

Index: src/sbin/cgdconfig/params.h
diff -u src/sbin/cgdconfig/params.h:1.14 src/sbin/cgdconfig/params.h:1.14.2.1
--- src/sbin/cgdconfig/params.h:1.14	Fri Aug 12 10:49:35 2022
+++ src/sbin/cgdconfig/params.h	Fri Oct 11 08:54:39 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: params.h,v 1.14 2022/08/12 10:49:35 riastradh Exp $ */
+/* $NetBSD: params.h,v 1.14.2.1 2024/10/11 08:54:39 martin Exp $ */
 
 /*-
  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@@ -81,6 +81,7 @@ struct params {
 #define VERIFY_REENTER		0x4
 #define VERIFY_MBR      	0x5
 #define VERIFY_GPT      	0x6
+#define VERIFY_ZFS      	0x7
 
 /* shared key derivation methods */
 

Reply via email to