NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Re: Re: bin/58212: cgdconfig(8): Add zfs verification method



The following reply was made to PR bin/58212; it has been noted by GNATS.

From: Malte Dehling <mdehling%gmail.com@localhost>
To: netbsd-bugs%netbsd.org@localhost
Cc: Taylor R Campbell <riastradh%netbsd.org@localhost>, gnats-bugs%netbsd.org@localhost
Subject: Re: Re: Re: bin/58212: cgdconfig(8): Add zfs verification method
Date: Mon, 29 Apr 2024 18:46:11 -0700

 Hi,
 
 On Sun, Apr 28, 2024 at 01:13:05PM -0700, Malte Dehling wrote:
 > >Submitter-Id:  net
 > >Originator:    Malte Dehling
 > >Organization:
 > >Confidential:  no
 > >Synopsis:      cgdconfig(8): Add zfs verification method
 > >Severity:      non-critical
 > >Priority:      medium
 > >Category:      bin
 > >Class:         change-request
 > >Release:       NetBSD 10.0, -current
 > >Environment:
 >     NetBSD 10.0 (GENERIC) #4: Wed Apr 24 12:21:26 PDT 2024
 >     mdehling@nb-base-dev:/scratch/obj/sys/arch/amd64/compile/GENERIC amd64
 >
 > >Description:
 > I would like to propose the attached patch to add a zfs verification
 > method to the cgdconfig(8) program.  With such a method, it will be
 > possible to use cgd devices as vdevs in a zpool without an intermediate
 > gpt.
 
 How about this version instead?
 
 I _think_ I got the byte order logic right:
 - deduce the byte order from the magic bytes and use it to initialize
   the checksum computation with the same byte order
 - on-disk sha256 is always stored in big-endian order, so convert
   whatever we compute to BE before comparing
 
 Tested only on LE since I don't have a BE netbsd system handy right now.
 
 
 ---
 Implement vdev label checksum verification.  Allows using raw cgd
 devices as vdevs in a zpool.
 ---
  sbin/cgdconfig/Makefile    |  15 +++++
  sbin/cgdconfig/cgdconfig.8 |   2 +
  sbin/cgdconfig/cgdconfig.c | 111 +++++++++++++++++++++++++++++++++++++
  sbin/cgdconfig/params.c    |   9 +++
  sbin/cgdconfig/params.h    |   1 +
  5 files changed, 138 insertions(+)
 
 diff --git a/sbin/cgdconfig/Makefile b/sbin/cgdconfig/Makefile
 index fec75b4e375..0ed669ab738 100644
 --- a/sbin/cgdconfig/Makefile
 +++ b/sbin/cgdconfig/Makefile
 @@ -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>
 diff --git a/sbin/cgdconfig/cgdconfig.8 b/sbin/cgdconfig/cgdconfig.8
 index 2b0da2cb732..e48ccde02c5 100644
 --- a/sbin/cgdconfig/cgdconfig.8
 +++ b/sbin/cgdconfig/cgdconfig.8
 @@ -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.
 diff --git a/sbin/cgdconfig/cgdconfig.c b/sbin/cgdconfig/cgdconfig.c
 index 9a634ef37e2..de4d09013bf 100644
 --- a/sbin/cgdconfig/cgdconfig.c
 +++ b/sbin/cgdconfig/cgdconfig.c
 @@ -73,6 +73,11 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.61 2022/11/17
 06:40:38 chs Exp $");
 
  #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"
 @@ -170,6 +175,9 @@ 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);
 
 @@ -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;
 @@ -1182,6 +1194,105 @@ verify_gpt(int fd)
  	return ret;
  }
 
 +#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)
 +{
 +	struct stat sb;
 +	vdev_phys_t *vdev_phys;
 +	off_t vdev_phys_off;
 +	ssize_t ret;
 +	bool byteswap;
 +	zio_cksum_t cksum_found, cksum_real;
 +	SHA256_CTX ctx;
 +
 +	if (fstat(fd, &sb)) {
 +		warn("fstat");
 +		return 1;
 +	} else if (sb.st_size == 0) {
 +		warnx("fstat returned size zero");
 +		return 1;
 +	}
 +
 +	vdev_phys = emalloc(sizeof *vdev_phys);
 +	for (int l = 0; l < VDEV_LABELS; l++) {
 +		vdev_phys_off = ( l < VDEV_LABELS/2 ?
 +		    l * sizeof(vdev_label_t) :
 +		    sb.st_size - (VDEV_LABELS-l) * sizeof(vdev_label_t) ) \
 +		    + offsetof(vdev_label_t, vl_vdev_phys);
 +
 +		ret = prog_pread(fd, vdev_phys, sizeof *vdev_phys,
 +		    vdev_phys_off);
 +		if (ret < 0) {
 +			warn("pread");
 +			ret = 1;
 +			break;
 +		} else if ((size_t)ret < sizeof *vdev_phys) {
 +			warnx("pread: incomplete block");
 +			ret = 1;
 +			break;
 +		}
 +
 +		ret = 0;
 +
 +		if (vdev_phys->vp_zbt.zec_magic == BSWAP_64(ZEC_MAGIC))
 +			byteswap = true;
 +		else if (vdev_phys->vp_zbt.zec_magic == ZEC_MAGIC)
 +			byteswap = false;
 +		else {
 +			ret = 1;
 +			break;
 +		};
 +
 +		cksum_found = vdev_phys->vp_zbt.zec_cksum;
 +
 +		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);
 +
 +		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("checksum mismatch on vdev label %d", l);
 +			warnx("found %lx, %lx, %lx, %lx",
 +			    (unsigned long)cksum_found.zc_word[0],
 +			    (unsigned long)cksum_found.zc_word[1],
 +			    (unsigned long)cksum_found.zc_word[2],
 +			    (unsigned long)cksum_found.zc_word[3]);
 +			warnx("expected %lx, %lx, %lx, %lx",
 +			    (unsigned long)cksum_real.zc_word[0],
 +			    (unsigned long)cksum_real.zc_word[1],
 +			    (unsigned long)cksum_real.zc_word[2],
 +			    (unsigned long)cksum_real.zc_word[3]);
 +			ret = 1;
 +			break;
 +		}
 +	}
 +	free(vdev_phys);
 +	return ret;
 +}
 +
 +#endif
 +
  static off_t sblock_try[] = SBLOCKSEARCH;
 
  static int
 diff --git a/sbin/cgdconfig/params.c b/sbin/cgdconfig/params.c
 index 91af02c21cc..5da25ec0595 100644
 --- a/sbin/cgdconfig/params.c
 +++ b/sbin/cgdconfig/params.c
 @@ -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;
 diff --git a/sbin/cgdconfig/params.h b/sbin/cgdconfig/params.h
 index fb79a0deb80..ef49dde6aba 100644
 --- a/sbin/cgdconfig/params.h
 +++ b/sbin/cgdconfig/params.h
 @@ -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 */
 
 -- 
 2.44.0
 
 
 Cheers,
 -- 
 Malte Dehling
 



Home | Main Index | Thread Index | Old Index