NetBSD Problem Report #36544

From woods@building.weird.com  Sun Jun 24 02:55:17 2007
Return-Path: <woods@building.weird.com>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id AA43F63B8E6
	for <gnats-bugs@gnats.netbsd.org>; Sun, 24 Jun 2007 02:55:17 +0000 (UTC)
Message-Id: <m1I2IFx-002IwcC@building.weird.com>
Date: Sat, 23 Jun 2007 22:55:17 -0400 (EDT)
From: "Greg A. Woods" <woods@planix.com>
Sender: "Greg A. Woods" <woods@building.weird.com>
Reply-To: "Greg A. Woods" <woods@planix.com>
To: gnats-bugs@NetBSD.org
Subject: UID_MAX and GID_MAX should reflect the unsigned nature of uid_t and gid_t
X-Send-Pr-Version: 3.95

>Number:         36544
>Category:       standards
>Synopsis:       UID_MAX and GID_MAX should reflect the unsigned nature of uid_t and gid_t
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    standards-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 24 03:00:01 +0000 2007
>Originator:     Greg A. Woods
>Release:        netbsd-current 2007/06/22
>Organization:
Planix, Inc.; Toronto, Ontario; Canada
>Environment:


System: NetBSD
>Description:

	UID_MAX and GID_MAX should reflect the unsigned nature of uid_t
	and gid_t

	this is consistent with the actual maximum values allowed by
	other types of systems that went to uint32_t types for uid_t,
	such as AIX

	This also allows for an entry into master.passwd that truly
	represents the the default NFS anonymous user:

	nfsanon:*:4294967294:4294967294::0:0:NFS anonymous (-2@32) user:/nonexistant:/sbin/nologin


>How-To-Repeat:

>Fix:

	note that there may be yet more things that need tweaking
	elsewhere throughout the system after this change is made.

	Please contact me for assistance if necessary.  I've been
	running many systems with this change since before 1.6.

Index: sys/sys/syslimits.h
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/sys/sys/syslimits.h,v
retrieving revision 1.23
diff -u -r1.23 syslimits.h
--- sys/sys/syslimits.h	11 Dec 2005 12:25:21 -0000	1.23
+++ sys/sys/syslimits.h	3 May 2006 21:15:48 -0000
@@ -42,13 +42,13 @@
 #ifndef CHILD_MAX
 #define	CHILD_MAX		  160	/* max simultaneous processes */
 #endif
-#define	GID_MAX		   2147483647U	/* max value for a gid_t (2^31-2) */
+#define	GID_MAX	       ((~(uid_t)0)-1)	/* max value for a gid_t (2^32-2) */
 #define	LINK_MAX		32767	/* max file link count */
 #define	MAX_CANON		  255	/* max bytes in term canon input line */
 #define	MAX_INPUT		  255	/* max bytes in terminal input */
 #define	NAME_MAX		  255	/* max bytes in a file name */
 #define	NGROUPS_MAX		   16	/* max supplemental group id's */
-#define	UID_MAX		   2147483647U	/* max value for a uid_t (2^31-2) */
+#define	UID_MAX	      ((~(uid_t)0)-1)	/* max value for a uid_t (2^32-2) */
 #ifndef OPEN_MAX
 #define	OPEN_MAX		   64	/* max open files per process */
 #endif


	NOTE:  these next diffs are against netbsd-1-6


Index: lib/libc/gen/pw_scan.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/lib/libc/gen/pw_scan.c,v
retrieving revision 1.11
diff -u -r1.11 pw_scan.c
--- lib/libc/gen/pw_scan.c	29 Jan 2002 10:20:30 -0000	1.11
+++ lib/libc/gen/pw_scan.c	19 Jan 2005 22:18:02 -0000
@@ -34,9 +34,34 @@
  */

 #if HAVE_CONFIG_H
-#include "config.h"
-#include "compat_pwd.h"
-#else
+
+/*
+ * XXX including the source tree's sys/syslimits.h is a very bad hack that will
+ * fail on non-*BSD systems where config.h will then include <limits.h> and/or
+ * <sys/syslimits.h> from the host system and those includes won't be protected
+ * from multiple inclusion, causing clashes between host definitions and those
+ * from the source tree's sys/syslimits.h.  It works on *BSD because the host's
+ * <sys/syslimits.h> uses the very same multiple inclusion protection trick
+ * that the source tree's variant does and so this allows our tree's
+ * definitions to take precedence.  For SunOS-5 it may suffice to pre-define
+ * _LIMITS_H though....
+ */
+# include "../../sys/sys/syslimits.h"
+# define _LIMITS_H
+# include "config.h"
+# include "compat_pwd.h"
+
+/*
+ * XXX recent changes to compat/compat_defs.h turned on _POSIX_C_SOURCE and
+ * turned off _NETBSD_SOURCE so when <stdlib.h> is included we don't have a
+ * prototype for strtouq() and this causes sign extension of the result.  Yuck!
+ * Even though those changes have been backed out, we'll keep this prototype in
+ * here for safety....
+ */
+u_quad_t strtouq __P((const char * __restrict, char ** __restrict, int));
+
+#else  /* !HAVE_CONFIG_H */
+
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
 __RCSID("$NetBSD: pw_scan.c,v 1.11 2002/01/29 10:20:30 tv Exp $");
@@ -49,6 +74,7 @@

 #include <assert.h>
 #include <err.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <pwd.h>
 #include <stdio.h>
@@ -71,11 +97,17 @@
 	struct passwd *pw;
 	int *flags;
 {
-	unsigned long id;
+	uint64_t id;
 	int root, inflags;
 	char *ep;
 	const char *p, *sh;

+#if 0
+	assert(sizeof(uint64_t) >= sizeof(u_quad_t));	/* that strtouq() fits into id */
+	assert(UID_MAX < UINT64_MAX);			/* that overflow detection works */
+	assert(GID_MAX < UINT64_MAX);
+#endif
+
 	_DIAGASSERT(bp != NULL);
 	_DIAGASSERT(pw != NULL);

@@ -87,6 +119,19 @@

 	if (!(pw->pw_name = strsep(&bp, ":")))		/* login */
 		goto fmt;
+	if (strlen(pw->pw_name) > (LOGIN_NAME_MAX - 1)) {
+		if (!(inflags & _PASSWORD_NOWARN))
+			warnx("username too long, '%s' > %d", pw->pw_name, LOGIN_NAME_MAX - 1);
+		return (0);
+	}
+#if 0
+	/*
+	 * XXX something akin to this AWK code from /etc/security should also be done:
+	 * 
+	 *	if ($1 !~ /^[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])*$/)
+	 *		printf "Login %s has non-alphanumeric characters.\n", $1;
+	 */
+#endif
 	root = !strcmp(pw->pw_name, "root");

 	if (!(pw->pw_passwd = strsep(&bp, ":")))	/* passwd */
@@ -94,29 +139,39 @@

 	if (!(p = strsep(&bp, ":")))			/* uid */
 		goto fmt;
-	id = strtoul(p, &ep, 10);
+	id = strtouq(p, &ep, 10);
 	if (root && id) {
 		if (!(inflags & _PASSWORD_NOWARN))
 			warnx("root uid should be 0");
 		return (0);
 	}
-	if (id > UID_MAX || *ep != '\0') {
+	if (*ep != '\0') {
 		if (!(inflags & _PASSWORD_NOWARN))
 			warnx("invalid uid '%s'", p);
 		return (0);
 	}
+	if (id > (uint64_t) UID_MAX) {
+		if (!(inflags & _PASSWORD_NOWARN))
+			warnx("uid too big, '%s' > %" PRIu64, p, (uint64_t) UID_MAX);
+		return (0);
+	}
 	pw->pw_uid = (uid_t)id;
 	if ((*p == '\0') && (flags != (int *)NULL))
 		*flags |= _PASSWORD_NOUID;

 	if (!(p = strsep(&bp, ":")))			/* gid */
 		goto fmt;
-	id = strtoul(p, &ep, 10);
-	if (id > GID_MAX || *ep != '\0') {
+	id = strtouq(p, &ep, 10);
+	if (*ep != '\0') {
 		if (!(inflags & _PASSWORD_NOWARN))
 			warnx("invalid gid '%s'", p);
 		return (0);
 	}
+	if (id > (uint64_t) GID_MAX) {
+		if (!(inflags & _PASSWORD_NOWARN))
+			warnx("gid too big, '%s' > %" PRIu64, p, (uint64_t) GID_MAX);
+		return (0);
+	}
 	pw->pw_gid = (gid_t)id;
 	if ((*p == '\0') && (flags != (int *)NULL))
 		*flags |= _PASSWORD_NOGID;
Index: lib/libc/gen/pwcache.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/lib/libc/gen/pwcache.c,v
retrieving revision 1.21.2.1
diff -u -r1.21.2.1 pwcache.c
--- lib/libc/gen/pwcache.c	23 Jul 2004 14:33:14 -0000	1.21.2.1
+++ lib/libc/gen/pwcache.c	6 Sep 2004 22:44:25 -0000
@@ -191,7 +191,7 @@
 		return (0);
 	if (uidtb_fail)
 		return (-1);
-	if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
+	if ((uidtb = (UIDC **) calloc((size_t) UID_SZ, sizeof(UIDC *))) == NULL) {
 		++uidtb_fail;
 		return (-1);
 	}
@@ -212,7 +212,7 @@
 		return (0);
 	if (gidtb_fail)
 		return (-1);
-	if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
+	if ((gidtb = (GIDC **) calloc((size_t) GID_SZ, sizeof(GIDC *))) == NULL) {
 		++gidtb_fail;
 		return (-1);
 	}
@@ -233,7 +233,7 @@
 		return (0);
 	if (usrtb_fail)
 		return (-1);
-	if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
+	if ((usrtb = (UIDC **) calloc((size_t) UNM_SZ, sizeof(UIDC *))) == NULL) {
 		++usrtb_fail;
 		return (-1);
 	}
@@ -254,7 +254,7 @@
 		return (0);
 	if (grptb_fail)
 		return (-1);
-	if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
+	if ((grptb = (GIDC **) calloc((size_t) GNM_SZ, sizeof(GIDC *))) == NULL) {
 		++grptb_fail;
 		return (-1);
 	}
@@ -314,7 +314,7 @@
 		if (ptr == NULL)
 			return (NULL);
 		ptr->uid = uid;
-		(void)snprintf(ptr->name, UNMLEN, "%lu", (long) uid);
+		(void)snprintf(ptr->name, UNMLEN, "%lu", (unsigned long int) uid);
 		ptr->valid = INVALID;
 		if (noname)
 			return (NULL);
@@ -325,7 +325,7 @@
 		if (ptr == NULL)
 			return (pw->pw_name);
 		ptr->uid = uid;
-		(void)strlcpy(ptr->name, pw->pw_name, UNMLEN);
+		(void) strlcpy(ptr->name, pw->pw_name, (size_t) UNMLEN);
 		ptr->valid = VALID;
 	}
 	return (ptr->name);
@@ -384,7 +384,7 @@
 		if (ptr == NULL)
 			return (NULL);
 		ptr->gid = gid;
-		(void)snprintf(ptr->name, GNMLEN, "%lu", (long) gid);
+		(void) snprintf(ptr->name, (size_t) GNMLEN, "%lu", (unsigned long int) gid);
 		ptr->valid = INVALID;
 		if (noname)
 			return (NULL);
@@ -395,7 +395,7 @@
 		if (ptr == NULL)
 			return (gr->gr_name);
 		ptr->gid = gid;
-		(void)strlcpy(ptr->name, gr->gr_name, GNMLEN);
+		(void) strlcpy(ptr->name, gr->gr_name, (size_t) GNMLEN);
 		ptr->valid = VALID;
 	}
 	return (ptr->name);
@@ -456,7 +456,7 @@
 		*uid = pw->pw_uid;
 		return (0);
 	}
-	(void)strlcpy(ptr->name, name, UNMLEN);
+	(void) strlcpy(ptr->name, name, (size_t) UNMLEN);
 	if ((pw = (*_pwcache_getpwnam)(name)) == NULL) {
 		ptr->valid = INVALID;
 		return (-1);
@@ -522,7 +522,7 @@
 		return (0);
 	}

-	(void)strlcpy(ptr->name, name, GNMLEN);
+	(void) strlcpy(ptr->name, name, (size_t) GNMLEN);
 	if ((gr = (*_pwcache_getgrnam)(name)) == NULL) {
 		ptr->valid = INVALID;
 		return (-1);

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.