policycoreutils: fixfiles: refactor into the `set -u` dialect

This commit allows the use of `set -u` to detect reads of unset variables.
But what I really liked was making the code more explicit about these
modes.  I hope that this is easier for a new reader to reason about.

`fixfiles restore` has accumulated five different modes it can run in.
Now use a single variable to indicate the mode, out-of-band of the
variables used for the individual modes.

Apparently `set -u` / `set -o nounset` doesn't work correctly with arrays.
If we ever need bash arrays, we can simply remove `set -u`.  The `set -u`
dialect is a strict subset.  See http://mywiki.wooledge.org/BashFAQ/112

Extra notes:

RESTORE_MODE was created because I couldn't bring myself to use an empty
FILEPATH, as a special case to indicate the default mode.  Arguments
to the script (paths) could be empty already, so it would mean I had to
work out how we behaved in that case and decide whether it was reasonable.

It turns out the `-B | -N time` mode is distinct and does not respect
paths.  So we can tell the user we're not going to do anything with the
paths they passed.  Make sure this distinction is shown in the usage error
message.

We already rejected the combination of `-R rpmpackage,... dir/file...`.
Being aware of the different modes just causes more bogus combinations
to be rejected.

Signed-off-by: Alan Jenkins <alan.christopher.jenkins@gmail.com>
This commit is contained in:
Alan Jenkins 2017-05-07 12:05:52 +01:00 committed by James Carter
parent f499b02feb
commit 3475893b6f
2 changed files with 94 additions and 75 deletions

View File

@ -20,6 +20,8 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
set -o nounset
# #
# seclabel support was added in 2.6.30. This function will return a positive # seclabel support was added in 2.6.30. This function will return a positive
# number if the current kernel version is greater than 2.6.30, a negative # number if the current kernel version is greater than 2.6.30, a negative
@ -107,7 +109,9 @@ fullFlag=0
BOOTTIME="" BOOTTIME=""
VERBOSE="-p" VERBOSE="-p"
FORCEFLAG="" FORCEFLAG=""
RPMILES="" RPMFILES=""
PREFC=""
RESTORE_MODE="DEFAULT"
SETFILES=/sbin/setfiles SETFILES=/sbin/setfiles
RESTORECON=/sbin/restorecon RESTORECON=/sbin/restorecon
FILESYSTEMSRW=`get_rw_labeled_mounts` FILESYSTEMSRW=`get_rw_labeled_mounts`
@ -209,50 +213,57 @@ restore () {
OPTION=$1 OPTION=$1
shift shift
if [ ! -z "$PREFC" ]; then case "$RESTORE_MODE" in
diff_filecontext $* PREFC)
exit $? diff_filecontext $*
fi exit $?
if [ ! -z "$BOOTTIME" ]; then ;;
newer $BOOTTIME $* BOOTTIME)
exit $? newer $BOOTTIME $*
fi exit $?
;;
esac
[ -x /usr/sbin/genhomedircon ] && /usr/sbin/genhomedircon [ -x /usr/sbin/genhomedircon ] && /usr/sbin/genhomedircon
EXCLUDEDIRS="`exclude_dirs_from_relabelling`" EXCLUDEDIRS="`exclude_dirs_from_relabelling`"
LogExcluded LogExcluded
if [ ! -z "$RPMFILES" ]; then case "$RESTORE_MODE" in
for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do RPMFILES)
rpmlist $i | ${RESTORECON} ${EXCLUDEDIRS} ${FORCEFLAG} ${VERBOSE} $* -R -i -f - for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do
done rpmlist $i | ${RESTORECON} ${EXCLUDEDIRS} ${FORCEFLAG} ${VERBOSE} $* -R -i -f -
exit $? done
fi exit $?
if [ ! -z "$FILEPATH" ]; then ;;
${RESTORECON} ${EXCLUDEDIRS} ${FORCEFLAG} ${VERBOSE} -R $* -- "$FILEPATH" FILEPATH)
return ${RESTORECON} ${EXCLUDEDIRS} ${FORCEFLAG} ${VERBOSE} -R $* -- "$FILEPATH"
fi return # to loop over each FILEPATH
if [ -n "${FILESYSTEMSRW}" ]; then ;;
LogReadOnly DEFAULT)
echo "${OPTION}ing `echo ${FILESYSTEMSRW}`" if [ -n "${FILESYSTEMSRW}" ]; then
${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} -q ${FORCEFLAG} $* ${FC} ${FILESYSTEMSRW} LogReadOnly
else echo "${OPTION}ing `echo ${FILESYSTEMSRW}`"
echo >&2 "fixfiles: No suitable file systems found" ${SETFILES} ${VERBOSE} ${EXCLUDEDIRS} -q ${FORCEFLAG} $* ${FC} ${FILESYSTEMSRW}
fi else
if [ ${OPTION} != "Relabel" ]; then echo >&2 "fixfiles: No suitable file systems found"
return fi
fi if [ ${OPTION} != "Relabel" ]; then
echo "Cleaning up labels on /tmp" return
rm -rf /tmp/gconfd-* /tmp/pulse-* /tmp/orbit-* fi
echo "Cleaning up labels on /tmp"
rm -rf /tmp/gconfd-* /tmp/pulse-* /tmp/orbit-*
UNDEFINED=`get_undefined_type` || exit $? UNDEFINED=`get_undefined_type` || exit $?
UNLABELED=`get_unlabeled_type` || exit $? UNLABELED=`get_unlabeled_type` || exit $?
find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) \( -type s -o -type p \) -delete find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) \( -type s -o -type p \) -delete
find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /tmp {} \; find /tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /tmp {} \;
find /var/tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /var/tmp {} \; find /var/tmp \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /var/tmp {} \;
find /var/run \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /var/run {} \; find /var/run \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /var/run {} \;
[ ! -e /var/lib/debug ] || find /var/lib/debug \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /lib {} \; [ ! -e /var/lib/debug ] || find /var/lib/debug \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /lib {} \;
exit 0 exit 0
;;
esac
} }
fullrelabel() { fullrelabel() {
@ -263,7 +274,7 @@ fullrelabel() {
} }
relabel() { relabel() {
if [ ! -z "$RPMFILES" ]; then if [ "$RESTORE_MODE" == RPMFILES ]; then
restore Relabel restore Relabel
fi fi
@ -309,7 +320,9 @@ esac
} }
usage() { usage() {
echo $""" echo $"""
Usage: $0 [-v] [-F] [-B | -N time ] { check | restore | [-f] relabel | verify } [[dir/file] ... ] Usage: $0 [-v] [-F] { check | restore | [-f] relabel | verify } dir/file ...
or
Usage: $0 [-v] [-F] [-B | -N time ] { check | restore | [-f] relabel | verify }
or or
Usage: $0 [-v] [-F] -R rpmpackage[,rpmpackage...] { check | restore | verify } Usage: $0 [-v] [-F] -R rpmpackage[,rpmpackage...] { check | restore | verify }
or or
@ -319,39 +332,52 @@ Usage: $0 [-F] [-B] onboot
""" """
} }
if [ $# = 0 ]; then if [ $# -eq 0 ]; then
usage usage
exit 1 exit 1
fi fi
set_restore_mode() {
if [ "$RESTORE_MODE" != DEFAULT ]; then
# can't specify two different modes
usage
exit 1
fi
RESTORE_MODE="$1"
}
# See how we were called. # See how we were called.
while getopts "N:BC:FfR:l:v" i; do while getopts "N:BC:FfR:l:v" i; do
case "$i" in case "$i" in
B) B)
BOOTTIME=`/bin/who -b | awk '{print $3}'` BOOTTIME=`/bin/who -b | awk '{print $3}'`
set_restore_mode BOOTTIME
;; ;;
f) N)
fullFlag=1 BOOTTIME=$OPTARG
;; set_restore_mode BOOTTIME
v)
VERBOSE="-v"
;; ;;
R) R)
RPMFILES=$OPTARG RPMFILES=$OPTARG
set_restore_mode RPMFILES
;;
C)
PREFC=$OPTARG
set_restore_mode PREFC
;;
v)
VERBOSE="-v"
;; ;;
l) l)
# Old scripts use obsolete option `-l logfile` # Old scripts use obsolete option `-l logfile`
echo "Redirecting output to $OPTARG" echo "Redirecting output to $OPTARG"
exec >>"$OPTARG" 2>&1 exec >>"$OPTARG" 2>&1
;; ;;
C)
PREFC=$OPTARG
;;
F) F)
FORCEFLAG="-F" FORCEFLAG="-F"
;; ;;
N) f)
BOOTTIME=$OPTARG fullFlag=1
;; ;;
*) *)
usage usage
@ -362,34 +388,24 @@ done
shift $(( OPTIND - 1 )) shift $(( OPTIND - 1 ))
# Check for the command # Check for the command
command="$1" if [ $# -eq 0 ]; then
if [ -z "$command" ]; then
usage usage
exit 1 exit 1
fi fi
command="$1"
# Move out command from arguments # Move out command from arguments
shift shift
# if [ $# -gt 0 ]; then
# check if they specified both RPMFILES and FILEPATHs set_restore_mode FILEPATH
# while [ $# -gt 0 ]; do
FILEPATH="$1"
if [ ! -z "$RPMFILES" ]; then process "$command" || exit $?
if [ $# -gt 0 ]; then shift
usage done
exit 1
fi
process "$command"
else else
if [ -z "$1" ]; then process "$command"
process "$command"
else
while [ -n "$1" ]; do
FILEPATH="$1"
process "$command" || exit $?
shift
done
fi
fi fi
exit $? exit $?

View File

@ -5,8 +5,11 @@ fixfiles \- fix file SELinux security contexts.
.SH "SYNOPSIS" .SH "SYNOPSIS"
.na .na
.B fixfiles .B fixfiles
.I [\-v] [\-F] [\-B | \-N time ] { check | restore | [\-f] relabel | verify } [[dir/file] ... ] .I [\-v] [\-F] { check | restore | [\-f] relabel | verify } dir/file ...
.B fixfiles
.I [\-v] [\-F] [\-B | \-N time ] { check | restore | [\-f] relabel | verify }
.B fixfiles .B fixfiles
.I [\-v] [\-F] \-R rpmpackagename[,rpmpackagename...] { check | restore | verify } .I [\-v] [\-F] \-R rpmpackagename[,rpmpackagename...] { check | restore | verify }