apparmor/parser/rc.apparmor.functions
Steve Beattie 6123467433 skip files suffixed with .dpkg-old, based on a patch from Mathias Gug
<mathiaz@ubuntu.com> [Message-ID: <20070813201254.GD11381@mathias.mathiaz.net>]
Added comments to both file-skipping locations referencing the other
location that needs to be modified.

(The ideal solution would be for this information to be stored in one
commonly referenced location, configurable by distributors and
administratrors.)
2007-08-14 19:19:59 +00:00

467 lines
12 KiB
Bash

#!/bin/sh
#
# $Id$
#
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
# NOVELL (All rights reserved)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# 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, contact Novell, Inc.
# ----------------------------------------------------------------------
# rc.apparmor.functions by Steve Beattie
#
# NOTE: rc.apparmor initscripts that source this file need to implement
# the following set of functions:
# aa_action
# aa_log_success_msg
# aa_log_warning_msg
# aa_log_failure_msg
# aa_log_skipped_msg
# Some nice defines that we use
CONFIG_DIR=/etc/apparmor
MODULE=apparmor
OLD_MODULE=subdomain
if [ -f "${CONFIG_DIR}/${MODULE}.conf" ] ; then
APPARMOR_CONF="${CONFIG_DIR}/${MODULE}.conf"
elif [ -f "${CONFIG_DIR}/${OLD_MODULE}.conf" ] ; then
APPARMOR_CONF="${CONFIG_DIR}/${OLD_MODULE}.conf"
elif [ -f "/etc/immunix/subdomain.conf" ] ; then
aa_log_warning_msg "/etc/immunix/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
APPARMOR_CONF="/etc/immunix/subdomain.conf"
elif [ -f "/etc/subdomain.conf" ] ; then
aa_log_warning_msg "/etc/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
APPARMOR_CONF="/etc/subdomain.conf"
else
aa_log_warning_msg "Unable to find config file in ${CONFIG_DIR}, installation problem?"
fi
# Read configuration options from /etc/subdomain.conf, default is to
# warn if subdomain won't load.
SUBDOMAIN_MODULE_PANIC="warn"
SUBDOMAIN_ENABLE_OWLSM="no"
APPARMOR_ENABLE_AAEVENTD="no"
if [ -f "${APPARMOR_CONF}" ] ; then
#parse the conf file to see what we should do
. "${APPARMOR_CONF}"
fi
if [ -f /sbin/apparmor_parser ] ; then
PARSER=/sbin/apparmor_parser
elif [ -f /sbin/subdomain_parser -o -h /sbin/subdomain_parser ] ; then
PARSER=/sbin/subdomain_parser
else
aa_log_failure_msg "Unable to find apparmor_parser, installation problem?"
exit 1
fi
# SUBDOMAIN_DIR and APPARMOR_DIR might be defined in subdomain.conf|apparmor.conf
if [ -d "${APPAMROR_DIR}" ] ; then
PROFILE_DIR=${APPARMOR_DIR}
elif [ -d "${SUBDOMAIN_DIR}" ] ; then
PROFILE_DIR=${SUBDOMAIN_DIR}
elif [ -d /etc/apparmor.d ] ; then
PROFILE_DIR=/etc/apparmor.d
elif [ -d /etc/subdomain.d ] ; then
PROFILE_DIR=/etc/subdomain.d
fi
ABSTRACTIONS="-I${PROFILE_DIR}"
AA_EV_BIN=/usr/sbin/aa-eventd
AA_EV_PIDFILE=/var/run/aa-eventd.pid
AA_STATUS=/usr/sbin/apparmor_status
SD_EV_BIN=/usr/sbin/sd-event-dispatch.pl
SD_EV_PIDFILE=/var/run/sd-event-dispatch.init.pid
SD_STATUS=/usr/sbin/subdomain_status
SECURITYFS=/sys/kernel/security
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
if [ -d "/var/lib/${MODULE}" ] ; then
APPARMOR_TMPDIR="/var/lib/${MODULE}"
elif [ -d "/var/lib/${OLD_MODULE}" ] ; then
APPARMOR_TMPDIR="/var/lib/${OLD_MODULE}"
else
APPARMOR_TMPDIR="/tmp"
fi
# keep exit status from parser during profile load. 0 is good, 1 is bad
STATUS=0
# This set of patterns to skip needs to be kept in sync with
# SubDomain.pm::isSkippableFile()
skip_profile() {
local profile=$1
if [ "${profile%.rpmnew}" != "${profile}" -o \
"${profile%.rpmsave}" != "${profile}" -o \
"${profile%.dpkg-new}" != "${profile}" -o \
"${profile%.dpkg-old}" != "${profile}" -o \
"${profile%\~}" != "${profile}" ] ; then
return 0
fi
return 1
}
parse_profiles() {
# get parser arg
case "$1" in
load)
PARSER_ARGS="--add"
PARSER_MSG="Loading AppArmor profiles "
;;
reload)
PARSER_ARGS="--replace"
PARSER_MSG="Reloading AppArmor profiles "
;;
*)
exit 1
;;
esac
echo -n "$PARSER_MSG"
# run the parser on all of the apparmor profiles
if [ ! -f "$PARSER" ]; then
aa_log_failure_msg "- AppArmor parser not found"
exit 1
fi
if [ ! -d "$PROFILE_DIR" ]; then
aa_log_skipped_msg "- Profile directory not found\nNo AppArmor policy loaded."
return 1
fi
if [ -z "$(ls $PROFILE_DIR/)" ]; then
aa_log_skipped_msg "- No profiles found\nNo AppArmor policy loaded."
return 1
fi
for profile in $PROFILE_DIR/*; do
if skip_profile "${profile}" ; then
echo " Skipping profile $profile"
logger -t "AppArmor(init)" -p daemon.warn "Skipping profile $profile"
STATUS=2
elif [ -f "${profile}" ] ; then
$PARSER $ABSTRACTIONS $PARSER_ARGS "$profile" > /dev/null
if [ $? -ne 0 ]; then
echo " Profile $profile failed to load"
STATUS=1
fi
fi
done
if [ $STATUS -eq 0 ]; then
aa_log_success_msg
elif [ $STATUS -eq 2 ]; then
aa_log_warning_msg
else
aa_log_failure_msg
exit $STATUS
fi
}
profiles_names_list() {
# run the parser on all of the apparmor profiles
TMPFILE=$1
if [ ! -f "$PARSER" ]; then
aa_log_failure_msg "- AppArmor parser not found"
exit 1
fi
if [ ! -d "$PROFILE_DIR" ]; then
aa_log_failure_msg "- Profile directory not found"
exit 1
fi
for profile in $PROFILE_DIR/*; do
if ! skip_profile "${profile}" && [ -f "${profile}" ] ; then
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" | grep -v '\^')
if [ $? -eq 0 ]; then
echo "$LIST_ADD" >>$TMPFILE
fi
fi
done
}
failstop_system() {
level=$(runlevel | cut -d" " -f2)
if [ $level -ne "1" ] ; then
aa_log_failure_msg "- could not start AppArmor. Changing to runlevel 1"
telinit 1;
return -1;
fi
aa_log_failure_msg "- could not start AppArmor."
return -1
}
module_panic() {
# the module failed to load, determine what action should be taken
case "$SUBDOMAIN_MODULE_PANIC" in
"warn"|"WARN")
return 1 ;;
"panic"|"PANIC") failstop_system
rc=$?
return $rc ;;
*) aa_log_failure_msg "- invalid AppArmor module fail option"
return -1 ;;
esac
}
is_apparmor_loaded() {
if ! is_securityfs_mounted ; then
mount_securityfs
fi
mount_subdomainfs
if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then
SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
return 0
fi
if [ -f "${SECURITYFS}/${OLD_MODULE}/profiles" ]; then
SFS_MOUNTPOINT="${SECURITYFS}/${OLD_MODULE}"
return 0
fi
if [ -f "${SUBDOMAINFS_MOUNTPOINT}/profiles" ]; then
SFS_MOUNTPOINT=${SUBDOMAINFS_MOUNTPOINT}
return 0
fi
# check for subdomainfs version of module
grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules
return $?
}
is_securityfs_mounted() {
grep -q securityfs /proc/filesystems && grep -q securityfs /proc/mounts
return $?
}
mount_securityfs() {
if grep -q securityfs /proc/filesystems ; then
aa_action "Mounting securityfs on ${SECURITYFS}" \
mount -t securityfs securityfs "${SECURITYFS}"
return $?
fi
return 0
}
mount_subdomainfs() {
# for backwords compatibility
if grep -q subdomainfs /proc/filesystems && \
! grep -q subdomainfs /proc/mounts && \
[ -n "${SUBDOMAINFS_MOUNTPOINT}" ]; then
aa_action "Mounting subdomainfs on ${SUBDOMAINFS_MOUNTPOINT}" \
mount "${SUBDOMAINFS_MOUNTPOINT}"
return $?
fi
return 0
}
unmount_subdomainfs() {
SUBDOMAINFS=$(grep subdomainfs /proc/mounts | cut -d" " -f2 2> /dev/null)
if [ -n "${SUBDOMAINFS}" ]; then
aa_action "Unmounting subdomainfs" umount ${SUBDOMAINFS}
fi
}
load_module() {
local rc=0
if modinfo -F filename apparmor > /dev/null 2>&1 ; then
MODULE=apparmor
elif modinfo -F filename ${OLD_MODULE} > /dev/null 2>&1 ; then
MODULE=${OLD_MODULE}
fi
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
aa_action "Loading AppArmor module" /sbin/modprobe -q $MODULE $1
rc=$?
if [ $rc -ne 0 ] ; then
module_panic
rc=$?
if [ $rc -ne 0 ] ; then
exit $rc
fi
fi
fi
if ! is_apparmor_loaded ; then
return 1
fi
return $rc
}
apparmor_start() {
if ! is_apparmor_loaded ; then
load_module
rc=$?
if [ $rc -ne 0 ] ; then
return $rc
fi
fi
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
return 1
fi
configure_owlsm
if [ $(wc -l "$SFS_MOUNTPOINT/profiles" | awk '{print $1}') -eq 0 ] ; then
parse_profiles load
else
aa_log_skipped_msg "Loading AppArmor profiles - AppArmor already loaded with profiles."
fi
}
remove_profiles() {
# removing profiles as we directly read from subdomainfs
# doesn't work, since we are removing entries which screws up
# our position. Lets hope there are never enough profiles to
# overflow the variable
if ! is_apparmor_loaded ; then
aa_log_failure_msg "- failed, is AppArmor loaded?"
return 1
fi
if [ ! -w "$SFS_MOUNTPOINT/.remove" ] ; then
aa_log_failure_msg "- failed, Do you have the correct privileges?"
return 1
fi
if [ ! -x "${PARSER}" ] ; then
aa_log_failure_msg "- failed, unable to execute AppArmor parser"
return 1
fi
retval=0
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | while read profile ; do
echo "\"$profile\" { }" | $PARSER -R >/dev/null
rc=$?
if [ ${rc} -ne 0 ] ; then
retval=${rc}
fi
done
if [ ${retval} -eq 0 ] ; then
aa_log_success_msg
else
aa_log_failure_msg
fi
return ${retval}
}
apparmor_stop() {
echo -n "Unloading AppArmor profiles "
remove_profiles
return $?
}
apparmor_kill() {
if ! is_apparmor_loaded ; then
aa_log_failure_msg "Killing AppArmor module - failed, AppArmor is not loaded."
return 1
fi
unmount_subdomainfs
if grep -qE "^apparmor[[:space:]]" /proc/modules ; then
MODULE=apparmor
elif grep -qE "^subdomain[[:space:]]" /proc/modules ; then
MODULE=subdomain
else
aa_log_failure_msg "Killing AppArmor module - failed, AppArmor is builtin"
return 1
fi
aa_action "Unloading AppArmor modules" /sbin/modprobe -qr $MODULE
return $?
}
__apparmor_restart() {
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
return 4
fi
configure_owlsm
parse_profiles reload
PNAMES_LIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
profiles_names_list ${PNAMES_LIST}
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort >"$MODULE_PLIST"
sort "$PNAMES_LIST" | comm -2 -3 "$MODULE_PLIST" - | while read profile ; do
echo "\"$profile\" {}" | $PARSER -R >/dev/null
done
rm "$MODULE_PLIST"
rm "$PNAMES_LIST"
return 0
}
apparmor_restart() {
if ! is_apparmor_loaded ; then
apparmor_start
rc=$?
return $rc
fi
__apparmor_restart
return $?
}
apparmor_try_restart() {
if ! is_apparmor_loaded ; then
return 0
fi
__apparmor_restart
return $?
}
configure_owlsm () {
if [ "${SUBDOMAIN_ENABLE_OWLSM}" = "yes" -a -f ${SFS_MOUNTPOINT}/control/owlsm ] ; then
# Sigh, the "sh -c" is necessary for the SuSE aa_action
# and it can't be abstracted out as a seperate function, as
# that breaks under RedHat's action, which needs a
# binary to invoke.
aa_action "Enabling OWLSM extension" sh -c "echo -n \"1\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
elif [ -f "${SFS_MOUNTPOINT}/control/owlsm" ] ; then
aa_action "Disabling OWLSM extension" sh -c "echo -n \"0\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
fi
}
apparmor_status () {
if test -x ${AA_STATUS} ; then
${AA_STATUS} --verbose
return $?
fi
if test -x ${SD_STATUS} ; then
${SD_STATUS} --verbose
return $?
fi
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
echo "AppArmor is not loaded."
rc=1
else
echo "AppArmor is enabled,"
rc=0
fi
echo "Install the apparmor-utils package to receive more detailed"
echo "status information here (or examine ${SFS_MOUNTPOINT} directly)."
return $rc
}