git: f0a08fa9f532 - main - geom_label: Add more validation for NTFS volume tasting
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 04 Oct 2021 22:18:00 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=f0a08fa9f532a58f5d7a4814d6eb7ddd49f368da
commit f0a08fa9f532a58f5d7a4814d6eb7ddd49f368da
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-10-04 21:48:44 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-10-04 22:15:06 +0000
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 f78d4d28b967..888096164b09 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;