Subject: Solution(?) to kern/28804: quotacheck crashes on FFSv2
To: None <tech-kern@netbsd.org>
From: Edgar =?iso-8859-1?B?RnXf?= <efnbl06@bn2.maus.net>
List: tech-kern
Date: 02/12/2007 19:59:27
I don't know where this should belong.

The original PR has been reported as kern, but it's really a userland problem.

Also, the PR (kern/28804) is more than two years old, so the people recorded as interested parties may no longer be active. I've replied to the PR, but probably no-one is going to read that unless I hint at it.

There seem to be at least two obvious bugs in quotacheck.
While comparing the source to fbd's version, I also noticed that fbd seems to have incorporated several enhancements, mostly by McKusick, thay may be worthwile to import. They deal with not accounting for either the accounting files themselves or snapshots and an optimisation regarding soft dependencies I don't understand.

The following patch corrects the two problems (not setting ino, using a superblock field for sizing a malloc before reading in the SB):

--- quotacheck.c.orig	2004-12-12 06:57:03.000000000 +0100
+++ quotacheck.c	2007-02-11 16:32:55.000000000 +0100
@@ -1,5 +1,3 @@
-/*	$NetBSD: quotacheck.c,v 1.36 2004/12/12 05:57:03 christos Exp $	*/
-
 /*
  * Copyright (c) 1980, 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -360,19 +358,9 @@
 	sync();
 	dev_bsize = 1;

 
-	cgp = malloc(sblock.fs_cgsize);
-	if (cgp == NULL) {
-		warn("%s: can't allocate %d bytes of cg space", fsname,
-		    sblock.fs_cgsize);
-		if (pid != NULL)
-			exit(1);
-		return 1;
-	}
-
 	for (i = 0; ; i++) {
 		if (sblock_try[i] == -1) {
 			warnx("%s: superblock not found", fsname);
-			free(cgp);
 			if (pid != NULL)
 				exit(1);
 			return 1;
@@ -411,10 +399,20 @@
 		break;
 	}

 
+	cgp = malloc(sblock.fs_cgsize);
+	if (cgp == NULL) {
+		warn("%s: can't allocate %d bytes of cg space", fsname,
+		    sblock.fs_cgsize);
+		if (pid != NULL)
+			exit(1);
+		return 1;
+	}
+
 	dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
 	maxino = sblock.fs_ncg * sblock.fs_ipg;
-	for (ino = 0, cg = 0; cg < sblock.fs_ncg; cg++) {
-		setinodebuf(cg * sblock.fs_ipg);
+	for (cg = 0; cg < sblock.fs_ncg; cg++) {
+		ino = cg * sblock.fs_ipg;
+		setinodebuf(ino);
 #ifdef HAVE_UFSv2
 		if (sblock.fs_magic == FS_UFS2_MAGIC) {
 			bread(fsbtodb(&sblock, cgtod(&sblock, cg)), (char *)cgp,