Module Name:    src
Committed By:   christos
Date:           Sun May 12 18:02:16 UTC 2024

Modified Files:
        src/sbin/cgdconfig: Makefile cgdconfig.8 cgdconfig.c params.c params.h

Log Message:
PR/58212: Malte Dehling: Add zfs verification method


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sbin/cgdconfig/Makefile
cvs rdiff -u -r1.57 -r1.58 src/sbin/cgdconfig/cgdconfig.8
cvs rdiff -u -r1.62 -r1.63 src/sbin/cgdconfig/cgdconfig.c
cvs rdiff -u -r1.34 -r1.35 src/sbin/cgdconfig/params.c
cvs rdiff -u -r1.14 -r1.15 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.23
--- src/sbin/cgdconfig/Makefile:1.22	Fri Aug 12 06:49:17 2022
+++ src/sbin/cgdconfig/Makefile	Sun May 12 14:02:16 2024
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.22 2022/08/12 10:49:17 riastradh Exp $
+# $NetBSD: Makefile,v 1.23 2024/05/12 18:02:16 christos 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.58
--- src/sbin/cgdconfig/cgdconfig.8:1.57	Fri Aug 12 06:49:47 2022
+++ src/sbin/cgdconfig/cgdconfig.8	Sun May 12 14:02:16 2024
@@ -1,4 +1,4 @@
-.\" $NetBSD: cgdconfig.8,v 1.57 2022/08/12 10:49:47 riastradh Exp $
+.\" $NetBSD: cgdconfig.8,v 1.58 2024/05/12 18:02:16 christos 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,6 +270,8 @@ 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.

Index: src/sbin/cgdconfig/cgdconfig.c
diff -u src/sbin/cgdconfig/cgdconfig.c:1.62 src/sbin/cgdconfig/cgdconfig.c:1.63
--- src/sbin/cgdconfig/cgdconfig.c:1.62	Sun Apr 28 20:28:18 2024
+++ src/sbin/cgdconfig/cgdconfig.c	Sun May 12 14:02:16 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: cgdconfig.c,v 1.62 2024/04/29 00:28:18 riastradh Exp $ */
+/* $NetBSD: cgdconfig.c,v 1.63 2024/05/12 18:02:16 christos 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.62 2024/04/29 00:28:18 riastradh Exp $");
+__RCSID("$NetBSD: cgdconfig.c,v 1.63 2024/05/12 18:02:16 christos Exp $");
 #endif
 
 #ifdef HAVE_ARGON2
@@ -73,6 +73,11 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.62 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

Index: src/sbin/cgdconfig/params.c
diff -u src/sbin/cgdconfig/params.c:1.34 src/sbin/cgdconfig/params.c:1.35
--- src/sbin/cgdconfig/params.c:1.34	Fri Aug 12 06:49:35 2022
+++ src/sbin/cgdconfig/params.c	Sun May 12 14:02:16 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: params.c,v 1.34 2022/08/12 10:49:35 riastradh Exp $ */
+/* $NetBSD: params.c,v 1.35 2024/05/12 18:02:16 christos 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.35 2024/05/12 18:02:16 christos 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.15
--- src/sbin/cgdconfig/params.h:1.14	Fri Aug 12 06:49:35 2022
+++ src/sbin/cgdconfig/params.h	Sun May 12 14:02:16 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: params.h,v 1.14 2022/08/12 10:49:35 riastradh Exp $ */
+/* $NetBSD: params.h,v 1.15 2024/05/12 18:02:16 christos 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