NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
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: Taylor R Campbell <riastradh%netbsd.org@localhost>
Cc: gnats-bugs%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Subject: Re: Re: bin/58212: cgdconfig(8): Add zfs verification method
Date: Sun, 28 Apr 2024 16:07:27 -0700
--00000000000069a3400617303387
Content-Type: text/plain; charset="UTF-8"
Hi Taylor,
On Sun, Apr 28, 2024 at 08:38:55PM +0000, Taylor R Campbell wrote:
> Cool, thanks! We should definitely have a zfs verification method for
> cgdconfig(8). But I think we can do it a little more robustly -- and
> with fewer dependencies outside libc in cgdconfig(8).
>
> Here's what I wrote the last time someone suggested this -- identical
> to the nvlist approach you adapted from fstyp(8) -- but my round tuit
> supply ran short of taking the approach I suggested of verifying a
> fixed magic number and a SHA-256 hash over the header:
>
> I wonder if we can do this without pulling so much into cgdconfig and
> doing parsing there, though?
>
> A comment in fstyp(8) suggests there's a checksum (which it doesn't
> verify); maybe we can use that?
>
> Would be nice if there were a reference to the data format that we can
> put in a comment -- which should appear in fstyp(8) too.
>
> Would also be nice if we could quantify the false acceptance
> probability under uniform random data (i.e., wrong password, modelling
> password hash as uniform random function). For the current
> verification methods it looks like:
>
> verify_ffs = 1 - (1 - 4/2^32)^4 < one in 250 * 10^6
> verify_gpt < 1 - (1 - 1/2^96)^4 < one in 10^28
> verify_mbr = 1/2^16 (much too high for my comfort!)
>
> For zfs I would hope it can be much lower than for ffs.
>
> I went hunting through the zfs header files and it looks like the vdev
> label has a magic number and some kind of 256-bit checksum -- not
> specific to the vdev label (other zpool data structures have the same
> magic number and checksum), but maybe we can use it:
>
> /* vdev_impl.h */
> typedef struct vdev_phys {
> char vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_eck_t)];
> zio_eck_t vp_zbt;
> } vdev_phys_t;
>
> typedef struct vdev_label {
> char vl_pad1[VDEV_PAD_SIZE]; /* 8K */
> char vl_pad2[VDEV_PAD_SIZE]; /* 8K */
> vdev_phys_t vl_vdev_phys; /* 112K */
> char vl_uberblock[VDEV_UBERBLOCK_RING]; /* 128K */
> } vdev_label_t; /* 256K total */
>
> /* zio.h */
> #define ZEC_MAGIC 0x210da7ab10c7a11ULL
>
> typedef struct zio_eck {
> uint64_t zec_magic; /* for validation, endianness */
> zio_cksum_t zec_cksum; /* 256-bit checksum */
> } zio_eck_t;
>
> Judging by zio_checksum.c, it looks like it's SHA-256.
>
> I grepped for some of the nvlist keys that zfs uses, and found
> libzfs_import.c, which does a couple things:
>
> - Tries not just offset 0, but up to four different offsets with the
> label_offset function.
>
> - Checks for "state" and "txg" in the nvlist.
>
> vdev_label_read_config also tries several different offsets, but only
> checks for "txg" -- and doesn't even require that. So the nvlist keys
> may be a red herring here.
>
> But with the checksum, it looks like we could get by with:
>
> 1. (optional) for each possible label offset:
>
> 2. verify vl->vl_vdev_phys.vp_zbt.zec_magic == ZEC_MAGIC or
> byte-swapped, and
>
> 3. verify vl->vl_vdev_phys.vp_zbt.zec_cksum is the SHA-256 hash of
> whatever part of vl it's computed over.
>
> The SHA-256 hash appears to be calculated over vl->vl_vdev_phys, but
> with vp_zbt.zec_cksum set to
>
> {labeloffset + offsetof(struct vdev_label, vl_vdev_phys), 0, 0, 0},
>
> with the 64-bit words possibly encoded in the same byte order as
> zec_magic. Except then the bytes of each 64-bit word in the SHA-256
> output hash are byte-swapped.
>
> This seems to check out on the one sample I tried, and it should have
> a false detection probability under uniform random data well below
> 1/2^256 which is extremely comfortable. (Should also have low false
> detection probability under other formats too because of the checksum
> even if you store a file with the magic number in it.)
Thanks for the detailed response!
I did the same reading to try and find out if there is a simple checksum
verification function but didn't find anything. It seems like zpool
import never actually verifies the checksums or magic bytes in
vl->vl_vdev_phys->vp_zbt . There are VDEV_LABELS (4) labels, two at the
beginning of the disk (offset 0 and 256k) and two at the end (at -512k,
-256k) and even with all of their vl->vl_vdev_phys->vp_zbt structures
zeroed out, zpool import shows no complaints. The checksums are updated
on export.
I did a quick test and computed sha256 for vl->vdev_phys and it works as
you described: the magic bytes need to be set first (byte-swapped on my
system) and the offset encoded in the first of the 64bit checksum words
(also byte-swapped). The computed sha256 checksum is then stored as 4
64bit words in byte-swapped order.
Implementing the checksum verification is easy and allows us to get rid
of the libnvpair dependency, so I don't mind implementing it that way.
Since I haven't looked into exactly how much checking libnvpair does, I
don't know what the risk of false positives for the current proposal is.
Cheers,
--
Malte Dehling
--00000000000069a3400617303387
Content-Type: application/pgp-signature; name="signature.asc"
Content-Disposition: attachment; filename="signature.asc"
Content-Transfer-Encoding: base64
X-Attachment-Id: 7279cfb2c4807360_0.1
LS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KCmlRSXpCQUFCQ0FBZEZpRUVva3ZsOUFOMEFo
T05jQXdlSzhMazZxS3dkMFFGQW1ZdTFxY0FDZ2tRSzhMazZxS3cKZDBUTi9nLy9Va3lYdGZqc2pF
S0p2OGFRQ3VETHIrWHFYRVNnaEhkZHo2Rk9OdFQxaE9Wbnl0RVkvUWFOWWNMNgpoc2JEdDAvMmND
S1JpTFFTL1lmVExtdmRkMm43S1E5V3VHbGtGcXBjZXFyZXR3RHJOTXFTN3RNcGI5eXE2VTR3Ck1D
T1ZEZDlMTmdONllwdjF1cWZ5S3RyTzRXTERRLzJiMUZTN0F4N0VDb2ZLUGphajNVemtUUlJmU3FZ
TkZxVEIKUzBVbXVsN0pnU25lRnhGZnRJVG9sZUQxUWZYSFRFSGpCTlN4YkVEak00cmpHbXVuMU5n
QlJqNjRmaS9WZVZxcQpWYURjOCt5Ly9pOFUxcE9EUjZTVjkwMDQyblEreHN3TzB5Q1pwZzlXT3Y5
QXNST1hKbTJoNTFHNmxIS0tNM25DCnR0K3p0L294UHFQY2hHZTl5dXhra05oZkdWZlJUWFl2aUJZ
Q1ptVkxvUWl4OExDU2l6UzNMTHpjMm9rcHdLK2cKSFlmd0dqRENRK20wNXhOUEZGNWcvSTdwd0R4
ZU8xVGdWL0Z3b1IzMHhCZUQzMEkxaVlLcDRPZjFWOWorZGNDSApNQjdwbm45ZmFzbzM4QllmVG1L
OUNXOEZWWDNxQWJCZFhGNFoxcmlyU2gvME5yV0ViSDBVaGRISldPRFFCSFcxClJJajJvS3ZLRFV5
N2pqT09oUFF4N3RhSUU0WWxSMVRmS1g4dHhKTXVydnY1TVZvNmpveEZPdmRjaGpYaytnVG4KRlFm
QUhnZ3poQXZEdS95VmhubTgydzd1amNlRmVHbUxjdm5xcWVzMkxrWVFBbDEzYVhiY0JQWVRZUE1t
V1B3QwpoQ28zeHJVQlNyU1FUVzdwWVZhcVBnRysybXAycXlxdzk5d1I3WHJ2N1Q3SVBPV1NDUzg9
Cj1YZ092Ci0tLS0tRU5EIFBHUCBTSUdOQVRVUkUtLS0tLQo=
--00000000000069a3400617303387--
Home |
Main Index |
Thread Index |
Old Index