Date: Sat, 27 May 2006 14:37:55 +0400 (MSD) From: Yar Tikhiy <yar@comp.chem.msu.su> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/98005: loader corrupts other files when rewriting nextboot.conf Message-ID: <200605271037.k4RAbtYw063346@comp.chem.msu.su> Resent-Message-ID: <200605271040.k4RAeJY9030900@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 98005 >Category: bin >Synopsis: loader corrupts other files when rewriting nextboot.conf >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat May 27 10:40:17 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Yar Tikhiy >Release: FreeBSD 7.0-CURRENT i386 >Organization: None >Environment: System: FreeBSD 7.0-CURRENT FreeBSD 7.0-CURRENT #1: Thu May 25 19:55:44 UTC 2006 root@:/usr/obj/usr/src/sys/GENERIC i386 >Description: When nextboot is in effect, loader(8) writes the modified contents of the nextboot.conf file, or whatever nextboot_conf is set to, to an incorrect location on the disk. The location overwritten is in the block after the one actually belonging to the nextboot.conf file. This problem is likely to be caused by an off-by-one bug in the stand-alone FS access library used by loader(8). >How-To-Repeat: ### Here's an example. Booting in the following environment: # cat /boot/loader.conf beastie_disable="YES" nextboot_conf="/root/foo" # cat /root/foo nextboot_enable="YES" kernel="${kernel}" kernel_options="${kernel_options}" ### After the reboot, /boot/kernel/kernel.symbols appears damaged: # /root/ckroot 378c378 < MD5 (/boot/kernel/kernel.symbols) = 98d1d52fed7985df0712618de7db8e03 --- > MD5 (/boot/kernel/kernel.symbols) = b42770ba4b010e8aed83ca89440ae79b ### Inspecting its contents. Note the `nextboot_enable="NO" ' string. ### It apparently came from rewrite_nextboot_file in support.4th. # hd /boot/kernel/kernel.symbols | grep -A8 nextboot_enable 000a0000 6e 65 78 74 62 6f 6f 74 5f 65 6e 61 62 6c 65 3d |nextboot_enable=| 000a0010 22 4e 4f 22 20 0a 6b 65 72 6e 65 6c 3d 22 24 7b |"NO" .kernel="${| 000a0020 6b 65 72 6e 65 6c 7d 22 0a 6b 65 72 6e 65 6c 5f |kernel}".kernel_| 000a0030 6f 70 74 69 6f 6e 73 3d 22 24 7b 6b 65 72 6e 65 |options="${kerne| 000a0040 6c 5f 6f 70 74 69 6f 6e 73 7d 22 0a 00 00 00 00 |l_options}".....| 000a0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000a0800 00 00 02 23 0c 0a 20 5a 00 00 05 80 30 01 00 00 |...#.. Z....0...| 000a0810 02 23 10 00 1a 4b 0e 00 00 01 4c 00 00 00 19 30 |.#...K....L....0| ### Let's find out the files' inodes: # ls -if /root/foo /boot/kernel/kernel.symbols 490 /root/foo 36 /boot/kernel/kernel.symbols ### Let's see how the files' blocks are laid out: # fsdb -r /dev/ad0s3a ** /dev/ad0s3a (NO WRITE) Examining file system `/dev/ad0s3a' Last Mounted on / current inode: directory I=2 MODE=40755 SIZE=512 MTIME=May 25 20:46:43 2006 [0 nsec] CTIME=May 25 20:46:43 2006 [0 nsec] ATIME=May 27 12:21:18 2006 [0 nsec] OWNER=root GRP=wheel LINKCNT=20 FLAGS=0 BLKCNT=4 GEN=58ef642f fsdb (inum: 2)> inode 490 current inode: regular file I=490 MODE=100644 SIZE=76 MTIME=May 27 12:15:23 2006 [0 nsec] CTIME=May 27 12:15:23 2006 [0 nsec] ATIME=May 27 12:21:37 2006 [0 nsec] OWNER=root GRP=wheel LINKCNT=1 FLAGS=0 BLKCNT=4 GEN=6f069864 fsdb (inum: 490)> blocks Blocks for inode 490: Direct blocks: 6551 (1 frag) fsdb (inum: 490)> inode 36 current inode: regular file I=36 MODE=100555 SIZE=18022637 MTIME=May 25 19:55:57 2006 [0 nsec] CTIME=May 25 20:22:34 2006 [0 nsec] ATIME=May 27 12:21:19 2006 [0 nsec] OWNER=root GRP=wheel LINKCNT=1 FLAGS=0 BLKCNT=89c0 GEN=3c3ab2a9 fsdb (inum: 36)> blocks Blocks for inode 36: Direct blocks: 6104, 6112, 6120, 6128, 6136, 6144, 6152, 6160, 6200, 6208, 6216, 6224 Indirect blocks: 6232, 6240, 6248, 6256, 6264, 6272, 6280, 6288, 6296, 6304, 6312, 6320, 6328, 6336, 6344, 6352, 6360, 6368, 6376, 6384, 6392, 6400, 6408, 6416, 6424, 6432, 6440, 6448, 6552, 6560, 6568, 6576, 6584, 6592, 6600, 6608, 6616, 6624, 6632, ^^^^ ... ### Note that block 6552 belongs to the damaged file while block 6551 ### contains /root/foo, which plays the role of a nextboot_conf file. ### BTW, 6551 is a fragment address. ### Now we need to know the FS parameters to do some easy math. # dumpfs /dev/ad0s3a | head -20 magic 19540119 (UFS2) time Sat May 27 12:21:51 2006 superblock location 65536 id [ 4475a06c d0014a51 ] ncg 4 size 262144 blocks 253815 bsize 16384 shift 14 mask 0xffffc000 fsize 2048 shift 11 mask 0xfffff800 frag 8 shift 3 fsbtodb 2 minfree 8% optim time symlinklen 120 maxbsize 16384 maxbpg 2048 maxcontig 8 contigsumsize 8 nbfree 20648 ndir 49 nifree 63361 nffree 1229 bpg 8193 fpg 65544 ipg 16448 nindir 2048 inopb 64 maxfilesize 140806241583103 sbsize 2048 cgsize 12288 csaddr 2112 cssize 2048 sblkno 40 cblkno 48 iblkno 56 dblkno 2112 cgrotor 0 fmod 0 ronly 0 clean 1 avgfpdir 64 avgfilesize 16384 flags none fsmnt / volname swuid 0 ... ### Aha, bsize is 16384. 40 blocks precede block 6552 in the damaged ### file according to fsdb. ### Therefore the file offset of block 6552 is 40*16384 = 0xa0000, ### which is exactly the offset of the damaged part (see above.) ### Let's see the raw disk contents. Keep in mind that FFS blocks ### are addressed in a funny way. The "bs" value here isn't bsize, ### but fsize. # dd bs=2048 iseek=6551 count=2 if=/dev/ad0s3a | hd 00000000 6e 65 78 74 62 6f 6f 74 5f 65 6e 61 62 6c 65 3d |nextboot_enable=| 00000010 22 59 45 53 22 0a 6b 65 72 6e 65 6c 3d 22 24 7b |"YES".kernel="${| 00000020 6b 65 72 6e 65 6c 7d 22 0a 6b 65 72 6e 65 6c 5f |kernel}".kernel_| 00000030 6f 70 74 69 6f 6e 73 3d 22 24 7b 6b 65 72 6e 65 |options="${kerne| 00000040 6c 5f 6f 70 74 69 6f 6e 73 7d 22 0a 00 00 00 00 |l_options}".....| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000800 6e 65 78 74 62 6f 6f 74 5f 65 6e 61 62 6c 65 3d |nextboot_enable=| 00000810 22 4e 4f 22 20 0a 6b 65 72 6e 65 6c 3d 22 24 7b |"NO" .kernel="${| 00000820 6b 65 72 6e 65 6c 7d 22 0a 6b 65 72 6e 65 6c 5f |kernel}".kernel_| 00000830 6f 70 74 69 6f 6e 73 3d 22 24 7b 6b 65 72 6e 65 |options="${kerne| 00000840 6c 5f 6f 70 74 69 6f 6e 73 7d 22 0a 00 00 00 00 |l_options}".....| 00000850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 2+0 records in 2+0 records out 4096 bytes transferred in 0.011375 secs (360082 bytes/sec) ### We can see clearly that the loader wrote the modified data ### to the 2048-byte fragment following the correct one. ### And of course, the FS metadata aren't damaged: # fsck -f / ** /dev/ad0s3a ** Last Mounted on / ** Root file system ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames ** Phase 3 - Check Connectivity ** Phase 4 - Check Reference Counts ** Phase 5 - Check Cyl groups 2429 files, 87402 used, 166413 free (1229 frags, 20648 blocks, 0.5% fragmentation) >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200605271037.k4RAbtYw063346>