Skip to content

Commit

Permalink
Add a --tty option
Browse files Browse the repository at this point in the history
If the tty option is passed it will:
  Create a pty.
  Set the parent's stdin to raw mode.
  Set the child's fds to the term.
  Handle copying to/from the term.
  Handle SIGWINCH.
  • Loading branch information
mstory21 committed May 11, 2021
1 parent 7b368c1 commit ee46e33
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 6 deletions.
39 changes: 33 additions & 6 deletions enter.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "ns.h"
#include "outer.h"
#include "path.h"
#include "tty.h"
#include "setarch.h"
#include "sig.h"
#include "util.h"
Expand Down Expand Up @@ -208,6 +209,11 @@ int enter(struct entry_settings *opts)
cleaner and easier to always fork, regardless of unsharing the PID
namespace. */

int parentSock = -1, childSock = -1;
if (opts->tty) {
tty_setup_socketpair(&parentSock, &childSock);
}

pid_t pid = fork();
if (pid == -1) {
if (errno == ENOMEM && nsactions[NS_PID] >= 0) {
Expand All @@ -217,6 +223,9 @@ int enter(struct entry_settings *opts)
}

if (pid) {
if (childSock >= 0) {
close(childSock);
}
if (opts->pidfile != NULL) {
int pidfile = open(opts->pidfile, O_WRONLY | O_CREAT | O_CLOEXEC | O_NOCTTY , 0666);
if (pidfile == -1) {
Expand Down Expand Up @@ -260,22 +269,32 @@ int enter(struct entry_settings *opts)
sigset_t mask;
sigfillset(&mask);

if (parentSock >= 0) {
tty_parent_setup(parentSock);
}

for (;;) {

int waitflags = WEXITED | WNOHANG;
siginfo_t info;
sig_wait(&mask, &info);
sig_forward(&info, pid);

if (info.si_signo != SIGCHLD) {
continue;
if (parentSock < 0) {
sig_wait(&mask, &info);
sig_forward(&info, pid);
if (info.si_signo != SIGCHLD) {
continue;
}
} else {
if (!tty_parent_select(pid, &waitflags)) {
continue;
}
}

/* We might have been run as a process subreaper against our
will -- make sure we only exit when the main child pid
exited. */

int rc;
while ((rc = waitid(P_ALL, 0, &info, WEXITED | WNOHANG)) != -1) {
while ((rc = waitid(P_ALL, 0, &info, waitflags)) != -1) {
if (info.si_signo != SIGCHLD) {
break;
}
Expand Down Expand Up @@ -308,6 +327,10 @@ int enter(struct entry_settings *opts)
}
}

if (parentSock >= 0) {
close(parentSock);
}

sigset_t mask;
sigemptyset(&mask);

Expand Down Expand Up @@ -575,6 +598,10 @@ int enter(struct entry_settings *opts)
}
}

if (childSock >= 0) {
tty_child(childSock);
}

if (opts->init != NULL && opts->init[0] != '\0') {

if (!pid_unshare && prctl(PR_SET_CHILD_SUBREAPER, 1) == -1) {
Expand Down
2 changes: 2 additions & 0 deletions enter.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct entry_settings {

const char *pidfile;

bool tty;

int no_copy_hard_limits;
int no_fake_devtmpfs;
int no_derandomize;
Expand Down
6 changes: 6 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ enum {
OPTION_NO_INIT,
OPTION_NO_ENV,
OPTION_NO_COPY_HARD_LIMITS,
OPTION_TTY,
};

static void process_nslist_entry(const char **out, const char *share, const char *path, int append_nsname)
Expand Down Expand Up @@ -284,6 +285,7 @@ int main(int argc, char *argv[], char *envp[])
{ "pidfile", required_argument, NULL, OPTION_PIDFILE },
{ "ip", required_argument, NULL, OPTION_IP },
{ "route", required_argument, NULL, OPTION_ROUTE },
{ "tty", no_argument, NULL, OPTION_TTY },

/* Opt-out feature flags */
{ "no-copy-hard-limits", no_argument, NULL, OPTION_NO_COPY_HARD_LIMITS },
Expand Down Expand Up @@ -656,6 +658,10 @@ int main(int argc, char *argv[], char *envp[])
opts.no_env = 1;
break;

case OPTION_TTY:
opts.tty = 1;
break;

case 'r':
opts.root = optarg;
break;
Expand Down
6 changes: 6 additions & 0 deletions man/bst.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@ _VAR=value_ before the executable to run.
the spacetime process. This can cause issues for environment variables like
PATH if the rootfs layout is different than the host.

\--tty
Allocate a pty for the process.

By default bst inherits the parent's terminal device (or lack thereof). Use
the --tty option to allocate a new pty for the child process.

# PRIVILEGE MODEL

*bst* strives to be runnable by unprivileged users. However, some code paths
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ bst_sources = [
'setarch.c',
'sig.c',
'timens.c',
'tty.c',
'usage.c',
'userns.c',
]
Expand Down
5 changes: 5 additions & 0 deletions test/tty.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env cram.sh

Allocate a PTY for the spacetime
$ bst --tty --mount devpts,/dev/pts,devpts,mode=620,ptmxmode=666 tty
/dev/pts/0
Loading

0 comments on commit ee46e33

Please sign in to comment.