Skip to content

Commit

Permalink
Merge pull request #3188 from giuseppe/fix-join-existing-containers
Browse files Browse the repository at this point in the history
rootless: new function to join existing conmon processes
  • Loading branch information
openshift-merge-robot authored May 29, 2019
2 parents 8649dbd + 153503e commit aed91ce
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 83 deletions.
44 changes: 10 additions & 34 deletions cmd/podman/main_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ package main

import (
"context"
"io/ioutil"
"log/syslog"
"os"
"runtime/pprof"
"strconv"
"strings"
"syscall"

Expand Down Expand Up @@ -120,18 +118,10 @@ func setupRootless(cmd *cobra.Command, args []string) error {
return errors.Wrapf(err, "could not get pause process pid file path")
}

data, err := ioutil.ReadFile(pausePidPath)
if err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "cannot read pause process pid file %s", pausePidPath)
}
if err == nil {
pausePid, err := strconv.Atoi(string(data))
if err != nil {
return errors.Wrapf(err, "cannot parse pause pid file %s", pausePidPath)
}
became, ret, err := rootless.JoinUserAndMountNS(uint(pausePid), "")
if _, err := os.Stat(pausePidPath); err == nil {
became, ret, err := rootless.TryJoinFromFilePaths("", false, []string{pausePidPath})
if err != nil {
logrus.Errorf("cannot join pause process pid %d. You may need to remove %s and stop all containers", pausePid, pausePidPath)
logrus.Errorf("cannot join pause process. You may need to remove %s and stop all containers", pausePidPath)
logrus.Errorf("you can use `system migrate` to recreate the pause process")
logrus.Errorf(err.Error())
os.Exit(1)
Expand All @@ -154,28 +144,13 @@ func setupRootless(cmd *cobra.Command, args []string) error {
logrus.Errorf(err.Error())
os.Exit(1)
}
var became bool
var ret int
if len(ctrs) == 0 {
became, ret, err = rootless.BecomeRootInUserNS(pausePidPath)
} else {
for _, ctr := range ctrs {
data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
if err != nil {
logrus.Errorf(err.Error())
continue
}
conmonPid, err := strconv.Atoi(string(data))
if err != nil {
logrus.Errorf(err.Error())
continue
}
became, ret, err = rootless.JoinUserAndMountNS(uint(conmonPid), pausePidPath)
if err == nil {
break
}
}

paths := []string{}
for _, ctr := range ctrs {
paths = append(paths, ctr.Config().ConmonPidFile)
}

became, ret, err := rootless.TryJoinFromFilePaths(pausePidPath, true, paths)
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
Expand All @@ -185,6 +160,7 @@ func setupRootless(cmd *cobra.Command, args []string) error {
}
return nil
}

func setRLimits() error {
rlimits := new(syscall.Rlimit)
rlimits.Cur = 1048576
Expand Down
2 changes: 1 addition & 1 deletion libpod/runtime_ctr.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
}()

if rootless.IsRootless() && ctr.config.ConmonPidFile == "" {
ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid")
ctr.config.ConmonPidFile = filepath.Join(ctr.state.RunDir, "conmon.pid")
}

// Go through named volumes and add them.
Expand Down
149 changes: 119 additions & 30 deletions pkg/rootless/rootless_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ rootless_gid ()
static void
do_pause ()
{
int i;
struct sigaction act;
int const sig[] =
{
SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM, SIGPOLL,
SIGPROF, SIGVTALRM, SIGXCPU, SIGXFSZ, 0
};

act.sa_handler = SIG_IGN;

for (i = 0; sig[i]; i++)
sigaction (sig[i], &act, NULL);

prctl (PR_SET_NAME, "podman pause", NULL, NULL, NULL);
while (1)
pause ();
Expand Down Expand Up @@ -333,6 +346,26 @@ syscall_clone (unsigned long flags, void *child_stack)
#endif
}

int
reexec_in_user_namespace_wait (int pid, int options)
{
pid_t p;
int status;

do
p = waitpid (pid, &status, 0);
while (p < 0 && errno == EINTR);

if (p < 0)
return -1;

if (WIFEXITED (status))
return WEXITSTATUS (status);
if (WIFSIGNALED (status))
return 128 + WTERMSIG (status);
return -1;
}

static int
create_pause_process (const char *pause_pid_file_path, char **argv)
{
Expand All @@ -356,6 +389,8 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
while (r < 0 && errno == EINTR);
close (p[0]);

reexec_in_user_namespace_wait(r, 0);

return r == 1 && b == '0' ? 0 : -1;
}
else
Expand Down Expand Up @@ -560,8 +595,51 @@ check_proc_sys_userns_file (const char *path)
}
}

static int
copy_file_to_fd (const char *file_to_read, int outfd)
{
char buf[512];
int fd;

fd = open (file_to_read, O_RDONLY);
if (fd < 0)
return fd;

for (;;)
{
ssize_t r, w, t = 0;

do
r = read (fd, buf, sizeof buf);
while (r < 0 && errno == EINTR);
if (r < 0)
{
close (fd);
return r;
}

if (r == 0)
break;

while (t < r)
{
do
w = write (outfd, &buf[t], r - t);
while (w < 0 && errno == EINTR);
if (w < 0)
{
close (fd);
return w;
}
t += w;
}
}
close (fd);
return 0;
}

int
reexec_in_user_namespace (int ready, char *pause_pid_file_path)
reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_read, int outputfd)
{
int ret;
pid_t pid;
Expand All @@ -574,6 +652,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path)
char *listen_pid = NULL;
bool do_socket_activation = false;
char *cwd = getcwd (NULL, 0);
sigset_t sigset, oldsigset;

if (cwd == NULL)
{
Expand All @@ -584,11 +663,11 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path)
listen_pid = getenv("LISTEN_PID");
listen_fds = getenv("LISTEN_FDS");

if (listen_pid != NULL && listen_fds != NULL) {
if (strtol(listen_pid, NULL, 10) == getpid()) {
do_socket_activation = true;
if (listen_pid != NULL && listen_fds != NULL)
{
if (strtol(listen_pid, NULL, 10) == getpid())
do_socket_activation = true;
}
}

sprintf (uid, "%d", geteuid ());
sprintf (gid, "%d", getegid ());
Expand Down Expand Up @@ -621,18 +700,35 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path)
return pid;
}

if (sigfillset (&sigset) < 0)
{
fprintf (stderr, "cannot fill sigset: %s\n", strerror (errno));
_exit (EXIT_FAILURE);
}
if (sigdelset (&sigset, SIGCHLD) < 0)
{
fprintf (stderr, "cannot sigdelset(SIGCHLD): %s\n", strerror (errno));
_exit (EXIT_FAILURE);
}
if (sigprocmask (SIG_BLOCK, &sigset, &oldsigset) < 0)
{
fprintf (stderr, "cannot block signals: %s\n", strerror (errno));
_exit (EXIT_FAILURE);
}

argv = get_cmd_line_args (ppid);
if (argv == NULL)
{
fprintf (stderr, "cannot read argv: %s\n", strerror (errno));
_exit (EXIT_FAILURE);
}

if (do_socket_activation) {
char s[32];
sprintf (s, "%d", getpid());
setenv ("LISTEN_PID", s, true);
}
if (do_socket_activation)
{
char s[32];
sprintf (s, "%d", getpid());
setenv ("LISTEN_PID", s, true);
}

setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
setenv ("_CONTAINERS_ROOTLESS_UID", uid, 1);
Expand Down Expand Up @@ -685,27 +781,20 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path)
while (ret < 0 && errno == EINTR);
close (ready);

execvp (argv[0], argv);

_exit (EXIT_FAILURE);
}

int
reexec_in_user_namespace_wait (int pid)
{
pid_t p;
int status;
if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0)
{
fprintf (stderr, "cannot block signals: %s\n", strerror (errno));
_exit (EXIT_FAILURE);
}

do
p = waitpid (pid, &status, 0);
while (p < 0 && errno == EINTR);
if (file_to_read && file_to_read[0])
{
ret = copy_file_to_fd (file_to_read, outputfd);
close (outputfd);
_exit (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}

if (p < 0)
return -1;
execvp (argv[0], argv);

if (WIFEXITED (status))
return WEXITSTATUS (status);
if (WIFSIGNALED (status))
return 128 + WTERMSIG (status);
return -1;
_exit (EXIT_FAILURE);
}
Loading

0 comments on commit aed91ce

Please sign in to comment.