Subject: misc/15650: MAKEDEV generates bogus minor numbers for ptys
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kre@munnari.OZ.AU>
List: netbsd-bugs
Date: 02/18/2002 10:08:20
>Number:         15650
>Category:       misc
>Synopsis:       MAKEDEV generates bogus minor numbers for ptys
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    misc-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 17 21:30:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Robert Elz
>Release:        NetBSD 1.5ZA  (sources of 2002-02-15)
>Organization:
	Prince of Songkla University
>Environment:
	<The following information is extracted from your kernel. Please>
	<append output of "ldd", "ident" where relevant (multiple lines).>
System: NetBSD fuchsia.cs.mu.OZ.AU 1.5ZA NetBSD 1.5ZA (FUCHSIA) #4: Mon Dec 24 01:56:02 ICT 2001 kre@fuchsia:/usr/obj/sys/FUCHSIA i386
Architecture: i386
Machine: i386
>Description:
	The new MAKEDEV (lots of ptys) generates bogus minor numbers for
	all but the first 16 ptys.    Bogus in the sense that there are
	lots of gaps in the numbering, and they're no longer compatible
	with what existed before (which is the obvious aim of the new
	numbering scheme).   Quite likely everything will still work, except
	with monor device numbers up to 1681 instead of the intended 991

	This is all because of a small typo/thinko
	in the calculations.
>How-To-Repeat:
	Using a new MAKEDEV (line i386 version 1.168)
		/dev/MAKEDEV pty1
		ls -l ptyq*

	Or by changing the MAKEDEV script so that it does "echo mknod"
	instead of mknod (and call that M), and running the folloowing:

	[Don't run it as root, ignore errors from chown & chmod - or nobble
	those as well]

sh M  `for n in 0 1 2 3 4 5 6 7 8 9 10 11 112 13 14 15; do echo pty$n; done` |
	grep 'mknod pty' | awk '$5 == prev + 1 {
		prev = $5
		next
	}
	{
		if (last != "") {
			print name, last, prev
		}
		name = $2
		last = $5
		prev = $5
	}
	END {
		print name, last, prev
	}
'

	Observe the result ...

ptyp0 0 15
ptypg 256 301
ptyq0 62 77
ptyqg 348 393
ptyr0 124 139
ptyrg 440 485
ptys0 186 201
ptysg 532 577
ptyt0 248 263
ptytg 624 669
ptyu0 310 325
ptyug 716 761
ptyw0 434 449
ptywg 900 945
ptyx0 496 511
ptyxg 992 1037
ptyy0 558 573
ptyyg 1084 1129
ptyz0 620 635
ptyzg 1176 1221
ptyP0 682 697
ptyPg 1268 1313
ptyR0 806 821
ptyRg 1452 1497
ptyS0 868 883
ptySg 1544 1589
ptyT0 930 945
ptyTg 1636 1681

	(Aside: ttyv is missing because this is an i386, that's OK).

	The columns are the name of the first pty in a blok of consecutive
	minor numbers, and the other two columns are the first & last minor
	numbers in the block.

	Apply the patch below, run the same script, and the results will be ...

ptyp0 0 15
ptypg 256 301
ptyq0 16 31
ptyqg 302 347
ptyr0 32 47
ptyrg 348 393
ptys0 48 63
ptysg 394 439
ptyt0 64 79
ptytg 440 485
ptyu0 80 95
ptyug 486 531
ptyw0 112 127
ptywg 578 623
ptyx0 128 143
ptyxg 624 669
ptyy0 144 159
ptyyg 670 715
ptyz0 160 175
ptyzg 716 761
ptyP0 176 191
ptyPg 762 807
ptyR0 208 223
ptyRg 854 899
ptyS0 224 239
ptySg 900 945
ptyT0 240 255
ptyTg 946 991

	Which I believe was what was intended.

>Fix:

	Apply the following patch to src/etc/etc.i386/MAKEDEV
	and repeat for every other etc.*/MAKEDEV (though I haven't
	verified that the patch applies cleanly to all those).

	Note: I also addred a few comments explaining the magic
	arithmetic ...  (obviously, that part is optional)

	The real change is that one instance of "62" should be "16"
	(the same as it used to be for pty, before all the new ones
	were added - which if you think about it, since compatability
	is the aim, must be correct).


--- MAKEDEV.ORIG	Tue Feb 12 17:32:04 2002
+++ MAKEDEV	Mon Feb 18 09:45:03 2002
@@ -601,9 +601,13 @@
 		j=`echo 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | dd bs=1 count=1 skip=$jn 2>/dev/null`
 		skip=0
 		if [ $jn -ge 16 ]; then
+		  # minor is 256 + $class * (62 - 16) + ($jn - 16)
+		  # then skip that many, less what will be added below:
+		  # 256 + $class * (62 - 16) + ($jn - 16) - ($class * 16 + $jn)
+		  # which simplifies to ...
 			skip=$(($class * 30 + 256 - 16))
 		fi
-		unit=$(($class * 62 + $jn + $skip))
+		unit=$(($class * 16 + $jn + $skip))
 		mknod tty$name$j c 5 $unit
 		mknod pty$name$j c 6 $unit
 		jn=$(($jn + 1))
>Release-Note:
>Audit-Trail:
>Unformatted: