Module Name:    src
Committed By:   christos
Date:           Tue Sep 20 14:28:53 UTC 2011

Modified Files:
        src/usr.sbin/chroot: chroot.c

Log Message:
- don't use an uninitialized grouplist (from Patrick Welche)
- While here:
        * Allow all numeric users and groups
        * Error check string to number conversion
        * Factor out common code


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/usr.sbin/chroot/chroot.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/chroot/chroot.c
diff -u src/usr.sbin/chroot/chroot.c:1.18 src/usr.sbin/chroot/chroot.c:1.19
--- src/usr.sbin/chroot/chroot.c:1.18	Sun Aug 28 04:32:47 2011
+++ src/usr.sbin/chroot/chroot.c	Tue Sep 20 10:28:52 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: chroot.c,v 1.18 2011/08/28 08:32:47 mbalmer Exp $	*/
+/*	$NetBSD: chroot.c,v 1.19 2011/09/20 14:28:52 christos Exp $	*/
 
 /*
  * Copyright (c) 1988, 1993
@@ -39,13 +39,12 @@
 #if 0
 static char sccsid[] = "@(#)chroot.c	8.1 (Berkeley) 6/9/93";
 #else
-__RCSID("$NetBSD: chroot.c,v 1.18 2011/08/28 08:32:47 mbalmer Exp $");
+__RCSID("$NetBSD: chroot.c,v 1.19 2011/09/20 14:28:52 christos Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 
-#include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <grp.h>
@@ -53,20 +52,69 @@
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
 
 static void	usage(void) __dead;
 
+static int
+getnum(const char *str, uintmax_t *num)
+{
+	char *ep;
+
+	errno = 0;
+
+	*num = strtoumax(str, &ep, 0);
+	if (str[0] == '\0' || *ep != '\0') {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (errno == ERANGE && *num == UINTMAX_MAX)
+		return -1;
+
+	return 0;
+}
+
+
+static gid_t
+getgroup(const char *group)
+{
+	uintmax_t	num;
+	struct group	*gp;
+
+	if ((gp = getgrnam(group)) != NULL)
+		return gp->gr_gid;
+
+	if (getnum(group, &num) == -1)
+	    errx(1, "no such group `%s'", group);
+
+	return (gid_t)num;
+}
+
+static uid_t
+getuser(const char *user)
+{
+	uintmax_t	num;
+	struct passwd	*pw;
+
+	if ((pw = getpwnam(user)) != NULL)
+		return pw->pw_uid;
+
+	if (getnum(user, &num) == -1)
+		errx(1, "no such user `%s'", user);
+
+	return (uid_t)num;
+}
+
 int
 main(int argc, char *argv[])
 {
 	char	*user;		/* user to switch to before running program */
 	char	*group;		/* group to switch to ... */
 	char	*grouplist;	/* group list to switch to ... */
-	struct group	*gp;
-	struct passwd	*pw;
-	char		*endp, *p;
+	char		*p;
 	const char	*shell;
 	gid_t		gid, gidlist[NGROUPS_MAX];
 	uid_t		uid;
@@ -74,8 +122,10 @@
 
 	user = NULL;
 	group = NULL;
+	grouplist = NULL;
 	gid = 0;
 	uid = 0;
+	gids = 0;
 	while ((ch = getopt(argc, argv, "G:g:u:")) != -1) {
 		switch(ch) {
 		case 'u':
@@ -104,52 +154,22 @@
 	if (argc < 1)
 		usage();
 
-	if (group != NULL) {
-		if (isdigit((unsigned char)*group)) {
-			gid = (gid_t)strtoul(group, &endp, 0);
-			if (*endp != '\0')
-				goto getgroup;
-		} else {
- getgroup:
-			if ((gp = getgrnam(group)) != NULL)
-				gid = gp->gr_gid;
-			else
-				errx(1, "no such group `%s'", group);
-		}
-	}
+	if (user != NULL)
+		uid = getuser(user);
 
-	for (gids = 0;
-	    (p = strsep(&grouplist, ",")) != NULL && gids < NGROUPS_MAX; ) {
-		if (*p == '\0')
-			continue;
-
-		if (isdigit((unsigned char)*p)) {
-			gidlist[gids] = (gid_t)strtoul(p, &endp, 0);
-			if (*endp != '\0')
-				goto getglist;
-		} else {
- getglist:
-			if ((gp = getgrnam(p)) != NULL)
-				gidlist[gids] = gp->gr_gid;
-			else
-				errx(1, "no such group `%s'", p);
-		}
-		gids++;
-	}
-	if (p != NULL && gids == NGROUPS_MAX)
-		errx(1, "too many supplementary groups provided");
+	if (group != NULL)
+		gid = getgroup(group);
+
+	if (grouplist != NULL) {
+		while ((p = strsep(&grouplist, ",")) != NULL) {
+			if (*p == '\0')
+				continue;
+
+			if (gids == NGROUPS_MAX)
+				errx(1,
+				    "too many supplementary groups provided");
 
-	if (user != NULL) {
-		if (isdigit((unsigned char)*user)) {
-			uid = (uid_t)strtoul(user, &endp, 0);
-			if (*endp != '\0')
-				goto getuser;
-		} else {
- getuser:
-			if ((pw = getpwnam(user)) != NULL)
-				uid = pw->pw_uid;
-			else
-				errx(1, "no such user `%s'", user);
+			gidlist[gids++] = getgroup(p);
 		}
 	}
 
@@ -179,7 +199,7 @@
 usage(void)
 {
 
-	(void)fprintf(stderr, "usage: chroot [-G group,group,...] [-g group] "
-	    "[-u user] newroot [command]\n");
+	(void)fprintf(stderr, "Usage: %s [-G group,group,...] [-g group] "
+	    "[-u user] newroot [command]\n", getprogname());
 	exit(1);
 }

Reply via email to