selinux/policycoreutils/scripts/fixfiles
Alan Jenkins aa62e3665c policycoreutils: fixfiles: remove (broken) redundant code
setfiles is now run with $exclude_dirs.
We shouldn't need to patch the file contexts as well.

This is fortunate, since the file context patching code was broken
(by the same commit which introduced the redundancy).  It takes the
list of directories to exclude from $tempdirs, but $tempdirs is
never set.

Also messages about skipping directories were printed twice.  Firstly when
exclude_dirs is generated, and secondly in the file context patching code.

Also TEMPFCFILE was only removed in one path out of several.
2017-05-05 13:27:02 -04:00

399 lines
10 KiB
Bash
Executable File

#!/bin/bash
# fixfiles
#
# Script to restore labels on a SELinux box
#
# Copyright (C) 2004-2013 Red Hat, Inc.
# Authors: Dan Walsh <dwalsh@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# 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 is less than 2.6.30 and 0 if they are the same.
#
function useseclabel {
VER=`uname -r`
SUP=2.6.30
expr '(' "$VER" : '\([^.]*\)' ')' '-' '(' "$SUP" : '\([^.]*\)' ')' '|' \
'(' "$VER.0" : '[^.]*[.]\([^.]*\)' ')' '-' '(' "$SUP.0" : '[^.]*[.]\([^.]*\)' ')' '|' \
'(' "$VER.0.0" : '[^.]*[.][^.]*[.]\([^.]*\)' ')' '-' '(' "$SUP.0.0" : '[^.]*[.][^.]*[.]\([^.]*\)' ')'
}
#
# Get all mount points that support labeling. Use the 'seclabel' field if it
# is available. Else fall back to known fs types which likely support xattrs
# and we know were not context mounted.
#
get_all_labeled_mounts() {
FS="`cat /proc/self/mounts | sort | uniq | awk '{print $2}'`"
for i in $FS; do
if [ `useseclabel` -ge 0 ]
then
grep " $i " /proc/self/mounts | awk '{print $4}' | egrep --silent '(^|,)seclabel(,|$)' && echo $i
else
grep " $i " /proc/self/mounts | grep -v "context=" | egrep --silent '(ext[234]| ext4dev | gfs2 | xfs | jfs | btrfs )' && echo $i
fi
done
}
get_rw_labeled_mounts() {
FS=`get_all_labeled_mounts | sort | uniq`
for i in $FS; do
grep " $i " /proc/self/mounts | awk '{print $4}' | egrep --silent '(^|,)rw(,|$)' && echo $i
done
}
get_ro_labeled_mounts() {
FS=`get_all_labeled_mounts | sort | uniq`
for i in $FS; do
grep " $i " /proc/self/mounts | awk '{print $4}' | egrep --silent '(^|,)ro(,|$)' && echo $i
done
}
#
# Get the default label returned from the kernel for a file with a lable the
# kernel does not understand
#
get_undefined_type() {
SELINUXMNT=`grep selinuxfs /proc/self/mountinfo | head -1 | awk '{ print $5 }'`
cat ${SELINUXMNT}/initial_contexts/unlabeled | secon -t
}
#
# Get the default label for a file without a label
#
get_unlabeled_type() {
SELINUXMNT=`grep selinuxfs /proc/self/mountinfo | head -1 | awk '{ print $5 }'`
cat $SELINUXMNT/initial_contexts/file | secon -t
}
exclude_dirs_from_relabelling() {
exclude_from_relabelling=
if [ -e /etc/selinux/fixfiles_exclude_dirs ]
then
while read i
do
# skip blank line and comment
# skip not absolute path
# skip not directory
[ -z "${i}" ] && continue
[[ "${i}" =~ "^[[:blank:]]*#" ]] && continue
[[ ! "${i}" =~ ^/.* ]] && continue
[[ ! -d "${i}" ]] && continue
exclude_from_relabelling="$exclude_from_relabelling -e $i"
logit "skipping the directory $i"
done < /etc/selinux/fixfiles_exclude_dirs
fi
echo "$exclude_from_relabelling"
}
exclude_dirs() {
exclude=
for i in /sys /proc /dev /run /mnt /var/tmp /var/lib/BackupPC /home /tmp /dev; do
[ -e $i ] && exclude="$exclude -e $i";
done
exclude="$exclude `exclude_dirs_from_relabelling`"
echo "$exclude"
}
#
# Set global Variables
#
fullFlag=0
BOOTTIME=""
VERBOSE="-p"
FORCEFLAG=""
DIRS=""
RPMILES=""
LOGFILE=`tty`
if [ $? != 0 ]; then
LOGFILE="/dev/null"
fi
LOGGER=/usr/sbin/logger
SETFILES=/sbin/setfiles
RESTORECON=/sbin/restorecon
FILESYSTEMSRW=`get_rw_labeled_mounts`
FILESYSTEMSRO=`get_ro_labeled_mounts`
FILESYSTEMS="$FILESYSTEMSRW $FILESYSTEMSRO"
SELINUXTYPE="targeted"
if [ -e /etc/selinux/config ]; then
. /etc/selinux/config
FC=/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts
else
FC=/etc/security/selinux/file_contexts
fi
#
# Log to either syslog or a LOGFILE
#
logit () {
if [ -n $LOGFILE ]; then
echo $1 >> $LOGFILE
fi
}
#
# Find files newer then the passed in date and fix the label
#
newer() {
DATE=$1
shift
for m in `echo $FILESYSTEMSRW`; do
find $m -mount -newermt $DATE -print0 2>/dev/null | ${RESTORECON} ${FORCEFLAG} ${VERBOSE} $* -i -0 -f -
done;
}
#
# Compare PREVious File Context to currently installed File Context and
# run restorecon on all files affected by the differences.
#
diff_filecontext() {
if [ -f ${PREFC} -a -x /usr/bin/diff ]; then
TEMPFILE=`mktemp ${FC}.XXXXXXXXXX`
test -z "$TEMPFILE" && exit
PREFCTEMPFILE=`mktemp ${PREFC}.XXXXXXXXXX`
sed -r -e 's,:s0, ,g' $PREFC | sort -u > ${PREFCTEMPFILE}
sed -r -e 's,:s0, ,g' $FC | sort -u | \
/usr/bin/diff -b ${PREFCTEMPFILE} - | \
grep '^[<>]'|cut -c3-| grep ^/ | \
egrep -v '(^/home|^/root|^/tmp|^/dev)' |\
sed -r -e 's,[[:blank:]].*,,g' \
-e 's|\(([/[:alnum:]]+)\)\?|{\1,}|g' \
-e 's|([/[:alnum:]])\?|{\1,}|g' \
-e 's|\?.*|*|g' \
-e 's|\{.*|*|g' \
-e 's|\(.*|*|g' \
-e 's|\[.*|*|g' \
-e 's|\.\*.*|*|g' \
-e 's|\.\+.*|*|g' | \
# These two sorts need to be separate commands \
sort -u | \
sort -d | \
while read pattern ; \
do if ! echo "$pattern" | grep -q -f ${TEMPFILE} 2>/dev/null; then \
echo "$pattern"; \
case "$pattern" in *"*") \
echo "$pattern" | sed -e 's,^,^,' -e 's,\*$,,g' >> ${TEMPFILE};;
esac; \
fi; \
done | \
${RESTORECON} ${VERBOSE} -i -f - -R $* `exclude_dirs`; \
rm -f ${TEMPFILE} ${PREFCTEMPFILE}
fi
}
#
# Log all Read Only file systems
#
LogReadOnly() {
if [ ! -z "$FILESYSTEMSRO" ]; then
logit "Warning: Skipping the following R/O filesystems:"
logit "$FILESYSTEMSRO"
fi
}
rpmlist() {
rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
[ ${PIPESTATUS[0]} != 0 ] && echo "$1 not found" >/dev/stderr
}
#
# restore
# if called with -n will only check file context
#
restore () {
OPTION=$1
shift
if [ ! -z "$PREFC" ]; then
diff_filecontext $*
exit $?
fi
if [ ! -z "$BOOTTIME" ]; then
newer $BOOTTIME $*
exit $?
fi
[ -x /usr/sbin/genhomedircon ] && /usr/sbin/genhomedircon
LogReadOnly
#
exclude_dirs="`exclude_dirs_from_relabelling $OPTION`"
if [ ! -z "$RPMFILES" ]; then
for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do
rpmlist $i | ${RESTORECON} $exclude_dirs ${FORCEFLAG} ${VERBOSE} $* -R -i -f - >>$LOGFILE 2>&1
done
exit $?
fi
if [ ! -z "$FILEPATH" ]; then
${RESTORECON} $exclude_dirs ${FORCEFLAG} ${VERBOSE} -R $* -- "$FILEPATH" >>$LOGFILE 2>&1
return
fi
if [ -n "${FILESYSTEMSRW}" ]; then
echo "${OPTION}ing `echo ${FILESYSTEMSRW}`"
${SETFILES} ${VERBOSE} $exclude_dirs -q ${FORCEFLAG} $* ${FC} ${FILESYSTEMSRW} >>$LOGFILE 2>&1
else
echo >&2 "fixfiles: No suitable file systems found"
fi
if [ ${OPTION} != "Relabel" ]; then
return
fi
echo "Cleaning up labels on /tmp"
rm -rf /tmp/gconfd-* /tmp/pulse-* /tmp/orbit-*
UNDEFINED=`get_undefined_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}*" \) -exec chcon --reference /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 {} \;
[ ! -e /var/lib/debug ] || find /var/lib/debug \( -context "*:${UNLABELED}*" -o -context "*:${UNDEFINED}*" \) -exec chcon --reference /lib {} \;
exit 0
}
fullrelabel() {
logit "Cleaning out /tmp"
find /tmp/ -mindepth 1 -delete
LogReadOnly
restore Relabel
}
relabel() {
if [ ! -z "$RPMFILES" ]; then
restore Relabel
fi
if [ $fullFlag == 1 ]; then
fullrelabel
fi
echo -n "
Files in the /tmp directory may be labeled incorrectly, this command
can remove all files in /tmp. If you choose to remove files from /tmp,
a reboot will be required after completion.
Do you wish to clean out the /tmp directory [N]? "
read answer
if [ "$answer" = y -o "$answer" = Y ]; then
fullrelabel
else
restore Relabel
fi
}
process() {
#
# Make sure they specified one of the three valid commands
#
case "$1" in
restore) restore Relabel;;
check) VERBOSE="-v"; restore Check -n;;
verify) restore Verify -n;;
relabel) relabel;;
onboot)
> /.autorelabel
[ -z "$FORCEFLAG" ] || echo -n "$FORCEFLAG " >> /.autorelabel
[ -z "$BOOTTIME" ] || echo -N $BOOTTIME >> /.autorelabel
# Force full relabel if / does not have a label on it
getfilecon / > /dev/null 2>&1 || echo -F >/.autorelabel
echo "System will relabel on next boot"
;;
*)
usage
exit 1
esac
}
usage() {
echo $"""
Usage: $0 [-v] [-F] [-N time ] [-l logfile ] { check | restore| [-f] relabel | verify } [[dir/file] ... ]
or
Usage: $0 [-v] [-F] -R rpmpackage[,rpmpackage...] [-l logfile ] { check | restore | verify }
or
Usage: $0 [-v] [-F] -C PREVIOUS_FILECONTEXT { check | restore | verify }
or
Usage: $0 [-F] [-B] onboot
"""
}
if [ $# = 0 ]; then
usage
exit 1
fi
# See how we were called.
while getopts "N:BC:FfR:l:v" i; do
case "$i" in
B)
BOOTTIME=`/bin/who -b | awk '{print $3}'`
;;
f)
fullFlag=1
;;
v)
VERBOSE="-v"
;;
R)
RPMFILES=$OPTARG
;;
l)
LOGFILE=$OPTARG
;;
C)
PREFC=$OPTARG
;;
F)
FORCEFLAG="-F"
;;
N)
BOOTTIME=$OPTARG
;;
*)
usage
exit 1
esac
done
# Move out processed options from arguments
shift $(( OPTIND - 1 ))
# Check for the command
command="$1"
if [ -z "$command" ]; then
usage
fi
# Move out command from arguments
shift
#
# check if they specified both DIRS and RPMFILES
#
if [ ! -z "$RPMFILES" ]; then
process "$command"
if [ $# -gt 0 ]; then
usage
fi
else
if [ -z "$1" ]; then
process "$command"
else
while [ -n "$1" ]; do
FILEPATH="$1"
process "$command"
shift
done
fi
fi
exit $?