Add remap-uid-and-gid-for-lv

I've used this script to remap files' uids/gids of containers created
without a custom userns into their new range.  It's inferior to
`fuidshift` from the `lxc` project in that it doesn't handle ACLs and is
quite slow - probably because it calls a binary for every file.

By default, it runs in debug mode only printing the chown command
instead of executing it. You need to edit the file to use it.

It also only works with LVs (logical volumes from LVM), mounting them
automatically.
This commit is contained in:
MasterofJOKers 2023-02-25 17:15:23 +01:00
parent 271d7009cf
commit 845e3fe30e
1 changed files with 71 additions and 0 deletions

71
lxc/remap-uid-and-gid-for-lv Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
# Remap all files uid/gid to a new range
#
# This is an inferior version of `fuidshift` from the `lxd-tools` Debian package, as it only handles uid/gid and
# doesn't handle ACLs and thus journalctl's files and by that hinders updating systemd inside the container. It's also
# quite slow.
usage () {
echo "remap-uid-and-gid <container-name> [<target-lv>]"
printf "\nIf <target-lv> is not given it is computed from a default value with the given container name\n"
exit 1
}
CONTAINER_NAME="${1}"
if [ "${CONTAINER_NAME}" = "" ]; then
usage
fi
TARGET_LV="${2}"
if [ "${TARGET_LV}" = "" ]; then
GUESSED_LV="/dev/mapper/daffy--vg-lxc--${CONTAINER_NAME}"
if [ -e "${GUESSED_LV}" ]; then
TARGET_LV="${GUESSED_LV}"
fi
fi
if [ "${TARGET_LV}" = "" ]; then
usage
fi
if mount | grep -qF " on /mnt"; then
echo "Mountpoint /mnt is already in use."
exit 1
fi
mount "${TARGET_LV}" /mnt
cd /mnt
ROOT_USER_ID=$(get-lxc-idmap-config u $CONTAINER_NAME | cut -d ' ' -f 5)
ROOT_GROUP_ID=$(get-lxc-idmap-config g $CONTAINER_NAME | cut -d ' ' -f 5)
printf "uid: %s gid: %s\n" $ROOT_USER_ID $ROOT_GROUP_ID
# We ignore links here, because they might not point to a valid location and would make our program fail. They are also
# owned by whoever mounted the filesystem it seems, so don't need a chown.
find . -xdev -not -type l -printf "%U %G %p\n" | \
while read F; do
U=$(echo $F | cut -d ' ' -f 1)
if [ ${U} -lt ${ROOT_USER_ID} ] || [ ${U} -gt $(( ${ROOT_USER_ID} + 65535 )) ]; then
NEW_U=$(( ${U} + ${ROOT_USER_ID} ))
else
NEW_U=${U}
fi
G=$(echo $F | cut -d ' ' -f 2)
if [ ${G} -lt ${ROOT_GROUP_ID} ] || [ ${G} -gt $(( ${ROOT_GROUP_ID} + 65535 )) ]; then
NEW_G=$(( ${G} + ${ROOT_GROUP_ID} ))
else
NEW_G=${G}
fi
if [ "${U}" = "${NEW_U}" ] && [ "${G}" = "${NEW_G}" ]; then
continue
fi
P=$(echo $F | cut -d ' ' -f 3-)
printf "chown %s:%s %s\n" ${NEW_U} ${NEW_G} "${P}"
# chown ${NEW_U}:${NEW_G} "${P}"
done
cd /
umount /mnt