Subject: port-i386/4089: Prevent disklabel from destroying boot blocks
To: None <gnats-bugs@gnats.netbsd.org>
From: None <hiroy@netcom.com>
List: netbsd-bugs
Date: 09/05/1997 08:02:53
>Number:         4089
>Category:       port-i386
>Synopsis:       Prevent disklabel from destroying boot blocks
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Sep  5 08:05:00 1997
>Last-Modified:
>Originator:     Hiroyuki Ito
>Organization:
	None
>Release:        NetBSD-current 1997/08/28
>Environment:
System: NetBSD 1.2G i386


>Description:
	disklabel -Rr disk protofile
or
	disklabel -wr disk disktype
can destroy boot blocks. this is not a good thing.

>How-To-Repeat:
% uname -srm
NetBSD 1.2G i386
% sysctl kern.securelevel
kern.securelevel = -1
% alias hd hexdump -e \''"%06_ax " 16/1 " %02x"'\'\
                 -e \''"  " "%_p"'\' -e \''"\n"'\'
% alias hd
hexdump -e '"%06_ax " 16/1 " %02x"' -e '"  " "%_p"' -e '"\n"'
% jot -c -s "" -n 512 229 - 0 > e5
% hd e5
000000  e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5 e5  ................
*
% mount | head -1
/dev/sd0a on / type ffs (local)
% whoami
root
% /sbin/disklabel sd0 > protofile
% /sbin/disklabel -r sd0 | diff protofile -
% egrep '^#|^  [ac]:' protofile
# /dev/rsd0d:
#        size   offset    fstype   [fsize bsize   cpg]
  a:    65536   491520    4.2BSD     1024  8192    16 	# (Cyl.  240 - 271)
  c:  3686400   491520    unused        0     0       	# (Cyl.  240 - 2039)
% 
% dd if=/dev/rsd0a of=xxx count=16
16+0 records in
16+0 records out
8192 bytes transferred in 1 secs (8192 bytes/sec)
% hd xxx | head -2
000000  66 ea 08 00 00 00 c0 07 8c c8 8e d8 66 b8 00 01  f...........f...
000010  00 00 8e d0 66 bc fc ff 00 00 8e c0 80 fa 80 66  ....f..........f
% hd -s `expr 512 \* 2` xxx | head -2
000400  fa 67 66 0f 01 15 00 01 00 00 0f 20 c0 66 83 c8  .gf........ .f..
000410  01 0f 22 c0 66 ea 1c 04 00 00 18 00 b8 20 00 00  ..".f........ ..
% dd if=e5 of=xxx seek=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes transferred in 1 secs (512 bytes/sec)
% /sbin/disklabel -W sd0
% dd if=xxx of=/dev/rsd0a
16+0 records in
16+0 records out
8192 bytes transferred in 1 secs (8192 bytes/sec)
% /sbin/disklabel -N sd0
% /sbin/disklabel -r sd0
disklabel: no disk label
% /sbin/disklabel -Rr sd0 protofile
% /sbin/disklabel -r sd0 | diff protofile -
% dd if=/dev/rsd0a of=xxx count=16
16+0 records in
16+0 records out
8192 bytes transferred in 1 secs (8192 bytes/sec)
% hd -n 512 xxx
000000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
*
% hd -s `expr 512 \* 2` xxx
000400  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
*
% 
% /usr/mdec/installboot /usr/mdec/biosboot.sym /dev/rsd0a
% dd if=/dev/rsd0a of=xxx count=16
16+0 records in
16+0 records out
8192 bytes transferred in 1 secs (8192 bytes/sec)
% hd xxx | head -2
000000  66 ea 08 00 00 00 c0 07 8c c8 8e d8 66 b8 00 01  f...........f...
000010  00 00 8e d0 66 bc fc ff 00 00 8e c0 80 fa 80 66  ....f..........f
% hd -s `expr 512 \* 2` xxx | head -2
000400  fa 67 66 0f 01 15 00 01 00 00 0f 20 c0 66 83 c8  .gf........ .f..
000410  01 0f 22 c0 66 ea 1c 04 00 00 18 00 b8 20 00 00  ..".f........ ..
% 
% sed 's/mysd/mysd0/' protofile > protofile0
% ./disklabel -r sd0 | diff - protofile0
3c3
< disk: mysd
---
> disk: mysd0
% hd -v xxx > xxx.hd
% dd if=e5 of=xxx seek=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes transferred in 1 secs (512 bytes/sec)
% ./disklabel -W sd0
% dd if=xxx of=/dev/rsd0a
16+0 records in
16+0 records out
8192 bytes transferred in 1 secs (8192 bytes/sec)
% ./disklabel -N sd0
% ./disklabel -r sd0
disklabel: no disk label
% ./disklabel -Rr sd0 protofile0
% ./disklabel -r sd0 | diff protofile0 -
% hd -v -n `expr 512 \* 16` /dev/rsd0a | diff xxx.hd -
33c33
< 000200  57 45 56 82 04 00 00 00 6d 79 73 64 00 00 00 00  WEV.....mysd....
---
> 000200  57 45 56 82 04 00 00 00 6d 79 73 64 30 00 00 00  WEV.....mysd0...
41c41
< 000280  00 00 00 00 57 45 56 82 a8 52 08 00 00 20 00 00  ....WEV..R... ..
---
> 000280  00 00 00 00 57 45 56 82 98 52 08 00 00 20 00 00  ....WEV..R... ..
% 

>Fix:

*** disklabel.c.orig	Thu Jul 10 18:28:47 1997
--- disklabel.c	Thu Sep  4 07:13:29 1997
***************
*** 420,428 ****
  	char *boot;
  	struct disklabel *lp;
  {
- 	int writeable;
- 	off_t sectoffset = 0;
- 
  #if NUMBOOT > 0
  	setbootflag(lp);
  #endif
--- 420,425 ----
***************
*** 431,439 ****
  	lp->d_checksum = 0;
  	lp->d_checksum = dkcksum(lp);
  	if (rflag) {
! #ifdef __i386__
! 		struct partition *pp = &lp->d_partitions[2];
  
  		/*
  		 * If NetBSD/i386 DOS partition is missing, or if 
  		 * the label to be written is not within partition,
--- 428,438 ----
  	lp->d_checksum = 0;
  	lp->d_checksum = dkcksum(lp);
  	if (rflag) {
! 		int writeable;
! 		off_t sectoffset = 0;
! 		size_t nbytes_to_write = lp->d_bbsize;
  
+ #ifdef __i386__
  		/*
  		 * If NetBSD/i386 DOS partition is missing, or if 
  		 * the label to be written is not within partition,
***************
*** 442,452 ****
  		 * In this case, partition 'a' had better start at 0,
  		 * otherwise we reject the request as meaningless. -wfj
  		 */
! 		if (dosdp && dosdp->dp_typ == DOSPTYP_386BSD && pp->p_size &&
! 			dosdp->dp_start == pp->p_offset) {
! 		        sectoffset = pp->p_offset * lp->d_secsize;
! 		} else {
! 			if (dosdp) {
  				int first, ch;
  
  				(void) printf("Erase the previous contents of the disk? [n]: ");
--- 441,453 ----
  		 * In this case, partition 'a' had better start at 0,
  		 * otherwise we reject the request as meaningless. -wfj
  		 */
! 		if (dosdp) {
! 			struct partition *pp = &lp->d_partitions[2];
! 
! 			if (dosdp->dp_typ == DOSPTYP_386BSD && pp->p_size &&
! 				dosdp->dp_start == pp->p_offset) {
! 				sectoffset = pp->p_offset * lp->d_secsize;
! 			} else {
  				int first, ch;
  
  				(void) printf("Erase the previous contents of the disk? [n]: ");
***************
*** 457,464 ****
  				if (first != 'y' && first != 'Y')
  					exit(0);
  			}
- 			sectoffset = 0;
  		}
  #endif
  
  		/*
--- 458,467 ----
  				if (first != 'y' && first != 'Y')
  					exit(0);
  			}
  		}
+ 		sectoffset += (char *)lp - boot;
+ 		boot = (char *)lp;
+ 		nbytes_to_write = DEV_BSIZE;
  #endif
  
  		/*
***************
*** 501,507 ****
  			dp[63] = sum;
  		}
  #endif
! 		if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
  			perror("write");
  			return (1);
  		}
--- 504,510 ----
  			dp[63] = sum;
  		}
  #endif
! 		if (write(f, boot, nbytes_to_write) != nbytes_to_write) {
  			perror("write");
  			return (1);
  		}
>Audit-Trail:
>Unformatted: