mirror of
https://github.com/containers/podman.git
synced 2025-06-24 19:42:56 +08:00
Merge pull request #9928 from pendulm/fix_rootless_socket_activation
Fix rootless socket activation
This commit is contained in:
@ -61,6 +61,10 @@ static int open_files_max_fd;
|
|||||||
static fd_set *open_files_set;
|
static fd_set *open_files_set;
|
||||||
static uid_t rootless_uid_init;
|
static uid_t rootless_uid_init;
|
||||||
static gid_t rootless_gid_init;
|
static gid_t rootless_gid_init;
|
||||||
|
static bool do_socket_activation = false;
|
||||||
|
static char *saved_systemd_listen_fds;
|
||||||
|
static char *saved_systemd_listen_pid;
|
||||||
|
static char *saved_systemd_listen_fdnames;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
syscall_setresuid (uid_t ruid, uid_t euid, uid_t suid)
|
syscall_setresuid (uid_t ruid, uid_t euid, uid_t suid)
|
||||||
@ -242,6 +246,10 @@ static void __attribute__((constructor)) init()
|
|||||||
{
|
{
|
||||||
const char *xdg_runtime_dir;
|
const char *xdg_runtime_dir;
|
||||||
const char *pause;
|
const char *pause;
|
||||||
|
const char *listen_pid;
|
||||||
|
const char *listen_fds;
|
||||||
|
const char *listen_fdnames;
|
||||||
|
|
||||||
DIR *d;
|
DIR *d;
|
||||||
|
|
||||||
pause = getenv ("_PODMAN_PAUSE");
|
pause = getenv ("_PODMAN_PAUSE");
|
||||||
@ -293,6 +301,26 @@ static void __attribute__((constructor)) init()
|
|||||||
closedir (d);
|
closedir (d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listen_pid = getenv("LISTEN_PID");
|
||||||
|
listen_fds = getenv("LISTEN_FDS");
|
||||||
|
listen_fdnames = getenv("LISTEN_FDNAMES");
|
||||||
|
|
||||||
|
if (listen_pid != NULL && listen_fds != NULL && strtol(listen_pid, NULL, 10) == getpid())
|
||||||
|
{
|
||||||
|
// save systemd socket environment for rootless child
|
||||||
|
do_socket_activation = true;
|
||||||
|
saved_systemd_listen_pid = strdup(listen_pid);
|
||||||
|
saved_systemd_listen_fds = strdup(listen_fds);
|
||||||
|
saved_systemd_listen_fdnames = strdup(listen_fdnames);
|
||||||
|
if (saved_systemd_listen_pid == NULL
|
||||||
|
|| saved_systemd_listen_fds == NULL
|
||||||
|
|| saved_systemd_listen_fdnames == NULL)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "save socket listen environments error: %s\n", strerror (errno));
|
||||||
|
_exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Shortcut. If we are able to join the pause pid file, do it now so we don't
|
/* Shortcut. If we are able to join the pause pid file, do it now so we don't
|
||||||
need to re-exec. */
|
need to re-exec. */
|
||||||
xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR");
|
xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR");
|
||||||
@ -635,6 +663,12 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
|||||||
for (f = 3; f <= open_files_max_fd; f++)
|
for (f = 3; f <= open_files_max_fd; f++)
|
||||||
if (is_fd_inherited (f))
|
if (is_fd_inherited (f))
|
||||||
close (f);
|
close (f);
|
||||||
|
if (do_socket_activation)
|
||||||
|
{
|
||||||
|
unsetenv ("LISTEN_PID");
|
||||||
|
unsetenv ("LISTEN_FDS");
|
||||||
|
unsetenv ("LISTEN_FDNAMES");
|
||||||
|
}
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
@ -660,6 +694,15 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
|||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_socket_activation)
|
||||||
|
{
|
||||||
|
char s[32];
|
||||||
|
sprintf (s, "%d", getpid());
|
||||||
|
setenv ("LISTEN_PID", s, true);
|
||||||
|
setenv ("LISTEN_FDS", saved_systemd_listen_fds, true);
|
||||||
|
setenv ("LISTEN_FDNAMES", saved_systemd_listen_fdnames, true);
|
||||||
|
}
|
||||||
|
|
||||||
setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
|
setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
|
||||||
setenv ("_CONTAINERS_ROOTLESS_UID", uid, 1);
|
setenv ("_CONTAINERS_ROOTLESS_UID", uid, 1);
|
||||||
setenv ("_CONTAINERS_ROOTLESS_GID", gid, 1);
|
setenv ("_CONTAINERS_ROOTLESS_GID", gid, 1);
|
||||||
@ -777,9 +820,6 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
|||||||
char **argv;
|
char **argv;
|
||||||
char uid[16];
|
char uid[16];
|
||||||
char gid[16];
|
char gid[16];
|
||||||
char *listen_fds = NULL;
|
|
||||||
char *listen_pid = NULL;
|
|
||||||
bool do_socket_activation = false;
|
|
||||||
char *cwd = getcwd (NULL, 0);
|
char *cwd = getcwd (NULL, 0);
|
||||||
sigset_t sigset, oldsigset;
|
sigset_t sigset, oldsigset;
|
||||||
|
|
||||||
@ -789,14 +829,6 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
|||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf (uid, "%d", geteuid ());
|
sprintf (uid, "%d", geteuid ());
|
||||||
sprintf (gid, "%d", getegid ());
|
sprintf (gid, "%d", getegid ());
|
||||||
@ -814,7 +846,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
|||||||
{
|
{
|
||||||
long num_fds;
|
long num_fds;
|
||||||
|
|
||||||
num_fds = strtol (listen_fds, NULL, 10);
|
num_fds = strtol (saved_systemd_listen_fds, NULL, 10);
|
||||||
if (num_fds != LONG_MIN && num_fds != LONG_MAX)
|
if (num_fds != LONG_MIN && num_fds != LONG_MAX)
|
||||||
{
|
{
|
||||||
int f;
|
int f;
|
||||||
@ -863,6 +895,8 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
|||||||
char s[32];
|
char s[32];
|
||||||
sprintf (s, "%d", getpid());
|
sprintf (s, "%d", getpid());
|
||||||
setenv ("LISTEN_PID", s, true);
|
setenv ("LISTEN_PID", s, true);
|
||||||
|
setenv ("LISTEN_FDS", saved_systemd_listen_fds, true);
|
||||||
|
setenv ("LISTEN_FDNAMES", saved_systemd_listen_fdnames, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
|
setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1);
|
||||||
|
103
test/system/270-socket-activation.bats
Normal file
103
test/system/270-socket-activation.bats
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env bats -*- bats -*-
|
||||||
|
#
|
||||||
|
# Tests podman system service under systemd socket activation
|
||||||
|
#
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
SERVICE_NAME="podman_test_$(random_string)"
|
||||||
|
|
||||||
|
SYSTEMCTL="systemctl"
|
||||||
|
UNIT_DIR="/usr/lib/systemd/system"
|
||||||
|
SERVICE_SOCK_ADDR="/run/podman/podman.sock"
|
||||||
|
|
||||||
|
if is_rootless; then
|
||||||
|
UNIT_DIR="$HOME/.config/systemd/user"
|
||||||
|
mkdir -p $UNIT_DIR
|
||||||
|
|
||||||
|
SYSTEMCTL="$SYSTEMCTL --user"
|
||||||
|
if [ -z "$XDG_RUNTIME_DIR" ]; then
|
||||||
|
export XDG_RUNTIME_DIR=/run/user/$(id -u)
|
||||||
|
fi
|
||||||
|
SERVICE_SOCK_ADDR="$XDG_RUNTIME_DIR/podman/podman.sock"
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVICE_FILE="$UNIT_DIR/$SERVICE_NAME.service"
|
||||||
|
SOCKET_FILE="$UNIT_DIR/$SERVICE_NAME.socket"
|
||||||
|
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
skip_if_remote "systemd tests are meaningless over remote"
|
||||||
|
|
||||||
|
basic_setup
|
||||||
|
|
||||||
|
cat > $SERVICE_FILE <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Podman API Service
|
||||||
|
Requires=podman.socket
|
||||||
|
After=podman.socket
|
||||||
|
Documentation=man:podman-system-service(1)
|
||||||
|
StartLimitIntervalSec=0
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=exec
|
||||||
|
KillMode=process
|
||||||
|
Environment=LOGGING="--log-level=info"
|
||||||
|
ExecStart=$PODMAN $LOGGING system service -t 2
|
||||||
|
EOF
|
||||||
|
cat > $SOCKET_FILE <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Podman API Socket
|
||||||
|
Documentation=man:podman-system-service(1)
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=%t/podman/podman.sock
|
||||||
|
SocketMode=0660
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# ensure pause die before each test runs
|
||||||
|
if is_rootless; then
|
||||||
|
local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
|
||||||
|
if [ -f $pause_pid ]; then
|
||||||
|
kill -9 $(cat $pause_pid) 2> /dev/null
|
||||||
|
rm -f $pause_pid
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
$SYSTEMCTL start "$SERVICE_NAME.socket"
|
||||||
|
}
|
||||||
|
|
||||||
|
function teardown() {
|
||||||
|
$SYSTEMCTL stop "$SERVICE_NAME.socket"
|
||||||
|
rm -f "$SERVICE_FILE" "$SOCKET_FILE"
|
||||||
|
$SYSTEMCTL daemon-reload
|
||||||
|
basic_teardown
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "podman system service - socket activation - no container" {
|
||||||
|
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
|
||||||
|
is "$output" "OK" "podman service responses normally"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "podman system service - socket activation - exist container " {
|
||||||
|
run_podman run $IMAGE sleep 90
|
||||||
|
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
|
||||||
|
is "$output" "OK" "podman service responses normally"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "podman system service - socket activation - kill rootless pause " {
|
||||||
|
if ! is_rootless; then
|
||||||
|
skip "root podman no need pause process"
|
||||||
|
fi
|
||||||
|
run_podman run $IMAGE sleep 90
|
||||||
|
local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
|
||||||
|
if [ -f $pause_pid ]; then
|
||||||
|
kill -9 $(cat $pause_pid) 2> /dev/null
|
||||||
|
fi
|
||||||
|
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
|
||||||
|
is "$output" "OK" "podman service responses normally"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: filetype=sh
|
Reference in New Issue
Block a user