mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-05 17:01:00 +01:00

<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.)
467 lines
12 KiB
Bash
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
|
|
}
|