Subject: kern/5080: f_count panic (et al.)
To: None <>
From: David Holland <>
List: netbsd-bugs
Date: 02/27/1998 21:30:56
>Number:         5080
>Category:       kern
>Synopsis:       panic on f_count (in struct file) negative
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 27 18:35:01 1998
>Originator: (David A. Holland)
   - David A. Holland             |    VINO project home page:    |
>Release:        1.3
System: NetBSD 1.2.1 NetBSD 1.2.1 (CHIANTI) #1: Tue Sep 9 16:52:39 EDT 1997 i386

Note: also tested with the 1.3 distribution kernel from

	The reference count on struct file is a signed short, so if
	one can construct more than 32767 references it overflows.
	This can be done with a combination of dup() and fork().

	Additional unexplained behavior occurs if you set NDUPS to 60
	and NFORKS to 550: in 1.2.1, it reliably crashes with a page
	fault in wdcstart(), and in 1.3, it hangs (cannot create any
	more processes) and once I got it to reference 0xdeadbeef in
	m_freem() [but only once] by trying to telnet in.

	Since this seems to happen on fork #50, long before the ref
	count should overflow, it may be an additional unrelated 

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define NDUPS 1600
#define NFORKS 22

static void child() {

static void openem() {
	int i,r;
	int fd = open("/etc/passwd", O_RDONLY);
	if (fd<0) { perror("open /etc/passwd"); exit(1); }
	for (i=0; i<NDUPS; i++) {
		r = dup(fd);
		if (r<0) { perror("dup"); exit(1); }

static void forkus() {
	int i;
	int r;
	write(1, "forking\n", 8);
	for (i=0; i<NFORKS; i++) {
		r = fork();
		if (r<0) { perror("fork"); exit(1); }
		if (r==0) child();
		write(1, ".-", 2);

int main() {
	int status;
	while (wait(&status)>=0);
	return 0;

	fork() needs to check and make sure that f_count doesn't overflow.
	(dup already seems to.)