| 1 | #!/bin/sh
|
| 2 | #
|
| 3 | # Enter an Alpine rootfs with bwrap, not chroot.
|
| 4 | #
|
| 5 | # This is an ALTERNATIVE to 'enter-chroot'. It's not a "hook", like
|
| 6 | # regtest/enter-hook-{bwrap,chroot}
|
| 7 |
|
| 8 | set -e
|
| 9 |
|
| 10 | rootfs_dir=${1:-}
|
| 11 | if test -z "$rootfs_dir"; then
|
| 12 | # $this_dir idiom
|
| 13 | rootfs_dir=$(cd $(dirname "$0"); pwd)
|
| 14 | fi
|
| 15 |
|
| 16 | user=${2:-root}
|
| 17 |
|
| 18 | # abuild rootbld has --unshare-ipc, etc. but has OPTION for --unshare-net.
|
| 19 | # It doesn't use --unshare-all. Don't use that; specify everything explicitly
|
| 20 | bwrap_flags=${3:-}
|
| 21 |
|
| 22 | shift 3
|
| 23 |
|
| 24 | # Awk script that is nicer than:
|
| 25 | # getent passwd "$user"
|
| 26 |
|
| 27 | temp_prefix="/tmp/$$"
|
| 28 |
|
| 29 | uid_file=$temp_prefix.uid.txt
|
| 30 | gid_file=$temp_prefix.gid.txt
|
| 31 | home_file=$temp_prefix.home.txt
|
| 32 | shell_file=$temp_prefix.shell.txt
|
| 33 |
|
| 34 | awk -F : \
|
| 35 | -v user=$user \
|
| 36 | -v uid_file=$uid_file \
|
| 37 | -v gid_file=$gid_file \
|
| 38 | -v home_file=$home_file \
|
| 39 | -v shell_file=$shell_file \
|
| 40 | '
|
| 41 | $1 == user {
|
| 42 | #printf("FOUND User %s in the rootfs\n", user);
|
| 43 | print $3 > uid_file
|
| 44 | print $4 > gid_file
|
| 45 | print $6 > home_file
|
| 46 | print $7 > shell_file
|
| 47 | found = 1
|
| 48 | exit # jumps to the END block
|
| 49 | }
|
| 50 |
|
| 51 | END {
|
| 52 | if (found == 0) {
|
| 53 | printf("User %s not found in the rootfs\n", user);
|
| 54 | exit 1
|
| 55 | }
|
| 56 | }
|
| 57 | ' $rootfs_dir/etc/passwd
|
| 58 |
|
| 59 | # Note: there is a slurp operator in bash/ksh $(<file)
|
| 60 | uid=$(cat $uid_file)
|
| 61 | gid=$(cat $gid_file)
|
| 62 | user_home=$(cat $home_file)
|
| 63 | user_shell=$(cat $shell_file)
|
| 64 |
|
| 65 | # Clean up
|
| 66 | rm $temp_prefix*
|
| 67 |
|
| 68 | if false; then
|
| 69 | echo uid=$uid
|
| 70 | echo gid=$gid
|
| 71 | echo home=$user_home
|
| 72 | echo shell=$user_shell
|
| 73 | fi
|
| 74 |
|
| 75 | if true; then
|
| 76 |
|
| 77 | # This is a ROOTLESS alternative to the method in:
|
| 78 | # https://github.com/oils-for-unix/alpine-chroot-install/blob/master/alpine-chroot-install#L192
|
| 79 | #
|
| 80 | # $_sudo chroot . /usr/bin/env -i su -l "$user" \
|
| 81 | # sh -c ". /etc/profile; . /env.sh; cd '$oldpwd' 2>/dev/null; \"\$@\"" \
|
| 82 | # -- "${@:-sh}"
|
| 83 | #
|
| 84 | # - No sudo; bwrap is rootless
|
| 85 | # - No chroot; bwrap has --bind $rootfs_dir /
|
| 86 | # - No env -i; bwrap has --clearenv
|
| 87 | # - No su -l; we run sh -l
|
| 88 | # - this is not POSIX, but I think all shells we acre about support it (dash,
|
| 89 | # busybox ash, bash)
|
| 90 | # - No su $user, we get the uid with awk, and pass --uid $uid to bwrap
|
| 91 | # - No . /etc/profile - sh -l does that
|
| 92 | # - No env.sh, because we need a clean environment
|
| 93 | # - No cd, I think $sh -l reads that from $HOME
|
| 94 | #
|
| 95 | # Note that we set $USER $LOGNAME $SHELL $HOME
|
| 96 | #
|
| 97 | # This s simpler, but the problem is when we have TWO UIDs - root uid=0 and udu
|
| 98 | # uid=1000. TODO: Experiment with chown everything as a user.
|
| 99 |
|
| 100 | # Note: overflow{uid,gid} are necessary for nested bwrap? They are just a file
|
| 101 | # containing 65534 (nobody)
|
| 102 |
|
| 103 | bwrap \
|
| 104 | $bwrap_flags \
|
| 105 | --unshare-user \
|
| 106 | --uid $uid \
|
| 107 | --gid $gid \
|
| 108 | --clearenv \
|
| 109 | --setenv USER $user \
|
| 110 | --setenv LOGNAME $user \
|
| 111 | --setenv SHELL $user_shell \
|
| 112 | --setenv HOME $user_home \
|
| 113 | --bind "$rootfs_dir" / \
|
| 114 | --proc /proc \
|
| 115 | --bind /proc/sys/kernel/overflowuid /proc/sys/kernel/overflowuid \
|
| 116 | --bind /proc/sys/kernel/overflowgid /proc/sys/kernel/overflowgid \
|
| 117 | --dev /dev \
|
| 118 | -- \
|
| 119 | $user_shell -l -c ' "$@" ' dummy0 "${@:-sh}"
|
| 120 |
|
| 121 | else
|
| 122 | # this requires root, because su requires root
|
| 123 |
|
| 124 | bwrap \
|
| 125 | $bwrap_flags \
|
| 126 | --bind "$rootfs_dir" / \
|
| 127 | --proc /proc \
|
| 128 | --bind /proc/sys/kernel/overflowuid /proc/sys/kernel/overflowuid \
|
| 129 | --bind /proc/sys/kernel/overflowgid /proc/sys/kernel/overflowgid \
|
| 130 | --dev /dev \
|
| 131 | -- \
|
| 132 | /usr/bin/env -i -- \
|
| 133 | su -l "$user" -- -c '. /etc/profile; . /env.sh; "$@"' dummy0 "${@:-sh}"
|
| 134 | fi
|