267 lines
6.8 KiB
Bash
Executable File
267 lines
6.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# fixfiles
|
|
#
|
|
# Script to restore labels on a SELinux box
|
|
#
|
|
# Copyright (C) 2004-2009 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
|
|
|
|
#
|
|
# Set global Variables
|
|
#
|
|
fullFlag=0
|
|
FORCEFLAG=""
|
|
DIRS=""
|
|
RPMILES=""
|
|
OUTFILES=""
|
|
LOGFILE=`tty`
|
|
if [ $? != 0 ]; then
|
|
LOGFILE="/dev/null"
|
|
fi
|
|
SYSLOGFLAG="-l"
|
|
LOGGER=/usr/sbin/logger
|
|
SETFILES=/sbin/setfiles
|
|
RESTORECON=/sbin/restorecon
|
|
FILESYSTEMSRW=`mount | grep -v "context=" | egrep -v '\((|.*,)bind(,.*|)\)' | awk '/(ext[234]| ext4dev | gfs2 | xfs | jfs | btrfs ).*\(rw/{print $3}';`
|
|
FILESYSTEMSRO=`mount | grep -v "context=" | egrep -v '\((|.*,)bind(,.*|)\)' | awk '/(ext[234]| ext4dev | gfs2 | xfs | jfs | btrfs ).*\(ro/{print $3}';`
|
|
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
|
|
}
|
|
#
|
|
# 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' | \
|
|
# 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 | \
|
|
while read pattern ; do sh -c "find $pattern \
|
|
! \( -fstype ext2 -o -fstype ext3 -o -fstype ext4 -o -fstype ext4dev -o -fstype gfs2 -o -fstype jfs -o -fstype xfs -o -fstype btrfs \) -prune -o \
|
|
\( -wholename /home -o -wholename /root -o -wholename /tmp -wholename /dev \) -prune -o -print0"; \
|
|
done 2> /dev/null | \
|
|
${RESTORECON} $* -0 -f -
|
|
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 () {
|
|
if [ ! -z "$PREFC" ]; then
|
|
diff_filecontext $*
|
|
exit $?
|
|
fi
|
|
if [ ! -z "$RPMFILES" ]; then
|
|
for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do
|
|
rpmlist $i | ${RESTORECON} ${OUTFILES} ${FORCEFLAG} $* -R -i -f - 2>&1 >> $LOGFILE
|
|
done
|
|
exit $?
|
|
fi
|
|
if [ ! -z "$FILEPATH" ]; then
|
|
if [ -x /usr/bin/find ]; then
|
|
/usr/bin/find "$FILEPATH" \
|
|
! \( -fstype ext2 -o -fstype ext3 -o -fstype ext4 -o -fstype ext4dev -o -fstype gfs2 -o -fstype jfs -o -fstype xfs -o -fstype btrfs \) -prune -o -print0 | \
|
|
${RESTORECON} ${OUTFILES} ${FORCEFLAG} $* -0 -f - 2>&1 >> $LOGFILE
|
|
else
|
|
${RESTORECON} ${OUTFILES} ${FORCEFLAG} -R $* $FILEPATH 2>&1 >> $LOGFILE
|
|
fi
|
|
return
|
|
fi
|
|
LogReadOnly
|
|
${SETFILES} -q ${OUTFILES} ${SYSLOGFLAG} ${FORCEFLAG} $* ${FC} ${FILESYSTEMSRW} 2>&1 >> $LOGFILE
|
|
rm -rf /tmp/gconfd-* /tmp/pulse-* /tmp/orbit-*
|
|
find /tmp \( -context "*:file_t*" -o -context "*:unlabeled_t*" \) -exec chcon -t tmp_t {} \;
|
|
find /var/tmp \( -context "*:file_t*" -o -context "*:unlabeled_t*" \) -exec chcon -t tmp_t {} \;
|
|
exit $?
|
|
}
|
|
|
|
fullrelabel() {
|
|
logit "Cleaning out /tmp"
|
|
find /tmp/ -mindepth 1 -print0 | xargs -0 /bin/rm -f
|
|
LogReadOnly
|
|
restore
|
|
}
|
|
|
|
relabel() {
|
|
if [ ! -z "$RPMFILES" ]; then
|
|
restore
|
|
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
|
|
fi
|
|
}
|
|
|
|
process() {
|
|
#
|
|
# Make sure they specified one of the three valid commands
|
|
#
|
|
case "$1" in
|
|
restore) restore -p ;;
|
|
check) restore -n -v;;
|
|
verify) restore -n -o -;;
|
|
relabel) relabel;;
|
|
onboot)
|
|
touch /.autorelabel
|
|
echo "System will relabel on next boot"
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
esac
|
|
}
|
|
usage() {
|
|
echo $"Usage: $0 [-l logfile ] [-o outputfile ] { check | restore|[-F] relabel } [[dir] ... ] "
|
|
echo or
|
|
echo $"Usage: $0 -R rpmpackage[,rpmpackage...] -C PREVIOUS_FILECONTEXT [-l logfile ] [-o outputfile ] { check | restore }"
|
|
echo $"Usage: $0 onboot"
|
|
}
|
|
|
|
if [ $# = 0 ]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
# See how we were called.
|
|
while getopts "C:Ffo:R:l:" i; do
|
|
case "$i" in
|
|
f)
|
|
fullFlag=1
|
|
;;
|
|
R)
|
|
RPMFILES=$OPTARG
|
|
;;
|
|
o)
|
|
OUTFILES=$OPTARG
|
|
;;
|
|
l)
|
|
LOGFILE=$OPTARG
|
|
;;
|
|
C)
|
|
PREFC=$OPTARG
|
|
;;
|
|
F)
|
|
FORCEFLAG="-F"
|
|
;;
|
|
*)
|
|
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 $?
|