diff --git a/sys/vfs/ntfs/ntfs_compr.c b/sys/vfs/ntfs/ntfs_compr.c --- a/sys/vfs/ntfs/ntfs_compr.c +++ b/sys/vfs/ntfs/ntfs_compr.c @@ -78,6 +78,23 @@ } boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift); blen = 3 + (GET_UINT16(cbuf + cpos) & lmask); + /* + * DF-0932: reject malformed back-references whose displacement + * would read before the start of the output buffer. Without + * this check a crafted LZNT1 stream can drive pos + boff < 0, + * causing buf[pos + boff] to read kernel heap memory preceding + * the buf (uup) allocation; the bytes are then copied into uup + * and shipped to the reader via uiomove (ntfs_subr.c:1723) -- + * an unprivileged kernel heap info leak reachable by any reader + * of a mounted NTFS compressed file. + * + * Returning 0 here signals "malformed block" to ntfs_uncompunit + * (the only caller), which already maps new == 0 to EINVAL. + * ntfs_uncompblock otherwise returns len + 3 (>= 3), so 0 is an + * unambiguous error sentinel. + */ + if (pos + boff < 0) + return (0); for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) { buf[pos] = buf[pos + boff]; pos++;