From f0a08fa9f532a58f5d7a4814d6eb7ddd49f368da Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 4 Oct 2021 17:48:44 -0400 Subject: [PATCH] geom_label: Add more validation for NTFS volume tasting - Ensure that the computed MFT record size isn't negative or larger than maxphys before trying to read $Volume. - Guard against truncated records in volume metadata. - Ensure that the record length is large enough to contain the volume name. - Verify that the (UTF-16-encoded) volume name's length is a multiple of two. PR: 258833, 258914 MFC after: 2 weeks Sponsored by: The FreeBSD Foundation --- sys/geom/label/g_label_ntfs.c | 37 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/sys/geom/label/g_label_ntfs.c b/sys/geom/label/g_label_ntfs.c index f78d4d28b96..888096164b0 100644 --- a/sys/geom/label/g_label_ntfs.c +++ b/sys/geom/label/g_label_ntfs.c @@ -99,7 +99,8 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) struct ntfs_filerec *fr; struct ntfs_attr *atr; off_t voloff; - char *filerecp, *ap; + size_t recoff; + char *filerecp; int8_t mftrecsz; char vnchar; int recsize, j; @@ -119,8 +120,9 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) goto done; mftrecsz = bf->bf_mftrecsz; - recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); - if (recsize == 0 || recsize % pp->sectorsize != 0) + recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : + (1 << -mftrecsz); + if (recsize <= 0 || recsize > maxphys || recsize % pp->sectorsize != 0) goto done; voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + @@ -132,24 +134,33 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) if (filerecp == NULL) goto done; fr = (struct ntfs_filerec *)filerecp; - if (fr->fr_hdrmagic != NTFS_FILEMAGIC) goto done; - for (ap = filerecp + fr->fr_attroff; - atr = (struct ntfs_attr *)ap, atr->a_type != -1; - ap += atr->reclen) { + for (recoff = fr->fr_attroff; + recoff <= recsize - 2 * sizeof(uint32_t); + recoff += atr->reclen) { + atr = (struct ntfs_attr *)(filerecp + recoff); + if (atr->a_type == -1) + break; + if (atr->reclen < sizeof(*atr)) + break; + if (recsize - recoff < atr->reclen) + break; if (atr->a_type == NTFS_A_VOLUMENAME) { - if(atr->a_datalen >= size *2){ - label[0] = 0; - goto done; - } + if (atr->a_dataoff > atr->reclen || + atr->a_datalen > atr->reclen - atr->a_dataoff) + break; + /* - *UNICODE to ASCII. + * UNICODE to ASCII. * Should we need to use iconv(9)? */ + if (atr->a_datalen >= size * 2 || + atr->a_datalen % 2 != 0) + break; for (j = 0; j < atr->a_datalen; j++) { - vnchar = *(ap + atr->a_dataoff + j); + vnchar = ((char *)atr)[atr->a_dataoff + j]; if (j & 1) { if (vnchar) { label[0] = 0; -- 2.45.0