Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rootless: new function to join existing conmon processes #3188

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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