diff options
-rw-r--r-- | usr.sbin/chroot/chroot.8 | 60 | ||||
-rw-r--r-- | usr.sbin/chroot/chroot.c | 162 |
2 files changed, 187 insertions, 35 deletions
diff --git a/usr.sbin/chroot/chroot.8 b/usr.sbin/chroot/chroot.8 index e65bc71e29e..03202d202ce 100644 --- a/usr.sbin/chroot/chroot.8 +++ b/usr.sbin/chroot/chroot.8 @@ -1,7 +1,8 @@ -.\" $OpenBSD: chroot.8,v 1.6 2001/05/28 15:26:55 aaron Exp $ +.\" $OpenBSD: chroot.8,v 1.7 2002/10/25 19:23:48 millert Exp $ +.\" $NetBSD: chroot.8,v 1.9 2000/08/17 12:36:32 mrg Exp $ .\" -.\" Copyright (c) 1988, 1991 The Regents of the University of California. -.\" All rights reserved. +.\" Copyright (c) 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -31,10 +32,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" from: @(#)chroot.8 5.3 (Berkeley) 3/16/91 -.\" $Id: chroot.8,v 1.6 2001/05/28 15:26:55 aaron Exp $ +.\" from: @(#)chroot.8 8.1 (Berkeley) 6/9/93 .\" -.Dd March 16, 1991 +.Dd October 25, 2002 .Dt CHROOT 8 .Os .Sh NAME @@ -42,6 +42,9 @@ .Nd change root directory .Sh SYNOPSIS .Nm chroot +.Op Fl u Ar user +.Op Fl g Ar group +.Op Fl G Ar group,group,... .Ar newroot .Op Ar command .Sh DESCRIPTION @@ -51,11 +54,37 @@ command changes its root directory to the supplied directory .Ar newroot and executes .Ar command , -if supplied, or an interactive copy of your shell. +if supplied, or an interactive copy of the user's shell. .Pp -Note, +The +.Nm +command is restricted to the superuser. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl u Ar user +Set user ID to +.Ar user +(a user name or user ID). +.It Fl g Ar group +Set group ID to +.Ar group +(a group name or group ID). +If supplemental groups are specified via the +.Fl G +flag, +.Ar group +will be the used as the first entry in the group vector. +.It Fl G Ar group,group,... +Set the supplemental group IDs to a comma-separated list of +group names or group IDs. +.El +.Pp +Note, the .Ar command -or the shell are run as your real user ID. +or shell are run with the real user ID of the invoking user unless the +.Fl u +flag is specified. .Sh ENVIRONMENT .Bl -tag -width SHELL .It Ev SHELL @@ -73,9 +102,18 @@ is used. .Sh SEE ALSO .Xr chdir 2 , .Xr chroot 2 , +.Xr setgid 2 , +.Xr setgroups 2 , +.Xr setuid 2 , +.Xr getgrnam 3 , +.Xr getpwnam 3 , .Xr environ 7 .Sh HISTORY The .Nm -command is -.Ud +utility first appeared in +.Bx 4.4 . +.Sh CAVEATS +.Nm +should never be installed setuid root, as it would then be possible +to exploit the program to gain root privileges. diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c index 224c59857a3..52f6f1f5518 100644 --- a/usr.sbin/chroot/chroot.c +++ b/usr.sbin/chroot/chroot.c @@ -1,8 +1,9 @@ -/* $OpenBSD: chroot.c,v 1.5 2002/07/14 02:59:29 deraadt Exp $ */ +/* $OpenBSD: chroot.c,v 1.6 2002/10/25 19:23:48 millert Exp $ */ +/* $NetBSD: chroot.c,v 1.11 2001/04/06 02:34:04 lukem Exp $ */ /* - * Copyright (c) 1988 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,43 +34,156 @@ * SUCH DAMAGE. */ +#include <sys/cdefs.h> #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1988 The Regents of the University of California.\n\ - All rights reserved.\n"; +static const char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)chroot.c 5.8 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$OpenBSD: chroot.c,v 1.5 2002/07/14 02:59:29 deraadt Exp $"; +#if 0 +static const char sccsid[] = "@(#)chroot.c 8.1 (Berkeley) 6/9/93"; +#else +static const char rcsid[] = "$OpenBSD: chroot.c,v 1.6 2002/10/25 19:23:48 millert Exp $"; +#endif #endif /* not lint */ +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <grp.h> +#include <limits.h> +#include <paths.h> +#include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <paths.h> #include <unistd.h> -#include <err.h> + +int main(int, char **); +__dead void usage(void); int -main(int argc, char *argv[]) +main(int argc, char **argv) { - char *shell; + struct group *gp; + struct passwd *pw; + const char *shell; + char *user, *group, *grouplist, *endp, *p; + gid_t gid, gidlist[NGROUPS_MAX]; + uid_t uid; + int ch, gids; + unsigned long ul; + + gids = 0; + user = group = grouplist = NULL; + while ((ch = getopt(argc, argv, "G:g:u:")) != -1) { + switch(ch) { + case 'u': + user = optarg; + if (*user == '\0') + usage(); + break; + case 'g': + group = optarg; + if (*group == '\0') + usage(); + break; + case 'G': + grouplist = optarg; + if (*grouplist == '\0') + usage(); + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + if (group != NULL) { + if ((gp = getgrnam(group)) != NULL) + gid = gp->gr_gid; + else if (isdigit((unsigned char)*group)) { + errno = 0; + ul = strtoul(group, &endp, 10); + if (*endp != '\0' || + (ul == ULONG_MAX && errno == ERANGE)) + errx(1, "invalid group ID `%s'", group); + gid = (gid_t)ul; + } else + errx(1, "no such group `%s'", group); + if (grouplist != NULL) + gidlist[gids++] = gid; + } + + while ((p = strsep(&grouplist, ",")) != NULL && gids < NGROUPS_MAX) { + if (*p == '\0') + continue; - if (argc < 2) { - (void)fprintf(stderr, "usage: chroot newroot [command]\n"); - exit(1); + if ((gp = getgrnam(p)) != NULL) + gidlist[gids] = gp->gr_gid; + else if (isdigit((unsigned char)*p)) { + errno = 0; + ul = strtoul(p, &endp, 10); + if (*endp != '\0' || + (ul == ULONG_MAX && errno == ERANGE)) + errx(1, "invalid group ID `%s'", p); + gidlist[gids] = (gid_t)ul; + } else + errx(1, "no such group `%s'", p); + gids++; } - if (chroot(argv[1]) || chdir("/")) + if (p != NULL && gids == NGROUPS_MAX) + errx(1, "too many supplementary groups provided"); + + if (user != NULL) { + if ((pw = getpwnam(user)) != NULL) + uid = pw->pw_uid; + else if (isdigit((unsigned char)*user)) { + errno = 0; + ul = strtoul(user, &endp, 10); + if (*endp != '\0' || + (ul == ULONG_MAX && errno == ERANGE)) + errx(1, "invalid user ID `%s'", user); + uid = (uid_t)ul; + } else + errx(1, "no such user `%s'", user); + } + + if (chroot(argv[0]) != 0 || chdir("/") != 0) + err(1, "%s", argv[0]); + + if (gids && setgroups(gids, gidlist) != 0) + err(1, "setgroups"); + if (group && setgid(gid) != 0) + err(1, "setgid"); + if (user && setuid(uid) != 0) + err(1, "setuid"); + + if (argv[1]) { + execvp(argv[1], &argv[1]); err(1, "%s", argv[1]); - if (argv[2]) { - execvp(argv[2], &argv[2]); - err(1, "%s", argv[2]); - } else { - if (!(shell = getenv("SHELL"))) - shell = _PATH_BSHELL; - execlp(shell, shell, "-i", (char *)NULL); - err(1, "%s", shell); } + + if ((shell = getenv("SHELL")) == NULL) + shell = _PATH_BSHELL; + execlp(shell, shell, "-i", (char *)NULL); + err(1, "%s", shell); /* NOTREACHED */ } + +void +usage(void) +{ + extern char *__progname; + + (void)fprintf(stderr, "usage: %s [-g group] [-G group,group,...] " + "[-u user] newroot [command]\n", __progname); + exit(1); +} |