Reproductible kernel crash (2.1.1)

Philippe Troin (phil@fifi.org)
03 Feb 1999 20:34:01 -0800


--Multipart_Wed_Feb__3_20:34:01_1999-1
Content-Type: text/plain; charset=US-ASCII

Run the enclosed crashme program with a big number of concurrent
processes while doing a lot of inode access like in:

$ crashme 10 &
$ while true; do find / > /dev/null; done &

And you'll get:
1) A lot of "Warning: dev (03:07) tty->count(0) != #fd's(2) in
do_tty_hangup"
2) A few Warning: null TTY for (03:01) in tty_fasync
3) And finally a couple of this oopses (or worse) (you might have to
wait a few minutes for these)

==================== Begin Oops ====================
Unable to handle kernel NULL pointer dereference at virtual address 00000000
current->tss.cr3 = 05be1000, %cr3 = 05be1000
*pde = 00000000
Oops: 0002
CPU: 1
EIP: 0010:[<c019d926>]
EFLAGS: 00010282
eax: c7fc1020 ebx: 00000001 ecx: 00000009 edx: 00000001
esi: c7fc1020 edi: 00000000 ebp: 00000000 esp: c7dfbe4c
ds: 0018 es: 0018 ss: 0018
Process find (pid: 196, process nr: 21, stackpage=c7dfb000)
Stack: c7e8fd40 c7dfbe84 c7fc1000 00000000 c011172e c7fc1000 00000000 c7dfa000
c7e8fd40 c7dfa000 c7e8fd40 00000000 00000001 c0242020 00000000 c0127601
00000002 c3df18e0 00000000 00000000 c7dfa000 c7e8fd6c c013d406 c7e8fd40
Call Trace: [<c011172e>] [<c0127601>] [<c013d406>] [<c013af19>] [<c011c3e3>] [<c011c607>] [<c012f810>]
[<c012f688>] [<c013ae50>] [<c0108c00>]
Code: f3 a5 a1 c4 c3 27 c0 8b 74 24 10 39 86 c8 00 00 00 74 5b 8b

>>EIP: c019d926 <do_tty_hangup+14a/2d0>
Trace: c011172e <schedule+d2/360>
Trace: c0127601 <__wait_on_buffer+c9/12c>
Trace: c013d406 <ext2_bread+e2/114>
Trace: c013af19 <ext2_readdir+c9/584>
Trace: c011c3e3 <do_anonymous_page+97/a8>
Trace: c011c607 <handle_mm_fault+103/1e8>
Trace: c012f810 <sys_getdents+104/170>
Trace: c012f688 <filldir+0/84>
Code: c019d926 <do_tty_hangup+14a/2d0> 00000000 <_EIP>:
Code: c019d926 <do_tty_hangup+14a/2d0> 0: f3 a5 repz movsl %ds:(%esi),%es:(%edi)
Code: c019d928 <do_tty_hangup+14c/2d0> 2: a1 c4 c3 27 c0 movl 0xc027c3c4,%eax
Code: c019d92d <do_tty_hangup+151/2d0> 7: 8b 74 24 10 movl 0x10(%esp,1),%esi
Code: c019d931 <do_tty_hangup+155/2d0> b: 39 86 c8 00 00 cmpl %eax,0xc8(%esi)
Code: c019d936 <do_tty_hangup+15a/2d0> 10: 00
Code: c019d937 <do_tty_hangup+15b/2d0> 11: 74 5b je 6e <_EIP+0x6e> c019d994 <do_tty_hangup+1b8/2d0>
Code: c019d939 <do_tty_hangup+15d/2d0> 13: 8b 00 movl (%eax),%eax
==================== End Oops ====================

The crashme thingie spawns <N> processes (<N> defined on the command
line) which just open and close tty/pty pairs endlessly.

This is on:
Linux ceramic 2.2.1 #8 SMP Wed Feb 3 19:49:07 PST 1999 i686 unknown
with 2 CPUs, without UNIX98_PTYS support.

Phil.

--Multipart_Wed_Feb__3_20:34:01_1999-1
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="crashme.c"
Content-Transfer-Encoding: quoted-printable

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>

/* Configurable options */
static const char *tty_prefix =3D "/dev/tty";
static const char *pty_prefix =3D "/dev/pty";
static const char *ptty_1st_char =3D "pqrstuvwxyz";
static const char *ptty_2nd_char =3D "0123456789abcdef";

#define PTY_MODE 0666 /* S_IRUSR|S_IWUSR */
#define PTY_UID 0
#define PTY_GID 1

/* Declarations */
struct pty_pair_state
{
int pty;
int tty;
};

/* Globals */
char *progname;

/* Other defs */
#define XIT_OK 0
#define XIT_ARGS 1
#define XIT_SYS 2

/* Error logging function */
void =

log_error(int exit_status, const char *format, ...) =

{
va_list va;
int bufsize=3D256;
char buf[bufsize];
/**/
va_start(va, format);
vsnprintf(buf, bufsize, format, va);
fprintf(stderr, "%s: %s\n", progname, buf);

if (exit_status)
exit(exit_status);
}

/* Malloc with error logging */
void*
xmalloc(size_t size)
{
void *rv;
/**/
if (!(rv=3Dmalloc(size)))
{
log_error(XIT_SYS, "memory allocation failed: %s",
strerror(errno));
}
return rv;
}
/* Open a pty/tty pair, change perms to root.root rw----- and store old
perms in state */
int
open_pty_pair(struct pty_pair_state *state)
{
char *pty_string;
char *tty_string;
size_t pty_size;
size_t tty_size;
const char* last_1st_char;
const char* last_2nd_char;
const char* p_1st_char;
const char* p_2nd_char;
int xitcode=3D-1;
/**/

/* Allocate and copy prefixes */
pty_size =3D strlen(pty_prefix);
tty_size =3D strlen(tty_prefix);
pty_string =3D xmalloc(pty_size+3);
tty_string =3D xmalloc(tty_size+3);
strcpy(pty_string, pty_prefix);
strcpy(tty_string, tty_prefix);
pty_string[pty_size+2]=3D0;
tty_string[tty_size+2]=3D0;
=

/* How many chars in the arrays ? */
last_1st_char =3D ptty_1st_char+strlen(ptty_1st_char);
last_2nd_char =3D ptty_2nd_char+strlen(ptty_2nd_char);

/* Loop, and we need privileges to do the open() */
for ( p_1st_char=3Dptty_1st_char; p_1st_char < last_1st_char; ++p_1st_c=
har)
{
for ( p_2nd_char=3Dptty_2nd_char; p_2nd_char < last_2nd_char; ++p_2=
nd_char)
{
pty_string[pty_size] =3D *p_1st_char;
pty_string[pty_size+1] =3D *p_2nd_char;
state->pty=3Dopen(pty_string, O_RDWR|O_NOCTTY);
if (state->pty=3D=3D-1) =

{
switch(errno) =

{
case ENOENT:
/* File not found */
goto no_more_ptys;
case EIO:
/* Pty busy */
break;
default:
log_error(XIT_SYS, "open %s: %s",
pty_string, strerror(errno));
goto orderly_return;
}
}
else =

{
/* Found the pty, try open the tty */
tty_string[tty_size] =3D *p_1st_char;
tty_string[tty_size+1] =3D *p_2nd_char;
state->tty=3Dopen(tty_string, O_RDWR|O_NOCTTY);
if (state->tty=3D=3D-1) =

{
switch(errno) {
case ENOENT:
/* File not found */
break;
default:
log_error(XIT_SYS, "open %s: %s",
tty_string, strerror(errno));
goto orderly_return;
}
/* Close the pty then, and start over */
if (close(state->pty)=3D=3D-1)
{
log_error(XIT_SYS, "close %s: %s",
tty_string, strerror(errno));
goto orderly_return;
}
}
else =

{
/* Okie */
xitcode=3D0;
goto orderly_return;
}
}
}
}

/* Fallout action */
no_more_ptys:
/* Ran out of ptys ! */
log_error(XIT_SYS, "%s: no more ptys available", progname);
orderly_return:
free(pty_string);
free(tty_string);
return xitcode;
}

/* Close the pty/tty pair and restore permissions to previous state if
possible. =

If noerror is false, then will exit, otherwise will return an exit cod=
e
*/
int close_pty_pair(const struct pty_pair_state *state, int noerror) =

{
int xitcode;
int rv;
/**/
xitcode =3D noerror ? 0 : XIT_SYS;
rv=3D0;

if (close(state->pty)<0)
rv=3D-1, log_error(xitcode, "close pty: %s", strerror(errno));
if (close(state->tty)<0)
rv=3D-1, log_error(xitcode, "close tty: %s", strerror(errno));

return rv;
}
=0C
/* Set the correct tty modes */
int
set_tty(int tty)
{
struct termios tio;
struct termios tiosave;
int i;
/**/
if (tcgetattr(tty, &tio)<0) =

log_error(XIT_SYS, "tcgetattr: %s", strerror(errno));
tio.c_cflag =3D CS8 | CREAD | HUPCL | CLOCAL;
tio.c_iflag =3D IGNBRK | IGNPAR;
tio.c_oflag =3D 0;
tio.c_lflag =3D 0;
for (i=3D0; i<NCCS; i++)
tio.c_cc[i]=3D0;
tio.c_cc[VMIN]=3D1;
tio.c_cc[VTIME]=3D0;
tiosave=3Dtio;
if (tcsetattr(tty, TCSANOW, &tio)<0)
log_error(XIT_SYS, "tcsetattr: %s", strerror(errno));
if (tcgetattr(tty, &tio)<0)
log_error(XIT_SYS, "tcsetattr: %s", strerror(errno));
if (tio.c_iflag !=3Dtiosave.c_iflag
|| tio.c_oflag !=3Dtiosave.c_oflag
|| tio.c_cflag !=3Dtiosave.c_cflag
|| tio.c_lflag !=3Dtiosave.c_lflag)
log_error(XIT_SYS, "set_tty: cannot set terminal IO modes");
return 0;
}

int main(int argc, char *argv[])
{
char *ptr;
unsigned int nchilds;
unsigned int i;
/**/
for(ptr=3Dprogname=3Dargv[0]; *ptr;) if (*ptr=3D=3D'/') progname=3D++pt=
r; else ++ptr;

if (argc!=3D2)
log_error(XIT_ARGS, "need number of childs to spawn...\n");

nchilds =3D strtoul(argv[1], &ptr, 10);
if (*ptr)
log_error(XIT_ARGS, "\"%s\" is not a number !\n", argv[1]);

for (i=3D0; i<nchilds; i++)
switch(fork())
{
case -1:
log_error(XIT_SYS, "fork(): %s\n", strerror(errno));
case 0:
while(1)
{
int bufsize=3D128;
char buf[bufsize];
struct pty_pair_state ptys;
/**/
open_pty_pair(&ptys);
set_tty(ptys.tty);
#if 0
write(ptys.pty, buf, bufsize);
write(ptys.tty, buf, bufsize);
read(ptys.tty, buf, bufsize);
read(ptys.pty, buf, bufsize);
#endif
close_pty_pair(&ptys, 0);
}
default:
break;
}

while (1) pause();
}

--Multipart_Wed_Feb__3_20:34:01_1999-1--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/