aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/chroot/chroot.c
diff options
context:
space:
mode:
authorMike Makonnen <mtm@FreeBSD.org>2003-06-07 10:56:12 +0000
committerMike Makonnen <mtm@FreeBSD.org>2003-06-07 10:56:12 +0000
commit4fb3a3060cfe746c6c6699bc9b52d29594eb409b (patch)
tree61853aa938762478afa7fbdcb439ee67cdf40dd9 /usr.sbin/chroot/chroot.c
parentdf2c3922e942491c29468da515a3620a779f5470 (diff)
Notes
Diffstat (limited to 'usr.sbin/chroot/chroot.c')
-rw-r--r--usr.sbin/chroot/chroot.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c
index 3aeff1eddf43..16da4627a1cf 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);
}