From nobody@FreeBSD.org  Thu Oct 20 16:10:14 2011
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 5FFD3106566C
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 20 Oct 2011 16:10:14 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 3687C8FC0C
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 20 Oct 2011 16:10:14 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id p9KGADvp005794
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 20 Oct 2011 16:10:13 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id p9KGADxe005793;
	Thu, 20 Oct 2011 16:10:13 GMT
	(envelope-from nobody)
Message-Id: <201110201610.p9KGADxe005793@red.freebsd.org>
Date: Thu, 20 Oct 2011 16:10:13 GMT
From: Tim Brody <tdb2@ecs.soton.ac.uk>
To: freebsd-gnats-submit@FreeBSD.org
Subject: sysinstall has a 32 disk limit
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         161837
>Category:       kern
>Synopsis:       [libdisk] [patch] sysinstall(8) has a 32 disk limit
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-sysinstall
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 20 16:20:05 UTC 2011
>Closed-Date:    
>Last-Modified:  Thu Oct 20 19:36:02 UTC 2011
>Originator:     Tim Brody
>Release:        8.20
>Organization:
University of Southampton
>Environment:
n/a
>Description:
sysinstall calls libdisk/Disk_Names that has a hard-limit of 32 disk
devices. On systems (e.g. Sun X4540) with more disks than this some
drives will be silently ignored. On the X4540 the missing drives include
the 4 bootable devices, making it impossible to install with sysinstall/
fdisk (hence severity=high).

This problem was first identified 10 years ago when the number was bumped
from 20 to 32 - http://www.cz.freebsd.org/pub/FreeBSD-cvs/gnats/conf/24503.

Further (but unpatched), sysinstall/devices.c does not free the contents
of the disks array so will cause a memory leak.
>How-To-Repeat:

>Fix:
Apply attached patch to libdisk, recompile/reinstall libdisk and sysinstall.

Patch attached with submission follows:

Index: libdisk.h
===================================================================
--- libdisk.h	(revision 226570)
+++ libdisk.h	(working copy)
@@ -17,9 +17,6 @@
 /* You can define a particular architecture here if you are debugging. */
 /* #define P_DEBUG p_sparc64 */
 
-#define MAX_NO_DISKS	32
-/* Max # of disks Disk_Names() will return */
-
 #define MAX_SEC_SIZE    2048  /* maximum sector size that is supported */
 #define MIN_SEC_SIZE	512   /* the sector size to end sensing at */
 
Index: disk.c
===================================================================
--- disk.c	(revision 226570)
+++ disk.c	(working copy)
@@ -190,7 +190,7 @@
 char **
 Disk_Names()
 {
-	int disk_cnt;
+	int i, disk_cnt;
 	char **disks;
 	int error;
 	size_t listsize;
@@ -205,30 +205,36 @@
 	if (listsize == 0)
 		return (NULL);
 
-	disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS));
-	if (disks == NULL)
+	disk1 = disklist = (char *)calloc(listsize + 1, sizeof *disklist);
+	if (disklist == NULL)
 		return NULL;
-	disk1 = disklist = (char *)malloc(listsize + 1);
-	if (disklist == NULL) {
-		free(disks);
-		return NULL;
-	}
-	memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS));
-	memset(disklist, 0, listsize + 1);
+
 	error = sysctlbyname("kern.disks", disklist, &listsize, NULL, 0);
 	if (error || disklist[0] == 0) {
 		free(disklist);
-		free(disks);
 		return NULL;
 	}
-	for (disk_cnt = 0; disk_cnt < MAX_NO_DISKS; disk_cnt++) {
+
+	disk_cnt = 1;
+	for (i = 0; i < listsize; ++i) {
+		if (disklist[i] == ' ')
+			disk_cnt++;
+	}
+
+	disks = calloc(disk_cnt + 1, sizeof *disks);
+	if (disks == NULL) {
+		free(disklist);
+		return NULL;
+	}
+
+	for (i = 0; i < disk_cnt; ++i) {
 		disk2 = strsep(&disk1, " ");
 		if (disk2 == NULL)
 			break;
-		disks[disk_cnt] = strdup(disk2);
-		if (disks[disk_cnt] == NULL) {
-			for (disk_cnt--; disk_cnt >= 0; disk_cnt--)
-				free(disks[disk_cnt]);
+		disks[i] = strdup(disk2);
+		if (disks[i] == NULL) {
+			for (i--; i >= 0; i--)
+				free(disks[i]);
 			free(disklist);
 			free(disks);
 			return (NULL);


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-sysinstall 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Oct 20 19:34:42 UTC 2011 
Responsible-Changed-Why:  
reclassify and assign. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=161837 
>Unformatted:
