summaryrefslogtreecommitdiffstats
path: root/usr.sbin/chroot
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2003-06-07 10:56:12 +0000
committermtm <mtm@FreeBSD.org>2003-06-07 10:56:12 +0000
commit5ba88e8391788d787a2fea391421060d140a5072 (patch)
tree61853aa938762478afa7fbdcb439ee67cdf40dd9 /usr.sbin/chroot
parentdd1aaed4176a17e2aa5cc19f2b08672164b4f8e6 (diff)
downloadFreeBSD-src-5ba88e8391788d787a2fea391421060d140a5072.zip
FreeBSD-src-5ba88e8391788d787a2fea391421060d140a5072.tar.gz
Allow the optional setting of a user, primary group, or grouplist
when chrooting. Obtained from: NetBSD MFC after: 4 weeks
Diffstat (limited to 'usr.sbin/chroot')
-rw-r--r--usr.sbin/chroot/chroot.824
-rw-r--r--usr.sbin/chroot/chroot.c96
2 files changed, 114 insertions, 6 deletions
diff --git a/usr.sbin/chroot/chroot.8 b/usr.sbin/chroot/chroot.8
index c60152c..342d849 100644
--- a/usr.sbin/chroot/chroot.8
+++ b/usr.sbin/chroot/chroot.8
@@ -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
diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c
index 3aeff1e..16da462 100644
--- a/usr.sbin/chroot/chroot.c
+++ b/usr.sbin/chroot/chroot.c
@@ -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);
}
OpenPOWER on IntegriCloud