Skip to content

Commit

Permalink
Add a way to specify a hostname as well.
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentbernat committed Aug 17, 2011
1 parent 39f36dc commit 2a24c48
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 26 deletions.
13 changes: 6 additions & 7 deletions README.md
Expand Up @@ -16,13 +16,12 @@ exit the shell. Any filesystem that was mounted will also be unmounted
automatically.

This is what jchroot does:
1. provide a new PID namespace
2. provide a new IPC namespace
3. provide a new mount namespace
4. mount anything you want
5. chroot to your target
6. drop privileges if needed
7. execute your command
1. provide a new PID/IPC/mount/UTS namespace
2. mount anything you want
3. set hostname if needed
4. chroot to your target
5. drop privileges if needed
6. execute your command

After your command has been executed, any process started by the
execution of this command will be killed, any IPC will be freed, any
Expand Down
56 changes: 37 additions & 19 deletions jchroot.c
Expand Up @@ -35,6 +35,7 @@ struct config {
uid_t user;
gid_t group;
char *fstab;
char *hostname;
char *target;
char *const *command;
};
Expand All @@ -44,15 +45,16 @@ static void usage() {
"Usage: jchroot [OPTIONS] TARGET [--] COMMAND\n"
"\n"
"Available options:\n"
" -u USER | --user=USER Specify user to use after chroot\n"
" -g USER | --group=USER Specify group to use after chroot\n"
" -f FSTAB | --fstab=FSTAB Specify a fstab(5) file\n"
" -u USER | --user=USER Specify user to use after chroot\n"
" -g USER | --group=USER Specify group to use after chroot\n"
" -f FSTAB | --fstab=FSTAB Specify a fstab(5) file\n"
" -n NAME | --hostname=NAME Specify a hostname\n"
);
exit(EXIT_FAILURE);
}

/* Step 5: Execute command */
static int step5(struct config *config) {
static int step6(struct config *config) {
if (execvp(config->command[0], config->command) == -1) {
int i = 1;
fprintf(stderr, "unable to execute '%s", config->command[0]);
Expand All @@ -64,7 +66,7 @@ static int step5(struct config *config) {
}

/* Step 4: Drop privileges */
static int step4(struct config *config) {
static int step5(struct config *config) {
if (config->group != (gid_t) -1 && setgid(config->group)) {
fprintf(stderr, "unable to change to GID %d: %m\n", config->group);
return EXIT_FAILURE;
Expand All @@ -77,11 +79,11 @@ static int step4(struct config *config) {
fprintf(stderr, "unable to change to UID %d: %m\n", config->user);
return EXIT_FAILURE;
}
return step5(config);
return step6(config);
}

/* Step 3: Chroot */
static int step3(struct config *config) {
static int step4(struct config *config) {
if (chroot(config->target)) {
fprintf(stderr, "unable to chroot to %s: %m\n", config->target);
return EXIT_FAILURE;
Expand All @@ -90,6 +92,16 @@ static int step3(struct config *config) {
fprintf(stderr, "unable to go into chroot: %m\n");
return EXIT_FAILURE;
}
return step5(config);
}

/* Step 3: Set hostname */
static int step3(struct config *config) {
if (config->hostname &&
sethostname(config->hostname, strlen(config->hostname))) {
fprintf(stderr, "unable to change hostname to '%s': %m\n",
config->hostname);
}
return step4(config);
}

Expand Down Expand Up @@ -139,7 +151,7 @@ static int step2(void *arg) {
char *mntopts = strdup(mntent->mnt_opts);
char *mntdata = malloc(strlen(mntent->mnt_opts) + 1);
if (!mntdata || !mntopts) {
fprintf(stderr, "unable to allocate memory");
fprintf(stderr, "unable to allocate memory\n");
free(mntopts);
free(mntdata);
return EXIT_FAILURE;
Expand Down Expand Up @@ -190,18 +202,19 @@ static int step2(void *arg) {
return step3(config);
}

/* Step 1: create a new PID/IPC/NS namespace */
/* Step 1: create a new PID/IPC/NS/UTS namespace */
static int step1(struct config *config) {
int ret;
pid_t pid;

long stack_size = sysconf(_SC_PAGESIZE);
void *stack = alloca(stack_size) + stack_size;
int flags = CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS;

if (config->hostname) flags |= CLONE_NEWUTS;
pid = clone(step2,
stack,
SIGCHLD |
CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS,
SIGCHLD | flags,
config);
if (pid < 0) {
fprintf(stderr, "failed to clone: %m\n");
Expand All @@ -222,14 +235,15 @@ int main(int argc, char * argv[]) {
while (1) {
int option_index = 0;
static struct option long_options[] = {
{ "user", required_argument, 0, 'u' },
{ "group", required_argument, 0, 'g' },
{ "fstab", required_argument, 0, 'f' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
{ "user", required_argument, 0, 'u' },
{ "group", required_argument, 0, 'g' },
{ "fstab", required_argument, 0, 'f' },
{ "hostname", required_argument, 0, 'n' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};

c = getopt_long(argc, argv, "u:g:f:",
c = getopt_long(argc, argv, "u:g:f:n:",
long_options, &option_index);
if (c == -1) break;

Expand All @@ -245,7 +259,7 @@ int main(int argc, char * argv[]) {
if (!passwd) {
config.user = strtoul(optarg, NULL, 10);
if (errno) {
fprintf(stderr, "'%s' is not a valid user", optarg);
fprintf(stderr, "'%s' is not a valid user\n", optarg);
usage();
}
} else {
Expand All @@ -262,7 +276,7 @@ int main(int argc, char * argv[]) {
if (!group) {
config.group = strtoul(optarg, NULL, 10);
if (errno) {
fprintf(stderr, "'%s' is not a valid group", optarg);
fprintf(stderr, "'%s' is not a valid group\n", optarg);
usage();
}
} else {
Expand All @@ -273,6 +287,10 @@ int main(int argc, char * argv[]) {
if (!optarg) usage();
config.fstab = optarg;
break;
case 'n':
if (!optarg) usage();
config.hostname = optarg;
break;
}
}

Expand Down

0 comments on commit 2a24c48

Please sign in to comment.