Subject: kern/4505: Crash when reading from raw device to non mapped buffer
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kivinen@ssh.fi>
List: netbsd-bugs
Date: 11/16/1997 13:32:42
>Number:         4505
>Category:       kern
>Synopsis:       System crash when reading from raw device to buffer that is not mapped
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 16 03:35:02 1997
>Last-Modified:
>Originator:     Tero Kivinen
>Organization:
Ssh Communications Security Ltd
>Release:        1.2
>Environment:
	
System: NetBSD taulu.ssh.fi 1.2 NetBSD 1.2 (TAULU) #50: Mon Feb 24 21:40:52 EET 1997 kivinen@taulu.ssh.fi:/usr/src/sys/arch/i386/compile/TAULU i386


>Description:

	When reading data from raw device (/dev/rwd0a for example) to
	buffer that is allocated but not mapped the kernel will crash
	(drop to debugger).

	Because reading from raw device usually requires root
	permission this is not very fatal bug unless some environments
	are configured to allow raw disk access to some users
	(database disk etc). 

>How-To-Repeat:

	Run this program with /dev/rwd0b (or any other raw disk
	device) as an argument. If you give a block device or define
	NO_BUG when compiling it then the kernel doesn't crash. 
----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#define RAW_BUFFER_SIZE 10*1024*1024

int main(int argc, char **argv)
{
  char *buffer;
  int f;
  ssize_t l;

  if (argc != 2)
    {
      fprintf(stderr, "Usage: %s raw_disk_name\n", argv[0]);
      exit(1);
    }
  buffer = malloc(RAW_BUFFER_SIZE);
#ifdef NO_BUG
  memset(buffer, 0, RAW_BUFFER_SIZE);
#endif
  
  f = open(argv[1], O_RDONLY, 0);
  if (f < 0) { perror("open"); exit(1); }
  
  l = read(f, buffer, RAW_BUFFER_SIZE);
  if (l != RAW_BUFFER_SIZE) { perror("read"); exit(1); }
  
  close(f);
  exit(0);
}
----------------------------------------------------------------------

# gcc t.c
# sync
# ls -lag
total 324
drwxrwxrwt   2 root  wheel     512 Nov 16 13:37 .
drwxr-xr-x  21 tmo   wheel    1024 Oct 29 09:37 ..
-rwxr-xr-x   1 root  wheel    8845 Nov 16 13:37 a.out
-rw-r--r--   1 root  wheel     577 Nov 16 13:37 t.c
# ./a.out
Usage: ./a.out raw_disk_name
# ./a.out /dev/wd0b
# ./a.out /dev/rwd0b
panic: ptdi 649063
syncing disks... 8 8 6 1 done

dumping to dev 1, offset 370432
dump 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 succeeded


rebooting...

>Fix:

	I assume it will give the buffer supplied by user directly to
	device read if device is raw device, and the device read is
	not prepared to handle page faults. If you use block device
	then the pages are always allocated because they are in buffer
	cache.
>Audit-Trail:
>Unformatted:
>> NetBSD: 640/15360 k [1.28]
[[[wd(0,a)]/netbsd][-adrs]] :- 
798720+36864+581040+[54300+60192]=0x275cf4
entry point at 0x100020
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 1.2E (puijo0) #2: Wed Jun 25 15:38:59 EET DST 1997
    tmo@hylly.ssh.fi:/usr/local/kernel/test
cpu0: family 5 model 2 step 5
cpu0: Intel Pentium (P54C) (586-class)
real mem  = 16384000
avail mem = 13549568
using 225 buffers containing 921600 bytes of memory
mainbus0 (root)
... <rest of boot messages removed>
# cd tmp 
# ls -lag
total 324
drwxrwxrwt   2 root  wheel     512 Nov 16 13:37 .
drwxr-xr-x  21 tmo   wheel    1024 Oct 29 09:37 ..
-rwxr-xr-x   1 root  wheel    8845 Nov 16 13:37 a.out
-rw-r--r--   1 root  wheel     577 Nov 16 13:37 t.c
# sync
# gcc -DNO_BUG t.c
# ./a.out /dev/wd0b
# ./a.out /dev/rwd0b
# gcc t.c
# ./a.out /dev/rwd0b
panic: ptdi 731063
syncing disks... 1 1 done

dumping to dev 1, offset 370432
...