mirror of
https://github.com/9001/copyparty.git
synced 2025-08-16 00:22:13 -06:00
164 lines
4.2 KiB
Bash
Executable file
164 lines
4.2 KiB
Bash
Executable file
#!/bin/bash
|
|
set -e
|
|
|
|
# runs copyparty (or any other program really) in a chroot
|
|
#
|
|
# assumption: these directories, and everything within, are owned by root
|
|
sysdirs=(); for v in /bin /lib /lib32 /lib64 /sbin /usr /etc/alternatives ; do
|
|
[ -e $v ] && sysdirs+=($v)
|
|
done
|
|
|
|
# error-handler
|
|
help() { cat <<'EOF'
|
|
|
|
usage:
|
|
./prisonparty.sh <ROOTDIR> <USER|UID> <GROUP|GID> [VOLDIR [VOLDIR...]] -- python3 copyparty-sfx.py [...]
|
|
|
|
example:
|
|
./prisonparty.sh /var/lib/copyparty-jail cpp cpp /mnt/nas/music -- python3 copyparty-sfx.py -v /mnt/nas/music::rwmd
|
|
|
|
example for running straight from source (instead of using an sfx):
|
|
PYTHONPATH=$PWD ./prisonparty.sh /var/lib/copyparty-jail cpp cpp /mnt/nas/music -- python3 -um copyparty -v /mnt/nas/music::rwmd
|
|
|
|
note that if you have python modules installed as --user (such as bpm/key detectors),
|
|
you should add /home/foo/.local as a VOLDIR
|
|
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
|
|
errs=
|
|
for c in awk chroot dirname getent lsof mknod mount realpath sed sort stat uniq; do
|
|
command -v $c >/dev/null || {
|
|
echo ERROR: command not found: $c
|
|
errs=1
|
|
}
|
|
done
|
|
[ $errs ] && exit 1
|
|
|
|
|
|
# read arguments
|
|
trap help EXIT
|
|
jail="$(realpath "$1")"; shift
|
|
uid="$1"; shift
|
|
gid="$1"; shift
|
|
|
|
vols=()
|
|
while true; do
|
|
v="$1"; shift
|
|
[ "$v" = -- ] && break # end of volumes
|
|
[ "$#" -eq 0 ] && break # invalid usage
|
|
vols+=( "$(realpath "$v" || echo "$v")" )
|
|
done
|
|
pybin="$1"; shift
|
|
pybin="$(command -v "$pybin")"
|
|
pyarg=
|
|
while true; do
|
|
v="$1"
|
|
[ "${v:0:1}" = - ] || break
|
|
pyarg="$pyarg $v"
|
|
shift
|
|
done
|
|
cpp="$1"; shift
|
|
[ -d "$cpp" ] && cppdir="$PWD" || {
|
|
# sfx, not module
|
|
cpp="$(realpath "$cpp")"
|
|
cppdir="$(dirname "$cpp")"
|
|
}
|
|
trap - EXIT
|
|
|
|
usr="$(getent passwd $uid | cut -d: -f1)"
|
|
[ "$usr" ] || { echo "ERROR invalid username/uid $uid"; exit 1; }
|
|
uid="$(getent passwd $uid | cut -d: -f3)"
|
|
|
|
grp="$(getent group $gid | cut -d: -f1)"
|
|
[ "$grp" ] || { echo "ERROR invalid groupname/gid $gid"; exit 1; }
|
|
gid="$(getent group $gid | cut -d: -f3)"
|
|
|
|
# debug/vis
|
|
echo
|
|
echo "chroot-dir = $jail"
|
|
echo "user:group = $uid:$gid ($usr:$grp)"
|
|
echo " copyparty = $cpp"
|
|
echo
|
|
printf '\033[33m%s\033[0m\n' "copyparty can access these folders and all their subdirectories:"
|
|
for v in "${vols[@]}"; do
|
|
printf '\033[36m ├─\033[0m %s \033[36m ── added by (You)\033[0m\n' "$v"
|
|
done
|
|
printf '\033[36m ├─\033[0m %s \033[36m ── where the copyparty binary is\033[0m\n' "$cppdir"
|
|
printf '\033[36m ╰─\033[0m %s \033[36m ── the folder you are currently in\033[0m\n' "$PWD"
|
|
vols+=("$cppdir" "$PWD")
|
|
echo
|
|
|
|
|
|
# remove any trailing slashes
|
|
jail="${jail%/}"
|
|
|
|
|
|
# bind-mount system directories and volumes
|
|
for a in {1..30}; do mkdir "$jail/.prisonlock" && break; sleep 0.1; done
|
|
printf '%s\n' "${sysdirs[@]}" "${vols[@]}" | sed -r 's`/$``' | LC_ALL=C sort | uniq |
|
|
while IFS= read -r v; do
|
|
[ -e "$v" ] || {
|
|
printf '\033[1;31mfolder does not exist:\033[0m %s\n' "$v"
|
|
continue
|
|
}
|
|
i1=$(stat -c%D.%i "$v/" 2>/dev/null || echo a)
|
|
i2=$(stat -c%D.%i "$jail$v/" 2>/dev/null || echo b)
|
|
[ $i1 = $i2 ] && continue
|
|
mount | grep -qF " $jail$v " && echo wtf $i1 $i2 $v && continue
|
|
mkdir -p "$jail$v"
|
|
mount --bind "$v" "$jail$v"
|
|
done
|
|
rmdir "$jail/.prisonlock" || true
|
|
|
|
|
|
cln() {
|
|
trap - EXIT
|
|
wait -f -n $p && rv=0 || rv=$?
|
|
cd /
|
|
echo "stopping chroot..."
|
|
for a in {1..30}; do mkdir "$jail/.prisonlock" && break; sleep 0.1; done
|
|
lsof "$jail" 2>/dev/null | grep -F "$jail" &&
|
|
echo "chroot is in use; will not unmount" ||
|
|
{
|
|
mount | grep -F " on $jail" |
|
|
awk '{sub(/ type .*/,"");sub(/.* on /,"");print}' |
|
|
LC_ALL=C sort -r | while IFS= read -r v; do
|
|
umount "$v" && echo "umount OK: $v"
|
|
done
|
|
}
|
|
rmdir "$jail/.prisonlock" || true
|
|
exit $rv
|
|
}
|
|
trap cln EXIT
|
|
|
|
|
|
# create a tmp
|
|
mkdir -p "$jail/tmp"
|
|
chmod 777 "$jail/tmp"
|
|
|
|
|
|
# create a dev
|
|
(cd $jail; mkdir -p dev; cd dev
|
|
[ -e null ] || mknod -m 666 null c 1 3
|
|
[ -e zero ] || mknod -m 666 zero c 1 5
|
|
[ -e random ] || mknod -m 444 random c 1 8
|
|
[ -e urandom ] || mknod -m 444 urandom c 1 9
|
|
)
|
|
|
|
|
|
# run copyparty
|
|
export HOME="$(getent passwd $uid | cut -d: -f6)"
|
|
export USER="$usr"
|
|
export LOGNAME="$USER"
|
|
#echo "pybin [$pybin]"
|
|
#echo "pyarg [$pyarg]"
|
|
#echo "cpp [$cpp]"
|
|
chroot --userspec=$uid:$gid "$jail" "$pybin" $pyarg "$cpp" "$@" &
|
|
p=$!
|
|
trap 'kill -USR1 $p' USR1
|
|
trap 'trap - INT TERM; kill $p' INT TERM
|
|
wait
|