Allow the optional setting of a user, primary group, or grouplist

when chrooting.

Obtained from:	NetBSD
MFC after:	4 weeks
This commit is contained in:
Mike Makonnen 2003-06-07 10:56:12 +00:00
parent df2c3922e9
commit 4fb3a3060c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=115952
2 changed files with 114 additions and 6 deletions

View File

@ -32,7 +32,7 @@
.\" @(#)chroot.8 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
.Dd January 24, 2002
.Dd June 7, 2003
.Dt CHROOT 8
.Os
.Sh NAME
@ -40,6 +40,9 @@
.Nd change root directory
.Sh SYNOPSIS
.Nm
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl G Ar group,group,...
.Ar newroot
.Op Ar command
.Sh DESCRIPTION
@ -49,7 +52,20 @@ utility changes its current and root directories to the supplied directory
.Ar newroot
and then exec's
.Ar command ,
if supplied, or an interactive copy of the user's login shell.
if supplied,
or an interactive copy of the user's login shell.
.Pp
If the
.Fl u ,
.Fl g
or
.Fl G
options are given,
the user,
group and group list of the process are set to
these values after the
.Xr chroot 8
has taken place.
.Sh ENVIRONMENT
The following environment variable is referenced by
.Nm :
@ -69,6 +85,10 @@ is used.
.Sh SEE ALSO
.Xr chdir 2 ,
.Xr chroot 2 ,
.Xr setgid 2 ,
.Xr setgroups 2 ,
.Xr setuid 2 ,
.Xr getgrnam 3 ,
.Xr environ 7 ,
.Xr jail 8
.Sh HISTORY

View File

@ -47,8 +47,12 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <ctype.h>
#include <err.h>
#include <grp.h>
#include <limits.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -56,29 +60,112 @@ __FBSDID("$FreeBSD$");
static void usage(void);
char *user; /* user to switch to before running program */
char *group; /* group to switch to ... */
char *grouplist; /* group list to switch to ... */
int
main(argc, argv)
int argc;
char *argv[];
{
int ch;
const char *shell;
struct group *gp;
struct passwd *pw;
char *endp, *p;
const char *shell;
gid_t gid, gidlist[NGROUPS_MAX];
uid_t uid;
int ch, gids;
while ((ch = getopt(argc, argv, "")) != -1)
gid = 0;
uid = 0;
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 (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);
}
}
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 (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);
}
}
if (chdir(argv[0]) == -1 || chroot(".") == -1)
err(1, "%s", argv[0]);
if (gids && setgroups(gids, gidlist) == -1)
err(1, "setgroups");
if (group && setgid(gid) == -1)
err(1, "setgid");
if (user && setuid(uid) == -1)
err(1, "setuid");
if (argv[1]) {
execvp(argv[1], &argv[1]);
err(1, "%s", argv[1]);
@ -94,6 +181,7 @@ main(argc, argv)
static void
usage()
{
(void)fprintf(stderr, "usage: chroot newroot [command]\n");
(void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
"[-u user] newroot [command]\n");
exit(1);
}