The dumpcg() function in dumpfs(8) uses fs_contigsumsize and
cg_clustersumoff from the filesystem image without validation.
At line 390-396:
if (afs.fs_contigsumsize > 0) {
for (i = 1; i < afs.fs_contigsumsize; i++) {
printf("\t%d", cg_clustersum(&acg)[i]);
cg_clustersum() returns a pointer into the cylinder group buffer
at the offset specified by cg_clustersumoff. With a corrupted
image, either the offset or the size can be large enough to read
past the buffer (which is fs_bsize bytes), causing a SIGSEGV.
Confirmed on OpenBSD 7.8/arm64 with a mutated FFS image.
Fix: validate that cg_clustersumoff is within the buffer and
that fs_contigsumsize entries fit within the remaining space.
Found by AFL++ fuzzing.
Index: sbin/dumpfs/dumpfs.c
===================================================================
RCS file: /cvs/src/sbin/dumpfs/dumpfs.c,v
retrieving revision 1.39
diff -u -p -r1.39 dumpfs.c
--- sbin/dumpfs/dumpfs.c 9 May 2024 08:35:40 -0000 1.39
+++ sbin/dumpfs/dumpfs.c
@@ -387,7 +387,10 @@ dumpcg(const char *name, int fd, u_int c
j += i * acg.cg_frsum[i];
}
printf("\nsum of frsum: %d", j);
- if (afs.fs_contigsumsize > 0) {
+ if (afs.fs_contigsumsize > 0 &&
+ acg.cg_clustersumoff < afs.fs_bsize &&
+ afs.fs_contigsumsize <= (afs.fs_bsize -
+ acg.cg_clustersumoff) / (int)sizeof(int32_t)) {
for (i = 1; i < afs.fs_contigsumsize; i++) {
if ((i - 1) % 8 == 0)
printf("\nclusters %d-%d:", i,