Subject: bin/32102: newfs -O 0 does not respect the 4.2BSD inode format for uid and gid
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Pavel Cahyna <pcah8322@artax.karlin.mff.cuni.cz>
List: netbsd-bugs
Date: 11/17/2005 22:43:00
>Number:         32102
>Category:       bin
>Synopsis:       newfs -O 0 does not respect the 4.2BSD inode format for uid and gid
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Nov 17 22:43:00 +0000 2005
>Originator:     Pavel Cahyna
>Release:        NetBSD 3.0_BETA
>Organization:
>Environment:
System: NetBSD beta 3.0_BETA NetBSD 3.0_BETA (BETA) #4: Fri Oct 7 21:20:07 CEST 2005 root@beta:/usr/src/sys/arch/alpha/compile/BETA alpha
Architecture: alpha
Machine: alpha
>Description:
The old inode format has 16-bit UID and GID stored in a different
position than the default 4.4BSD format. newfs sets the owner/group of
root directory to the current user, but forgets to take this
difference into account.
>How-To-Repeat:
pavel:/usr/src/sbin/newfs$ ./newfs -O 0 -T floppy -s 2880s -Z -F ~/42bsd.img
Creating file system image in `/home/pavel/42bsd.img', size 1474560 bytes, in 16384 byte chunks.
/home/pavel/42bsd.img: 1.4MB (2880 sectors) block size 4096, fragment size 512
        using 4 cylinder groups of 0.35MB, 90 blks, 160 inodes.
super-block backups (for fsck -b #) at:
   32,  752, 1472, 2192,
pavel:/usr/src/sbin/newfs$ su -                                              
Terminal type is xterm.
root:~# vnconfig vnd0 ~pavel/42bsd.img  
root:~# mount -r /dev/vnd0a /mnt/pokus 
root:~# ls -ld /mnt/pokus/
drwxr-xr-x  2 root  wheel  512 Jan  1  1970 /mnt/pokus/
root:~# umount /mnt/pokus/              
root:~# vnconfig -u vnd0

Compare with:

pavel:/usr/src/sbin/newfs$ ./newfs -T floppy -s 2880s -Z -F ~/44bsd.img      
Creating file system image in `/home/pavel/44bsd.img', size 1474560 bytes, in 16384 byte chunks.
/home/pavel/44bsd.img: 1.4MB (2880 sectors) block size 4096, fragment size 512
        using 4 cylinder groups of 0.35MB, 90 blks, 160 inodes.
super-block backups (for fsck -b #) at:
   32,  752, 1472, 2192,
pavel@beta:/usr/src/sbin/newfs$ su - 
Terminal type is xterm.
root:~# vnconfig vnd0 ~pavel/44bsd.img  
root:~# mount -r /dev/vnd0a /mnt/pokus 
root:~# ls -ld /mnt/pokus/ 
drwxr-xr-x  2 pavel  users  512 Jan  1  1970 /mnt/pokus/
root:~# umount /mnt/pokus/ 
root:~# vnconfig -u vnd0 
>Fix:
Index: sbin/newfs/mkfs.c
===================================================================
RCS file: /cvsroot/src/sbin/newfs/mkfs.c,v
retrieving revision 1.88.2.1
diff -u -r1.88.2.1 mkfs.c
--- sbin/newfs/mkfs.c	6 Nov 2005 13:27:32 -0000	1.88.2.1
+++ sbin/newfs/mkfs.c	17 Nov 2005 22:33:34 -0000
@@ -1010,8 +1010,16 @@
 			return (0);
 		node.dp1.di_blocks = btodb(fragroundup(&sblock,
 		    node.dp1.di_size));
-		node.dp1.di_uid = geteuid();
-		node.dp1.di_gid = getegid();
+		if (Oflag == 0) {
+			node.dp1.di_u.oldids[0] = (geteuid() <= UINT16_MAX) ? \
+						  geteuid() : 0;
+			node.dp1.di_u.oldids[1] = (getegid() <= UINT16_MAX) ? \
+						  getegid() : 0; 
+		} else {
+			node.dp1.di_uid = geteuid();
+			node.dp1.di_gid = getegid();
+		}
+
 		wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), node.dp1.di_size,
 		    buf);
 	} else {
@@ -1045,12 +1053,30 @@
 	if (Oflag <= 1) {
 		if (mfs) {
 			node.dp1.di_mode = IFDIR | mfsmode;
-			node.dp1.di_uid = mfsuid;
-			node.dp1.di_gid = mfsgid;
+			if (Oflag == 0) {
+				node.dp1.di_u.oldids[0] = \
+					(mfsuid <= UINT16_MAX) ? \
+				       	mfsuid : 0;
+				node.dp1.di_u.oldids[1] = \
+					(mfsgid <= UINT16_MAX) ? \
+				       	mfsgid : 0; 
+			} else {
+				node.dp1.di_uid = mfsuid;
+				node.dp1.di_gid = mfsgid;
+			}
 		} else {
 			node.dp1.di_mode = IFDIR | UMASK;
-			node.dp1.di_uid = geteuid();
-			node.dp1.di_gid = getegid();
+			if (Oflag == 0) {
+				node.dp1.di_u.oldids[0] = \
+					(geteuid() <= UINT16_MAX) ? \
+				       	geteuid() : 0;
+				node.dp1.di_u.oldids[1] = \
+					(getegid() <= UINT16_MAX) ? \
+				       	getegid() : 0; 
+			} else {
+				node.dp1.di_uid = geteuid();
+				node.dp1.di_gid = getegid();
+			}
 		}
 		node.dp1.di_nlink = PREDEFDIR;
 		if (Oflag == 0)