diff --git a/completions/zsh/_distrobox-create b/completions/zsh/_distrobox-create index fac0eefa54..0ac9ec9504 100755 --- a/completions/zsh/_distrobox-create +++ b/completions/zsh/_distrobox-create @@ -15,10 +15,14 @@ _arguments -s \ '--pre-init-hooks[additional commands to execute prior to container initialization]:command:' \ '(--init -I)'{-I,--init}'[use init system inside the container]' \ '--nvidia[try to integrate host nVidia drivers in the guest]' \ + '--unprivileged[do not drop security measures when creating a container]' \ '--unshare-devsys[do not share host devices and sysfs dirs from host]' \ + '--unshare-groups[do not forward user''s additional groups into the container]' \ + '--unshare-home[do not mount host home directory into the container]' \ '--unshare-ipc[do not share ipc namespace with host]' \ '--unshare-netns[do not share the net namespace with host]' \ '--unshare-process[do not share process namespace with host]' \ + '--unshare-root[do not mount host root directory into the container]' \ '--unshare-all[activate all the unshare flags]' \ '(--compatibility -C)'{-C,--compatibility}'[show list of compatible images]' \ '(--help -h)'{-h,--help}'[show this message]' \ diff --git a/distrobox-assemble b/distrobox-assemble index bd7b36c7a6..34e5dcfa6b 100755 --- a/distrobox-assemble +++ b/distrobox-assemble @@ -52,9 +52,12 @@ pre_init_hooks="" pull="" root="" start_now="" +unprivileged="" +unshare_home="" unshare_ipc="" unshare_netns="" unshare_process="" +unshare_root="" unshare_devsys="" unshare_all="" volume="" @@ -323,15 +326,24 @@ run_distrobox() if [ -n "${nvidia}" ] && [ "${nvidia}" -eq 1 ]; then result_command="${result_command} --nvidia" fi + if [ -n "${unprivileged}" ] && [ "${unprivileged}" -eq 1 ]; then + result_command="${result_command} --unprivileged" + fi if [ -n "${unshare_netns}" ] && [ "${unshare_netns}" -eq 1 ]; then result_command="${result_command} --unshare-netns" fi + if [ -n "${unshare_home}" ] && [ "${unshare_home}" -eq 1 ]; then + result_command="${result_command} --unshare-home" + fi if [ -n "${unshare_ipc}" ] && [ "${unshare_ipc}" -eq 1 ]; then result_command="${result_command} --unshare-ipc" fi if [ -n "${unshare_process}" ] && [ "${unshare_process}" -eq 1 ]; then result_command="${result_command} --unshare-process" fi + if [ -n "${unshare_root}" ] && [ "${unshare_root}" -eq 1 ]; then + result_command="${result_command} --unshare-root" + fi if [ -n "${unshare_devsys}" ] && [ "${unshare_devsys}" -eq 1 ]; then result_command="${result_command} --unshare-devsys" fi diff --git a/distrobox-create b/distrobox-create index 5503155e73..7bd2b0b858 100755 --- a/distrobox-create +++ b/distrobox-create @@ -80,10 +80,13 @@ init=0 non_interactive=0 nvidia=0 nopasswd=0 +unprivileged=0 unshare_ipc=0 unshare_groups=0 +unshare_home=0 unshare_netns=0 unshare_process=0 +unshare_root=0 unshare_devsys=0 # Use cd + dirname + pwd so that we do not have relative paths in mount points @@ -214,11 +217,14 @@ Options: 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-groups: do not forward user's additional groups into the container + --unprivileged: do not drop security measures when creating a container + --unshare-devsys: do not share host devices and sysfs dirs from host + --unshare-groups: do not forward user's additional groups into the container + --unshare-home: do not mount host home directory into the container --unshare-ipc: do not share ipc namespace with host --unshare-netns: do not share the net namespace with host - --unshare-process: do not share process namespace with host + --unshare-process: do not share process namespace with host + --unshare-root: do not mount host root directory into the container --unshare-all: activate all the unshare flags below --compatibility/-C: show list of compatible images --help/-h: show this message @@ -298,6 +304,10 @@ while :; do shift dryrun=1 ;; + --unprivileged) + shift + unprivileged=1 + ;; -r | --root) shift rootful=1 @@ -320,6 +330,10 @@ while :; do shift unshare_groups=1 ;; + --unshare-home) + shift + unshare_home=1 + ;; --unshare-netns) shift unshare_netns=1 @@ -328,6 +342,10 @@ while :; do shift unshare_process=1 ;; + --unshare-root) + shift + unshare_root=1 + ;; --unshare-devsys) shift unshare_devsys=1 @@ -337,8 +355,10 @@ while :; do unshare_devsys=1 unshare_groups=1 unshare_ipc=1 + unshare_home=1 unshare_netns=1 unshare_process=1 + unshare_root=1 ;; -C | --compatibility) show_compatibility @@ -640,11 +660,14 @@ get_clone_image() # init: bool initful # nvidia: bool nvidia integration # rootful: bool rootful +# unprivileged: bool unprivileged # unshare_devsys: bool unshare devsys # unshare_groups: bool unshare groups +# unshare_home: bool unshare home dir # unshare_ipc: bool unshare ipc # unshare_netns: bool unshare netns # unshare_process: bool unshare proc +# unshare_root: bool unshare root dir # Expected env variables: # None # Outputs: @@ -657,10 +680,6 @@ generate_create_command() result_command="${result_command} --hostname \"${container_hostname}\" --name \"${container_name}\" - --privileged - --security-opt label=disable - --security-opt apparmor=unconfined - --pids-limit=-1 --user root:root" if [ "${unshare_ipc}" -eq 0 ]; then @@ -690,23 +709,24 @@ generate_create_command() result_command="${result_command} --label \"manager=distrobox\" --label \"distrobox.unshare_groups=${unshare_groups}\" + --label \"distrobox.unshare_home=${unshare_home}\" + --label \"distrobox.unshare_root=${unshare_root}\" --env \"SHELL=$(basename "${SHELL:-"/bin/bash"}")\" - --env \"HOME=${container_user_home}\" --env \"container=${container_manager}\" --env \"TERMINFO_DIRS=/usr/share/terminfo:/run/host/usr/share/terminfo\" --env \"CONTAINER_ID=${container_name}\" --volume /tmp:/tmp:rslave --volume \"${distrobox_entrypoint_path}\":/usr/bin/entrypoint:ro --volume \"${distrobox_export_path}\":/usr/bin/distrobox-export:ro - --volume \"${distrobox_hostexec_path}\":/usr/bin/distrobox-host-exec:ro - --volume \"${container_user_home}\":\"${container_user_home}\":rslave" + --volume \"${distrobox_hostexec_path}\":/usr/bin/distrobox-host-exec:ro" # Due to breaking change in https://github.com/opencontainers/runc/commit/d4b670fca6d0ac606777376440ffe49686ce15f4 # now we cannot mount /:/run/host as before, as it will try to mount RO partitions as RW thus breaking things. # This will ensure we will mount directories one-by-one thus avoiding this problem. # # This happens ONLY with podman+runc, docker and lilipod are unaffected, so let's do this only if we have podman AND runc. - if echo "${container_manager}" | grep -q "podman" && ${container_manager} info | grep -q runc; then + if [ "${unshare_root}" -eq 0 ] && + echo "${container_manager}" | grep -q "podman" && ${container_manager} info | grep -q runc; then for rootdir in /*; do # Skip symlinks @@ -727,11 +747,18 @@ generate_create_command() result_command="${result_command} --volume ${rootdir}:/run/host${rootdir}:rslave" done - else + elif [ "${unshare_root}" -eq 0 ]; then # We're either on podman+crun, docker or lilipod, let's keep old behaviour result_command="${result_command} --volume /:/run/host/:rslave" + fi + if [ "${unprivileged}" -eq 0 ]; then + result_command="${result_command} + --privileged + --security-opt label=disable + --security-opt apparmor=unconfined + --pids-limit=-1" fi if [ "${unshare_devsys}" -eq 0 ]; then @@ -740,6 +767,12 @@ generate_create_command() --volume /sys:/sys:rslave" fi + if [ "${unshare_home}" -eq 0 ]; then + result_command="${result_command} + --env \"HOME=${container_user_home}\" + --volume \"${container_user_home}\":\"${container_user_home}\":rslave" + fi + # In case of initful containers, we implement a series of mountpoint in order # for systemd to work properly inside a container. # The following are a flag-based implementation of what podman's --systemd flag @@ -864,7 +897,8 @@ generate_create_command() # Mount also the /var/home dir on ostree based systems # do this only if $HOME was not already set to /var/home/username if [ "${container_user_home}" != "/var/home/${container_user_name}" ] && - [ -d "/var/home/${container_user_name}" ]; then + [ -d "/var/home/${container_user_name}" ] && + [ "${unshare_home}" -eq 0 ]; then result_command="${result_command} --volume \"/var/home/${container_user_name}\":\"/var/home/${container_user_name}\":rslave" @@ -873,7 +907,8 @@ generate_create_command() # Mount also the XDG_RUNTIME_DIR to ensure functionality of the apps. # This is skipped in case of initful containers, so that a dedicated # systemd user session can be used. - if [ -d "/run/user/${container_user_uid}" ] && [ "${init}" -eq 0 ]; then + if [ -d "/run/user/${container_user_uid}" ] && [ "${init}" -eq 0 ] && + [ "${unshare_root}" -eq 0 ]; then result_command="${result_command} --volume /run/user/${container_user_uid}:/run/user/${container_user_uid}:rslave" fi diff --git a/distrobox-enter b/distrobox-enter index 21fb7b0218..9ed129d865 100755 --- a/distrobox-enter +++ b/distrobox-enter @@ -365,6 +365,8 @@ fi # skip_workdir: bool skip workdir # verbose: bool verbose # unshare_groups +# unshare_home +# unshare_root # distrobox_enter_path # Expected env variables: # PATH @@ -427,8 +429,11 @@ generate_enter_command() # pass distrobox-enter path, it will be used in the distrobox-export tool. if [ "${skip_workdir}" -eq 0 ]; then workdir="$(echo "${PWD:-${container_home:-"/"}}" | sed -e 's/"/\\\"/g')" - if [ -n "${workdir##*"${container_home}"*}" ]; then + if [ "${unshare_root:-0}" -eq 0 ] && [ -n "${workdir##*"${container_home}"*}" ]; then workdir="/run/host${workdir}" + elif ! [ "${unshare_home:-0}" -eq 0 ]; then + # Workdir is unshared, we just enter $HOME of the container. + workdir="${container_home}" fi else # Skipping workdir we just enter $HOME of the container. @@ -562,11 +567,15 @@ generate_enter_command() container_home="${HOME}" container_path="${PATH}" unshare_groups=0 +unshare_home=0 +unshare_root=0 # Now inspect the container we're working with. container_status="unknown" eval "$(${container_manager} inspect --type container --format \ 'container_status={{.State.Status}}; unshare_groups={{ index .Config.Labels "distrobox.unshare_groups" }}; + unshare_home={{ index .Config.Labels "distrobox.unshare_home" }}; + unshare_root={{ index .Config.Labels "distrobox.unshare_root" }}; {{range .Config.Env}}{{if slice . 0 5 | eq "HOME="}}container_home={{slice . 5 | printf "%q"}};{{end}}{{end}} {{range .Config.Env}}{{if slice . 0 5 | eq "PATH="}}container_path={{slice . 5 | printf "%q"}}{{end}}{{end}}' \ "${container_name}")" diff --git a/distrobox-export b/distrobox-export index f09e404028..7d1a820fae 100755 --- a/distrobox-export +++ b/distrobox-export @@ -208,6 +208,12 @@ if [ ! -f /run/.containerenv ] && [ ! -f /.dockerenv ] && [ -z "${container:-}" exit 126 fi +# Check if host dir is mounted in this container +if [ ! -d /run/host ]; then + printf >&2 "Cannot run in container with unshared host directory!\n" + exit 126 +fi + # Check if we're in a rootful or rootless container. if grep -q "rootless=0" /run/.containerenv 2> /dev/null; then rootful="--root" diff --git a/distrobox-host-exec b/distrobox-host-exec index f4690f26f1..b6002e2326 100755 --- a/distrobox-host-exec +++ b/distrobox-host-exec @@ -132,6 +132,12 @@ if [ ! -f /run/.containerenv ] && [ ! -f /.dockerenv ] && [ -z "${container:-}" exit 126 fi +# Check if host dir is mounted in this container +if [ ! -d /run/host ]; then + printf >&2 "Cannot run in container with unshared host directory!\n" + exit 126 +fi + if [ -z "${host_command}" ]; then host_command="${distrobox_host_exec_default_command}" fi diff --git a/distrobox-init b/distrobox-init index bfe881a848..eae76ca773 100755 --- a/distrobox-init +++ b/distrobox-init @@ -1423,12 +1423,14 @@ fi # # Podman supports a mount option to do this at creation time, but we're doing it # here to support also other container rmanagers which does not support that flag -mount -t devpts devpts -o noexec,nosuid,newinstance,ptmxmode=0666,mode=0620,gid=tty /dev/pts/ -mount --bind /dev/pts/ptmx /dev/ptmx +{ + mount -t devpts devpts -o noexec,nosuid,newinstance,ptmxmode=0666,mode=0620,gid=tty /dev/pts/ + mount --bind /dev/pts/ptmx /dev/ptmx +} || printf "Warning: Cannot mount devpts\n" # Change mount propagation to shared to make the environment more similar to a # modern Linux system, e.g. with Systemd as PID 1. -mount --make-rshared / +mount --make-rshared / || printf "Warning: Cannot remount root as shared\n" ############################################################################### ############################################################################### diff --git a/docs/usage/distrobox-assemble.md b/docs/usage/distrobox-assemble.md index 9dbf486a35..5d9f0a8007 100644 --- a/docs/usage/distrobox-assemble.md +++ b/docs/usage/distrobox-assemble.md @@ -113,9 +113,12 @@ This is a list of available options with the corresponding type: | nvidia | bool | | pull | bool | | root | bool | +| unprivileged | bool | +| unshare_home | bool | | unshare_ipc | bool | | unshare_netns | bool | | unshare_process | bool | +| unshare_root | bool | | unshare_devsys | bool | | unshare_all | bool | diff --git a/docs/usage/distrobox-create.md b/docs/usage/distrobox-create.md index 4db7c77b16..e7809e8289 100644 --- a/docs/usage/distrobox-create.md +++ b/docs/usage/distrobox-create.md @@ -36,11 +36,14 @@ graphical apps (X11/Wayland), and audio. 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 + --unprivileged: do not drop security measures when creating a container --unshare-devsys: do not share host devices and sysfs dirs from host --unshare-groups: do not forward user's additional groups into the container + --unshare-home: do not mount host home directory into the container --unshare-ipc: do not share ipc namespace with host --unshare-netns: do not share the net namespace with host --unshare-process: do not share process namespace with host + --unshare-root: do not mount host root directory into the container --unshare-all: activate all the unshare flags below --compatibility/-C: show list of compatible images --help/-h: show this message diff --git a/man/man1/distrobox-assemble.1 b/man/man1/distrobox-assemble.1 index dd4d81ede4..6234b467dd 100644 --- a/man/man1/distrobox-assemble.1 +++ b/man/man1/distrobox-assemble.1 @@ -236,6 +236,16 @@ T}@T{ bool T} T{ +unprivileged +T}@T{ +bool +T} +T{ +unshare_home +T}@T{ +bool +T} +T{ unshare_ipc T}@T{ bool @@ -251,6 +261,11 @@ T}@T{ bool T} T{ +unshare_root +T}@T{ +bool +T} +T{ unshare_devsys T}@T{ bool diff --git a/man/man1/distrobox-create.1 b/man/man1/distrobox-create.1 index 86ac11cd4a..f043508c12 100644 --- a/man/man1/distrobox-create.1 +++ b/man/man1/distrobox-create.1 @@ -58,11 +58,14 @@ usb devices and graphical apps (X11/Wayland), and audio. this will make host\[aq]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\[aq]s nVidia drivers in the guest +--unprivileged: do not drop security measures when creating a container --unshare-devsys: do not share host devices and sysfs dirs from host --unshare-groups: do not forward user\[aq]s additional groups into the container +--unshare-home: do not mount host home directory into the container --unshare-ipc: do not share ipc namespace with host --unshare-netns: do not share the net namespace with host --unshare-process: do not share process namespace with host +--unshare-root: do not mount host root directory into the container --unshare-all: activate all the unshare flags below --compatibility/-C: show list of compatible images --help/-h: show this message diff --git a/man/man1/distrobox.1 b/man/man1/distrobox.1 index cd4b2375cc..db95050a9c 100644 --- a/man/man1/distrobox.1 +++ b/man/man1/distrobox.1 @@ -236,6 +236,16 @@ T}@T{ bool T} T{ +unprivileged +T}@T{ +bool +T} +T{ +unshare_home +T}@T{ +bool +T} +T{ unshare_ipc T}@T{ bool @@ -251,6 +261,11 @@ T}@T{ bool T} T{ +unshare_root +T}@T{ +bool +T} +T{ unshare_devsys T}@T{ bool @@ -847,11 +862,14 @@ usb devices and graphical apps (X11/Wayland), and audio. this will make host\[aq]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\[aq]s nVidia drivers in the guest +--unprivileged: do not drop security measures when creating a container --unshare-devsys: do not share host devices and sysfs dirs from host --unshare-groups: do not forward user\[aq]s additional groups into the container +--unshare-home: do not mount host home directory into the container --unshare-ipc: do not share ipc namespace with host --unshare-netns: do not share the net namespace with host --unshare-process: do not share process namespace with host +--unshare-root: do not mount host root directory into the container --unshare-all: activate all the unshare flags below --compatibility/-C: show list of compatible images --help/-h: show this message