kern/82682: "Accounting resumed" while disk fills up

Bruce Evans bde at zeta.org.au
Mon Jun 27 13:40:25 GMT 2005


The following reply was made to PR kern/82682; it has been noted by GNATS.

From: Bruce Evans <bde at zeta.org.au>
To: Wietse Venema <wietse at porcupine.org>
Cc: freebsd-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org
Subject: Re: kern/82682: "Accounting resumed" while disk fills up
Date: Mon, 27 Jun 2005 23:39:52 +1000 (EST)

 On Sun, 26 Jun 2005, Wietse Venema wrote:
 
 >> Description:
 > When the disk fills up, the kernel as expected disables process accounting, but it RESUMES process accounting while the disk fills up further.
 >
 > Perhaps the code gets confused when the free space becomes negative (see repeat-by example below). But that is pure speculation.
 >
 > I have been using FreeBSD for 10+ years and routinely use dd of /dev/zero to wipe the free space as root. I did not notice this accounting anomaly when I was still using FreeBSD 4.
 
 This is one one the many possible and actual sign extension/overflow bugs
 caused by the poorly chosen types in the 64-bit statfs.  From kern_acct.c:
 
 %%%
  		if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
  			acctp = savacctp;
  			acctcred = savacctcred;
  			acctflags = savacctflags;
  			savacctp = NULLVP;
  			savacctcred = NOCRED;
  			log(LOG_NOTICE, "Accounting resumed\n");
  		}
 %%%
 
 In RELENG_4, everything in struct statfs has a non-foot-shooting type
 (plain long), but in -current after 2003/12/11 the types don't mesh
 properly; most types are 64 bits; f_bavail is still signed, as it needs
 to be to represent negative free space, but most of the other types
 are unsigned, as they need to be to cause sign extension bugs.  In the
 above, `acctresume * sb.f_blocks / 100' has type uint64_t and is not
 very large, but sb.f_bavail has type int64_t and is not very large in
 absolute value, so as soon as sb.f_bavail becomes negative it is converted
 to a huge uint64_t as part of the comparison and the comparison always
 succeeds.
 
 Another bug in the above is that `acctresume * sb.f_blocks' overflows if
 sb.f_blocks exceeds 1/4 of the maximum for the data type.  This overflow
 is hard to reach since (2^64)/4-1 blocks should be enough for anyone, and
 even overflow at (2^31)/4 blocks in RELENG_4 is hard to reach due to
 other limits (mainly the limit of 2^31-1 512-blocks).
 
 Bruce


More information about the freebsd-bugs mailing list