distrobox/0001-Fix-systemd-init-container-startup-1069.patch
Dario Faggioli 5bc832e0c1 Accepting request 1148667 from home:iDesmI:branches:Virtualization:containers
Fixes bug with image `registry.opensuse.org/opensuse/distrobox` running as root

- Add 0001-Fix-systemd-init-container-startup-1069.patch:
  * run podman exec command as root since some distros would ask
    for user password when using su to login even though the user
    has no password in /etc/shadow
  * fix pam_systemd not being checked for su

OBS-URL: https://build.opensuse.org/request/show/1148667
OBS-URL: https://build.opensuse.org/package/show/Virtualization:containers/distrobox?expand=0&rev=35
2024-02-21 15:50:58 +00:00

391 lines
14 KiB
Diff

From 3b1e312f884cad2185c3b57dcde470a5d7914c61 Mon Sep 17 00:00:00 2001
From: Pavin Joseph <pavinjoseph@gmail.com>
Date: Fri, 2 Feb 2024 02:48:05 +0530
Subject: [PATCH] Fix systemd/init container startup (#1069)
Change user login to prevent issues with firefox segfaulting (IPC I/O) related errors. TODO: improve init wait depending on whether container has init or not.
Improved waiting for systemd to start system
Fix creation of systemd login sessions to prevent conflict across multiple active sessions.
some containers are not allowing passthrough of certain environment variables without explicitly passing them using sudo's --preserve-env flag
run podman exec command as root since some distros like suse or arch would ask for user password when using su to login even though the user has no password in /etc/shadow
fix pam_systemd not being checked for su on certain distros like suse or arch.
---------
Signed-off-by: Luca Di Maio <luca.dimaio1@gmail.com>
Co-authored-by: Luca Di Maio <luca.dimaio1@gmail.com>
---
.markdownlint.yaml | 1 +
distrobox-create | 1 +
distrobox-enter | 10 +++----
distrobox-ephemeral | 2 +-
distrobox-export | 31 +++++++++++++--------
distrobox-init | 46 +++++++++++++++++++++++---------
distrobox-stop | 5 +++-
distrobox-upgrade | 4 +--
docs/usage/distrobox-assemble.md | 42 ++++++++++++++---------------
9 files changed, 89 insertions(+), 53 deletions(-)
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
index 5bc9252..171fca0 100644
--- a/.markdownlint.yaml
+++ b/.markdownlint.yaml
@@ -7,3 +7,4 @@ MD013:
headers: false
MD033: false
MD041: false
+MD045: false
diff --git a/distrobox-create b/distrobox-create
index 64e9911..4087e76 100755
--- a/distrobox-create
+++ b/distrobox-create
@@ -178,6 +178,7 @@ Options:
--pre-init-hooks: additional commands to execute prior to container initialization
--init/-I: use init system (like systemd) inside the container.
this will make host's processes not visible from within the container. (assumes --unshare-process)
+ may require additional packages depending on the container image: https://github.com/89luca89/distrobox/blob/main/docs/useful_tips.md#using-init-system-inside-a-distrobox
--nvidia: try to integrate host's nVidia drivers in the guest
--unshare-devsys: do not share host devices and sysfs dirs from host
--unshare-ipc: do not share ipc namespace with host
diff --git a/distrobox-enter b/distrobox-enter
index 6d8998a..96a97a4 100755
--- a/distrobox-enter
+++ b/distrobox-enter
@@ -131,7 +131,7 @@ Usage:
Options:
--name/-n: name for the distrobox default: my-distrobox
- --/-e: end arguments execute the rest as command to execute at login default: bash -l
+ --/-e: end arguments execute the rest as command to execute at login default: su ${USER}
--no-tty/-T: do not instantiate a tty
--no-workdir/-nw: always start the container from container's home directory
--additional-flags/-a: additional flags to pass to the container manager command
@@ -305,7 +305,7 @@ generate_command() {
result_command="${result_command}
--detach-keys=\"\""
result_command="${result_command}
- --user=\"${USER}\""
+ --user='root'"
# For some usage, like use in service, or launched by non-terminal
# eg. from desktop files, TTY can fail to instantiate, and fail to enter
@@ -346,7 +346,7 @@ generate_command() {
set +o xtrace
# disable logging for this snippet, or it will be too talkative.
for i in $(printenv | grep '=' | grep -Ev ' |"|`|\$' |
- grep -Ev '^(HOST|HOSTNAME|HOME|PATH|PROFILEREAD|SHELL|XDG_.*_DIRS|^_)'); do
+ grep -Ev '^(HOST|HOSTNAME|HOME|PATH|PROFILEREAD|SHELL|XDG_SEAT|XDG_VTNR|XDG_.*_DIRS|^_)'); do
# We filter the environment so that we do not have strange variables,
# multiline or containing spaces.
# We also NEED to ignore the HOME variable, as this is set at create time
@@ -435,12 +435,12 @@ generate_command() {
if [ -n "${container_command}" ]; then
result_command="${result_command}
- ${container_command}"
+ su ${USER} -c \"${container_command}\""
else
# if no command was specified, let's execute a command that will find
# and run the default shell for the user
result_command="${result_command}
- sh -c \"\\\$(getent passwd ${USER} | cut -f 7 -d :) -l"\"
+ su ${USER}"
fi
# Return generated command.
diff --git a/distrobox-ephemeral b/distrobox-ephemeral
index 47a1486..67b9c81 100755
--- a/distrobox-ephemeral
+++ b/distrobox-ephemeral
@@ -74,7 +74,7 @@ Options:
specify it through the DBX_SUDO_PROGRAM env variable, or 'distrobox_sudo_program' config variable)
--verbose/-v: show more verbosity
--help/-h: show this message
- --/-e: end arguments execute the rest as command to execute at login default: bash -l
+ --/-e: end arguments execute the rest as command to execute at login default: su ${USER}
--version/-V: show version
See also:
diff --git a/distrobox-export b/distrobox-export
index 77c928c..c05f267 100755
--- a/distrobox-export
+++ b/distrobox-export
@@ -39,7 +39,6 @@ host_home="${DISTROBOX_HOST_HOME:-"${HOME}"}"
dest_path="${host_home}/.local/bin"
is_sudo=0
rootful=""
-start_shell="/bin/sh -l -c"
verbose=0
version="1.6.0.1"
@@ -180,8 +179,7 @@ fi
# Ensure the foundamental variables are set and not empty, we will not proceed
# if they are not all set.
-if [ -z "${exported_app}" ] &&
- [ -z "${exported_bin}" ]; then
+if [ -z "${exported_app}" ] && [ -z "${exported_bin}" ]; then
printf >&2 "Error: Invalid arguments.\n"
printf >&2 "Error: missing export target. Run\n"
printf >&2 "\tdistrobox-export --help\n"
@@ -216,17 +214,29 @@ if [ -z "${container_name}" ]; then
container_name=$(uname -n | cut -d'.' -f1)
fi
-#
-if [ "${is_sudo}" -ne 0 ]; then
+# Command to execute
+container_command_suffix="${exported_bin} ${extra_flags} \"\$@\""
+
+# Edge case for systems without sudo
+if command -v su-exec > /dev/null >&1; then
+ sudo_prefix="su-exec ${USER}"
+ container_command_suffix="sh -l -c \"${exported_bin} ${extra_flags} \$*\""
+fi
+
+# Check if exported application/binary should be run with sudo privileges
+if [ "${is_sudo}" -ne 0 ]; then
+ sudo_prefix="sudo -S"
+
+ # Edge case for systems without sudo
if command -v su-exec > /dev/null >&1; then
- start_shell="su-exec root su - root ${start_shell}"
- elif command -v sudo > /dev/null 2>&1; then
- start_shell="$(command -v sudo) -i ${start_shell}"
+ sudo_prefix="su-exec root"
+ container_command_suffix="sh -l -c \"${exported_bin} ${extra_flags} \$*\""
fi
fi
# Prefix to add to an existing command to work through the container
-container_command_prefix="${DISTROBOX_ENTER_PATH:-"distrobox-enter"} ${rootful} -n ${container_name} -- ${start_shell} "
+container_command_prefix="${DISTROBOX_ENTER_PATH:-"distrobox-enter"} ${rootful} -n ${container_name} -- ${sudo_prefix:-} "
+
if [ -z "${exported_app_label}" ]; then
exported_app_label=" (on ${container_name})"
elif [ "${exported_app_label}" = "none" ]; then
@@ -247,8 +257,7 @@ generate_script() {
# distrobox_binary
# name: ${container_name}
if [ -z "\${CONTAINER_ID}" ]; then
- exec "${DISTROBOX_ENTER_PATH:-"distrobox-enter"}" ${rootful} -n ${container_name} -- \
- ${start_shell} '${exported_bin} ${extra_flags} \$@' -- "\$@"
+ exec "${DISTROBOX_ENTER_PATH:-"distrobox-enter"}" ${rootful} -n ${container_name} -- ${sudo_prefix:-} ${container_command_suffix}
elif [ -n "\${CONTAINER_ID}" ] && [ "\${CONTAINER_ID}" != "${container_name}" ]; then
exec distrobox-host-exec ${dest_path}/$(basename "${exported_bin}") ${extra_flags} "\$@"
else
diff --git a/distrobox-init b/distrobox-init
index f2153b9..6c7e3f1 100755
--- a/distrobox-init
+++ b/distrobox-init
@@ -1713,7 +1713,7 @@ fi
###############################################################################
###############################################################################
-printf "distrobox: Setting up distrobox profile...\n"
+printf "distrobox: Setting up distrobox profile...\n"
# This ensures compatibility with prompts and tools between toolbx and distrobox
touch /run/.toolboxenv
@@ -1768,8 +1768,8 @@ fi
###############################################################################
###############################################################################
-printf "distrobox: Setting up sudo...\n"
-mkdir -p /etc/sudoers.d
+printf "distrobox: Setting up sudo...\n"
+mkdir -p /etc/sudoers.d
# Ensure we're using the user's password for sudo, not root
if [ -e /etc/sudoers ]; then
sed -i "s|^Defaults targetpw.*||g" /etc/sudoers
@@ -1778,12 +1778,29 @@ fi
# Do not check fqdn when doing sudo, it will not work anyways
# Also allow canonical groups to use sudo
cat << EOF > /etc/sudoers.d/sudoers
+Defaults !targetpw
Defaults !fqdn
%wheel ALL=(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) ALL
%root ALL=(ALL:ALL) ALL
EOF
+# PAM config for "su" command
+if [ ! -e /etc/pam.d/su ]; then
+ mkdir -p /etc/pam.d
+ cat << EOF > /etc/pam.d/su
+auth sufficient pam_rootok.so
+auth required pam_unix.so
+account required pam_unix.so
+session required pam_unix.so
+-session optional pam_systemd.so
+EOF
+fi
+
+if ! grep -q "pam_systemd.so" /etc/pam.d/su; then
+ printf "%s" '-session optional pam_systemd.so' >> /etc/pam.d/su
+fi
+
# If we're running this script as root in a login shell (sudoless), we don't
# have to bother setting up sudo.
#
@@ -1923,7 +1940,7 @@ if [ "$(getent passwd "${container_user_name}" | cut -d: -f6)" != "${container_u
fi
# If we're rootless, delete password for root and user
-if [ ! -e /etc/passwd.done ]; then
+if [ ! -e /etc/passwd.done ]; then
temporary_password="$(cat /proc/sys/kernel/random/uuid)"
# We generate a random password to initialize the entry for the user.
printf "%s:%s" "${container_user_name}" "${temporary_password}" | chpasswd -e
@@ -1965,7 +1982,7 @@ if [ "${rootful}" -eq 1 ] &&
fi
# Now we're done
-touch /etc/passwd.done
+touch /etc/passwd.done
###############################################################################
###############################################################################
@@ -2078,16 +2095,16 @@ fi
# Instantiate a new pty to mount over /dev/console
# this way we will have init output right of the logs
[ -e /dev/console ] || touch /dev/console
-rm -f /var/console
-mkfifo /var/console
-script -c "cat /var/console" /dev/null &
+rm -f /var/console
+mkfifo /var/console
+script -c "cat /var/console" /dev/null &
# Ensure the pty is created
-sleep 0.5
+sleep 0.5
# Mount the created pty over /dev/console in order to have systemd logs
# right into container logs
-if ! mount --bind /dev/pts/0 /dev/console; then
+if ! mount --bind /dev/pts/0 /dev/console; then
# Fallback to older behaviour or fake plaintext file in case it fails
# this ensures rootful + initful boxes do not interfere with host's /dev/console
rm -f /var/console
@@ -2175,8 +2192,6 @@ fi
printf "distrobox: Firing up init system...\n"
if [ -e /usr/lib/systemd/systemd ] || [ -e /lib/systemd/systemd ]; then
- printf "container_setup_done\n"
-
# Start user Systemd unit, this will attempt until Systemd is ready
sh -c "while true; do \
sleep 1; \
@@ -2185,8 +2200,15 @@ if [ -e /usr/lib/systemd/systemd ] || [ -e /lib/systemd/systemd ]; then
exit 0; \
done" &
+ sh -c " while true; do \
+ systemctl is-system-running && break; \
+ printf >&2 'waiting for systemd to come up...\n' && sleep 1; \
+ done; \
+ printf container_setup_done" &
+
[ -e /usr/lib/systemd/systemd ] && exec /usr/lib/systemd/systemd --system --log-target=console --unit=multi-user.target
[ -e /lib/systemd/systemd ] && exec /lib/systemd/systemd --system --log-target=console --unit=multi-user.target
+
elif [ -e /sbin/init ]; then
printf "container_setup_done\n"
diff --git a/distrobox-stop b/distrobox-stop
index fd17cc1..891fb61 100755
--- a/distrobox-stop
+++ b/distrobox-stop
@@ -246,11 +246,14 @@ fi
# check if we have containers to delete
if [ -z "${container_name_list}" ]; then
container_name_list="${container_name_default}"
+else
+ # strip leading whitespace from container name
+ container_name_list="$(echo "${container_name_list}" | sed -E 's/^[[:space:]]+//')"
fi
if [ "${non_interactive}" -eq 0 ]; then
# Prompt to stop the container.
- printf "Do you really want to stop%s? [Y/n]: " "${container_name_list}"
+ printf "Do you really want to stop %s? [Y/n]: " "${container_name_list}"
read -r response
response="${response:-"Y"}"
else
diff --git a/distrobox-upgrade b/distrobox-upgrade
index ab5e96f..dafaa87 100755
--- a/distrobox-upgrade
+++ b/distrobox-upgrade
@@ -240,7 +240,7 @@ fi
for container in ${container_name}; do
printf >&2 "\033[1;31m Upgrading %s...\n\033[0m" "${container}"
# shellcheck disable=SC2086,SC2248
- "${distrobox_path}"/distrobox-enter --additional-flags "--user root:root" \
+ "${distrobox_path}"/distrobox-enter \
${distrobox_flags} ${container} -- \
- /usr/bin/entrypoint --upgrade
+ "command -v su-exec 2>/dev/null && su-exec root /usr/bin/entrypoint --upgrade || sudo -S -i /usr/bin/entrypoint --upgrade"
done
diff --git a/docs/usage/distrobox-assemble.md b/docs/usage/distrobox-assemble.md
index 35150ca..807ae50 100644
--- a/docs/usage/distrobox-assemble.md
+++ b/docs/usage/distrobox-assemble.md
@@ -97,27 +97,27 @@ This is a list of available options with the corresponding type:
| Flag Name | Type |
| - | - |
-| additional_flags | string
-| additional_packages | string
-| home | string
-| image | string
-| init_hooks | string
-| pre_init_hooks | string
-| volume | string
-| exported_apps | string
-| exported_bins | string
-| exported_bins_path | string
-| entry | bool
-| start_now | bool
-| init | bool
-| nvidia | bool
-| pull | bool
-| root | bool
-| unshare_ipc | bool
-| unshare_netns | bool
-| unshare_process | bool
-| unshare_devsys | bool
-| unshare_all | bool
+| additional_flags | string |
+| additional_packages | string |
+| home | string |
+| image | string |
+| init_hooks | string |
+| pre_init_hooks | string |
+| volume | string |
+| exported_apps | string |
+| exported_bins | string |
+| exported_bins_path | string |
+| entry | bool |
+| start_now | bool |
+| init | bool |
+| nvidia | bool |
+| pull | bool |
+| root | bool |
+| unshare_ipc | bool |
+| unshare_netns | bool |
+| unshare_process | bool |
+| unshare_devsys | bool |
+| unshare_all | bool |
boolean options default to false if not specified.
string options can be broken in multiple declarations additively in order to improve
--
2.41.0