mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-05 00:41:03 +01:00
396 lines
9.3 KiB
Bash
396 lines
9.3 KiB
Bash
#!/bin/sh
|
|
# ----------------------------------------------------------------------
|
|
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
|
# Copyright (c) 2009-2012 Canonical Ltd. (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_action_start
|
|
# aa_log_action_end
|
|
# aa_log_success_msg
|
|
# aa_log_warning_msg
|
|
# aa_log_failure_msg
|
|
# aa_log_skipped_msg
|
|
# aa_log_daemon_msg
|
|
# aa_log_end_msg
|
|
|
|
# Some nice defines that we use
|
|
|
|
CONFIG_DIR=/etc/apparmor
|
|
MODULE=apparmor
|
|
if [ -f "${CONFIG_DIR}/${MODULE}.conf" ] ; then
|
|
APPARMOR_CONF="${CONFIG_DIR}/${MODULE}.conf"
|
|
else
|
|
aa_log_warning_msg "Unable to find config file in ${CONFIG_DIR}, installation problem?"
|
|
fi
|
|
|
|
if [ -f "${APPARMOR_CONF}" ] ; then
|
|
#parse the conf file to see what we should do
|
|
. "${APPARMOR_CONF}"
|
|
fi
|
|
|
|
PARSER=/sbin/apparmor_parser
|
|
|
|
# APPARMOR_DIR might be defined in apparmor.conf
|
|
if [ -d "${APPARMOR_DIR}" ] ; then
|
|
PROFILE_DIR=${APPARMOR_DIR}
|
|
elif [ -d /etc/apparmor.d ] ; then
|
|
PROFILE_DIR=/etc/apparmor.d
|
|
fi
|
|
ABSTRACTIONS="-I${PROFILE_DIR}"
|
|
AA_STATUS=/usr/sbin/aa-status
|
|
SECURITYFS=/sys/kernel/security
|
|
|
|
# keep exit status from parser during profile load. 0 is good, 1 is bad
|
|
STATUS=0
|
|
|
|
# Test if the apparmor "module" is present.
|
|
is_apparmor_present() {
|
|
local modules=$1
|
|
shift
|
|
|
|
while [ $# -gt 0 ] ; do
|
|
modules="$modules|$1"
|
|
shift
|
|
done
|
|
|
|
[ $? -ne 0 -a -d /sys/module/apparmor ]
|
|
|
|
return $?
|
|
}
|
|
|
|
# This set of patterns to skip needs to be kept in sync with
|
|
# AppArmor.pm::isSkippableFile()
|
|
# returns 0 if profile should NOT be skipped
|
|
# returns 1 on verbose skip
|
|
# returns 2 on silent skip
|
|
skip_profile() {
|
|
local profile=$1
|
|
if [ "${profile%.rpmnew}" != "${profile}" -o \
|
|
"${profile%.rpmsave}" != "${profile}" -o \
|
|
-e "${PROFILE_DIR}/disable/`basename ${profile}`" -o \
|
|
"${profile%\~}" != "${profile}" ] ; then
|
|
return 1
|
|
fi
|
|
# Silently ignore the dpkg, pacman, and xbps files
|
|
if [ "${profile%.dpkg-new}" != "${profile}" -o \
|
|
"${profile%.dpkg-old}" != "${profile}" -o \
|
|
"${profile%.dpkg-dist}" != "${profile}" -o \
|
|
"${profile%.dpkg-bak}" != "${profile}" -o \
|
|
"${profile%.dpkg-remove}" != "${profile}" -o \
|
|
"${profile%.pacsave}" != "${profile}" -o \
|
|
"${profile%.pacnew}" != "${profile}" ] ; then
|
|
return 2
|
|
fi
|
|
if echo "${profile}" | egrep -q '^.+\.new-[0-9\.]+_[0-9]+$'; then
|
|
return 2
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
force_complain() {
|
|
local profile=$1
|
|
|
|
# if profile not in complain mode
|
|
if ! egrep -q "^/.*[ \t]+flags[ \t]*=[ \t]*\([ \t]*complain[ \t]*\)[ \t]+{" $profile ; then
|
|
local link="${PROFILE_DIR}/force-complain/`basename ${profile}`"
|
|
if [ -e "$link" ] ; then
|
|
aa_log_warning_msg "found $link, forcing complain mode"
|
|
return 0
|
|
fi
|
|
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 "
|
|
;;
|
|
*)
|
|
aa_log_failure_msg "required 'load' or 'reload'"
|
|
exit 1
|
|
;;
|
|
esac
|
|
aa_log_action_start "$PARSER_MSG"
|
|
# run the parser on all of the apparmor profiles
|
|
if [ ! -f "$PARSER" ]; then
|
|
aa_log_failure_msg "AppArmor parser not found"
|
|
aa_log_action_end 1
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -d "$PROFILE_DIR" ]; then
|
|
aa_log_failure_msg "Profile directory not found"
|
|
aa_log_action_end 1
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$(ls $PROFILE_DIR/)" ]; then
|
|
aa_log_failure_msg "No profiles found"
|
|
aa_log_action_end 1
|
|
return 1
|
|
fi
|
|
|
|
for profile in $PROFILE_DIR/*; do
|
|
skip_profile "${profile}"
|
|
skip=$?
|
|
# Ignore skip status == 2 (silent skip)
|
|
if [ "$skip" -eq 1 ] ; then
|
|
aa_log_skipped_msg "$profile"
|
|
logger -t "AppArmor(init)" -p daemon.warn "Skipping profile $profile"
|
|
STATUS=2
|
|
continue
|
|
elif [ "$skip" -ne 0 ]; then
|
|
continue
|
|
fi
|
|
if [ -f "${profile}" ] ; then
|
|
COMPLAIN=""
|
|
if force_complain "${profile}" ; then
|
|
COMPLAIN="-C"
|
|
fi
|
|
$PARSER $ABSTRACTIONS $PARSER_ARGS $COMPLAIN "$profile" > /dev/null
|
|
if [ $? -ne 0 ]; then
|
|
aa_log_failure_msg "$profile failed to load"
|
|
STATUS=1
|
|
fi
|
|
fi
|
|
done
|
|
if [ $STATUS -eq 2 ]; then
|
|
STATUS=0
|
|
fi
|
|
aa_log_action_end "$STATUS"
|
|
return $STATUS
|
|
}
|
|
|
|
profiles_names_list() {
|
|
# 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_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" )
|
|
if [ $? -eq 0 ]; then
|
|
echo "$LIST_ADD"
|
|
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 255;
|
|
fi
|
|
aa_log_failure_msg "- could not start AppArmor."
|
|
return 255
|
|
}
|
|
|
|
is_apparmor_loaded() {
|
|
if ! is_securityfs_mounted ; then
|
|
mount_securityfs
|
|
fi
|
|
|
|
if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then
|
|
SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
|
|
return 0
|
|
fi
|
|
|
|
is_apparmor_present apparmor
|
|
|
|
return $?
|
|
}
|
|
|
|
is_securityfs_mounted() {
|
|
test -d ${SECURITYFS} -a -d /sys/fs/cgroup/systemd || 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
|
|
}
|
|
|
|
apparmor_start() {
|
|
aa_log_daemon_msg "Starting AppArmor"
|
|
if ! is_apparmor_present ; then
|
|
aa_log_failure_msg "Starting AppArmor - failed, To enable AppArmor, ensure your kernel is configured with CONFIG_SECURITY_APPARMOR=y then add 'security=apparmor apparmor=1' to the kernel command line"
|
|
aa_log_end_msg 1
|
|
return 1
|
|
elif ! is_apparmor_loaded ; then
|
|
aa_log_failure_msg "Starting AppArmor - AppArmor control files aren't available under /sys/kernel/security/, please make sure securityfs is mounted."
|
|
aa_log_end_msg 1
|
|
return 1
|
|
fi
|
|
|
|
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
|
|
aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
|
|
aa_log_end_msg 1
|
|
return 1
|
|
fi
|
|
|
|
configure_owlsm
|
|
|
|
# if there is anything in the profiles file don't load
|
|
if ! read line < "$SFS_MOUNTPOINT/profiles"; then
|
|
parse_profiles load
|
|
else
|
|
aa_log_skipped_msg ": already loaded with profiles."
|
|
return 0
|
|
fi
|
|
aa_log_end_msg 0
|
|
return 0
|
|
}
|
|
|
|
remove_profiles() {
|
|
|
|
# removing profiles as we directly read from apparmorfs
|
|
# 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 "AppArmor module is not loaded"
|
|
return 1
|
|
fi
|
|
|
|
if [ ! -w "$SFS_MOUNTPOINT/.remove" ] ; then
|
|
aa_log_failure_msg "Root privileges not available"
|
|
return 1
|
|
fi
|
|
|
|
if [ ! -x "${PARSER}" ] ; then
|
|
aa_log_failure_msg "Unable to execute AppArmor parser"
|
|
return 1
|
|
fi
|
|
|
|
retval=0
|
|
# We filter child profiles as removing the parent will remove
|
|
# the children
|
|
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \
|
|
LC_COLLATE=C sort | grep -v // | while read profile ; do
|
|
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
|
rc=$?
|
|
if [ ${rc} -ne 0 ] ; then
|
|
retval=${rc}
|
|
fi
|
|
done
|
|
return ${retval}
|
|
}
|
|
|
|
apparmor_stop() {
|
|
aa_log_daemon_msg "Unloading AppArmor profiles "
|
|
remove_profiles
|
|
rc=$?
|
|
aa_log_end_msg $rc
|
|
return $rc
|
|
}
|
|
|
|
apparmor_kill() {
|
|
aa_log_daemon_msg "Unloading AppArmor modules "
|
|
if ! is_apparmor_loaded ; then
|
|
aa_log_failure_msg "AppArmor module is not loaded"
|
|
return 1
|
|
fi
|
|
|
|
if is_apparmor_present apparmor ; then
|
|
MODULE=apparmor
|
|
else
|
|
aa_log_failure_msg "AppArmor is builtin"
|
|
return 1
|
|
fi
|
|
/sbin/modprobe -qr $MODULE
|
|
rc=$?
|
|
aa_log_end_msg $rc
|
|
return $rc
|
|
}
|
|
|
|
__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
|
|
|
|
aa_log_daemon_msg "Restarting AppArmor"
|
|
|
|
configure_owlsm
|
|
parse_profiles reload
|
|
|
|
rc=$?
|
|
aa_log_end_msg $rc
|
|
return $rc
|
|
}
|
|
|
|
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 $?
|
|
}
|
|
|
|
apparmor_status () {
|
|
if test -x ${AA_STATUS} ; then
|
|
${AA_STATUS} --verbose
|
|
return $?
|
|
fi
|
|
if ! is_apparmor_loaded ; 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
|
|
}
|