The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f0a08fa9f532a58f5d7a4814d6eb7ddd49f368da

commit f0a08fa9f532a58f5d7a4814d6eb7ddd49f368da
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2021-10-04 21:48:44 +0000
Commit:     Mark Johnston <ma...@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;

Reply via email to