[PATCH 0/4] libvirt_recover_xattrs: Improve usability for libvirt development

I run into scenarios where I forget to destroy a VM which has a new WIP qemu capability. Starting a libvirtd which doesn't support it yet makes the libvirt vanish, thus after manually killing it libvirtd doesn't clear the xattrs, making it impossible to start the VM. libvirt_recover_xattrs fixes this, but is unusable unless you want to turn off all VMs. Peter Krempa (4): libvirt_recover_xattrs: Avoid backticks for subshell libvirt_recover_xattrs: Use only the correct xattr prefix libvirt_recover_xattrs: Add unsafe operation mode libvirt_recover_xattrs: Allow fixing multiple PATHs tools/libvirt_recover_xattrs.sh | 64 ++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 21 deletions(-) -- 2.28.0

Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tools/libvirt_recover_xattrs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/libvirt_recover_xattrs.sh b/tools/libvirt_recover_xattrs.sh index 3907413c63..cb98497732 100755 --- a/tools/libvirt_recover_xattrs.sh +++ b/tools/libvirt_recover_xattrs.sh @@ -34,7 +34,7 @@ URI=("qemu:///system" LIBVIRT_XATTR_PREFIXES=("trusted.libvirt.security" "system.libvirt.security") -if [ `whoami` != "root" ]; then +if [ $(whoami) != "root" ]; then die "Must be run as root" fi -- 2.28.0

Linux and FreeBSD have different prefix. In the current state we've tried to reset the labels for both systems which resulted in errors like this: Fixing /tmp/bitmaps2.qcow2 setfattr: /tmp/bitmaps2.qcow2: Operation not supported setfattr: /tmp/bitmaps2.qcow2: Operation not supported setfattr: /tmp/bitmaps2.qcow2: Operation not supported setfattr: /tmp/bitmaps2.qcow2: Operation not supported setfattr: /tmp/bitmaps2.qcow2: Operation not supported setfattr: /tmp/bitmaps2.qcow2: Operation not supported The 6 failed 'setfattrs' correspond to the wrong prefix. Select the correct prefix based on the kernel name and modify the code appropriately. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tools/libvirt_recover_xattrs.sh | 48 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/tools/libvirt_recover_xattrs.sh b/tools/libvirt_recover_xattrs.sh index cb98497732..b7a8c05cf4 100755 --- a/tools/libvirt_recover_xattrs.sh +++ b/tools/libvirt_recover_xattrs.sh @@ -29,11 +29,6 @@ DIR="/" URI=("qemu:///system" "lxc:///system") -# On Linux we use 'trusted' namespace, on FreeBSD we use 'system' -# as there is no 'trusted'. -LIBVIRT_XATTR_PREFIXES=("trusted.libvirt.security" - "system.libvirt.security") - if [ $(whoami) != "root" ]; then die "Must be run as root" fi @@ -62,6 +57,21 @@ if [ $# -gt 0 ]; then DIR=$1 fi +case $(uname -s) in + Linux) + XATTR_PREFIX="trusted.libvirt.security" + ;; + + FreeBSD) + XATTR_PREFIX="system.libvirt.security" + ;; + + *) + die "$0 is not supported on this platform" + ;; +esac + + if [ ${DRY_RUN} -eq 0 ]; then for u in ${URI[*]} ; do if [ -n "`virsh -q -c $u list 2>/dev/null`" ]; then @@ -73,24 +83,20 @@ fi declare -a XATTRS for i in "dac" "selinux"; do - for p in ${LIBVIRT_XATTR_PREFIXES[@]}; do - XATTRS+=("$p.$i" "$p.ref_$i" "$p.timestamp_$i") - done + XATTRS+=("$XATTR_PREFIX.$i" "$XATTR_PREFIX.ref_$i" "$XATTR_PREFIX.timestamp_$i") done -for p in ${LIBVIRT_XATTR_PREFIXES[*]}; do - for i in $(getfattr -R -d -m ${p} --absolute-names ${DIR} 2>/dev/null | grep "^# file:" | cut -d':' -f 2); do - echo $i; - if [ ${DRY_RUN} -ne 0 ]; then - getfattr -d -m $p --absolute-names $i | grep -v "^# file:" - continue - fi - if [ ${QUIET} -eq 0 ]; then - echo "Fixing $i"; - fi - for x in ${XATTRS[*]}; do - setfattr -x $x $i - done +for i in $(getfattr -R -d -m ${XATTR_PREFIX} --absolute-names ${DIR} 2>/dev/null | grep "^# file:" | cut -d':' -f 2); do + if [ ${DRY_RUN} -ne 0 ]; then + getfattr -d -m $p --absolute-names $i | grep -v "^# file:" + continue + fi + + if [ ${QUIET} -eq 0 ]; then + echo "Fixing $i"; + fi + for x in ${XATTRS[*]}; do + setfattr -x $x $i done done -- 2.28.0

In some cases you want to fix a certain directory while you don't really care whether there are other VMs running. Add a option to disable the check. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tools/libvirt_recover_xattrs.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/libvirt_recover_xattrs.sh b/tools/libvirt_recover_xattrs.sh index b7a8c05cf4..bb5f23cff0 100755 --- a/tools/libvirt_recover_xattrs.sh +++ b/tools/libvirt_recover_xattrs.sh @@ -7,7 +7,7 @@ function die { function show_help { cat << EOF -Usage: ${0##*/} -[hqn] [PATH] +Usage: ${0##*/} -[hqnu] [PATH] Clear out any XATTRs set by libvirt on all files that have them. The idea is to reset refcounting, should it break. @@ -15,6 +15,7 @@ The idea is to reset refcounting, should it break. -h display this help and exit -q quiet (don't print which files are being fixed) -n dry run; don't remove any XATTR just report the file name + -u unsafe; don't check whether there are running VMs; PATH must be specified PATH can be specified to refine search to only to given path instead of whole root ('/'), which is the default. @@ -23,6 +24,7 @@ EOF QUIET=0 DRY_RUN=0 +UNSAFE=0 DIR="/" # So far only qemu and lxc drivers use security driver. @@ -33,7 +35,7 @@ if [ $(whoami) != "root" ]; then die "Must be run as root" fi -while getopts hqn opt; do +while getopts hqnu opt; do case $opt in h) show_help @@ -45,6 +47,9 @@ while getopts hqn opt; do n) DRY_RUN=1 ;; + u) + UNSAFE=1 + ;; *) show_help >&2 exit 1 @@ -55,6 +60,10 @@ done shift $((OPTIND - 1)) if [ $# -gt 0 ]; then DIR=$1 +else + if [ ${UNSAFE} -eq 1 ]; then + die "Unsafe mode (-u) requires explicit 'PATH' argument" + fi fi case $(uname -s) in @@ -72,7 +81,7 @@ case $(uname -s) in esac -if [ ${DRY_RUN} -eq 0 ]; then +if [ ${DRY_RUN} -eq 0 ] && [ ${UNSAFE} -eq 0 ]; then for u in ${URI[*]} ; do if [ -n "`virsh -q -c $u list 2>/dev/null`" ]; then die "There are still some domains running for $u" -- 2.28.0

Loop for multiple PATH arguments to support shell pattern expansion. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tools/libvirt_recover_xattrs.sh | 51 +++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/tools/libvirt_recover_xattrs.sh b/tools/libvirt_recover_xattrs.sh index bb5f23cff0..59f1f3f476 100755 --- a/tools/libvirt_recover_xattrs.sh +++ b/tools/libvirt_recover_xattrs.sh @@ -7,7 +7,7 @@ function die { function show_help { cat << EOF -Usage: ${0##*/} -[hqnu] [PATH] +Usage: ${0##*/} -[hqnu] [PATH ...] Clear out any XATTRs set by libvirt on all files that have them. The idea is to reset refcounting, should it break. @@ -25,7 +25,6 @@ EOF QUIET=0 DRY_RUN=0 UNSAFE=0 -DIR="/" # So far only qemu and lxc drivers use security driver. URI=("qemu:///system" @@ -57,15 +56,6 @@ while getopts hqnu opt; do esac done -shift $((OPTIND - 1)) -if [ $# -gt 0 ]; then - DIR=$1 -else - if [ ${UNSAFE} -eq 1 ]; then - die "Unsafe mode (-u) requires explicit 'PATH' argument" - fi -fi - case $(uname -s) in Linux) XATTR_PREFIX="trusted.libvirt.security" @@ -95,17 +85,34 @@ for i in "dac" "selinux"; do XATTRS+=("$XATTR_PREFIX.$i" "$XATTR_PREFIX.ref_$i" "$XATTR_PREFIX.timestamp_$i") done +fix_xattrs() { + local DIR="$1" -for i in $(getfattr -R -d -m ${XATTR_PREFIX} --absolute-names ${DIR} 2>/dev/null | grep "^# file:" | cut -d':' -f 2); do - if [ ${DRY_RUN} -ne 0 ]; then - getfattr -d -m $p --absolute-names $i | grep -v "^# file:" - continue - fi + for i in $(getfattr -R -d -m ${XATTR_PREFIX} --absolute-names ${DIR} 2>/dev/null | grep "^# file:" | cut -d':' -f 2); do + if [ ${DRY_RUN} -ne 0 ]; then + getfattr -d -m $p --absolute-names $i | grep -v "^# file:" + continue + fi - if [ ${QUIET} -eq 0 ]; then - echo "Fixing $i"; - fi - for x in ${XATTRS[*]}; do - setfattr -x $x $i + if [ ${QUIET} -eq 0 ]; then + echo "Fixing $i"; + fi + for x in ${XATTRS[*]}; do + setfattr -x $x $i + done done -done +} + + +shift $((OPTIND - 1)) +if [ $# -gt 0 ]; then + while [ $# -gt 0 ]; do + fix_xattrs "$1" + shift $((OPTIND - 1)) + done +else + if [ ${UNSAFE} -eq 1 ]; then + die "Unsafe mode (-u) requires explicit 'PATH' argument" + fi + fix_xattrs "/" +fi -- 2.28.0

On 12/2/20 11:43 AM, Peter Krempa wrote:
I run into scenarios where I forget to destroy a VM which has a new WIP qemu capability. Starting a libvirtd which doesn't support it yet makes the libvirt vanish, thus after manually killing it libvirtd doesn't clear the xattrs, making it impossible to start the VM.
libvirt_recover_xattrs fixes this, but is unusable unless you want to turn off all VMs.
Peter Krempa (4): libvirt_recover_xattrs: Avoid backticks for subshell libvirt_recover_xattrs: Use only the correct xattr prefix libvirt_recover_xattrs: Add unsafe operation mode libvirt_recover_xattrs: Allow fixing multiple PATHs
tools/libvirt_recover_xattrs.sh | 64 ++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 21 deletions(-)
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (2)
-
Michal Privoznik
-
Peter Krempa