2006-04-11 21:52:54 +00:00
|
|
|
#!/bin/sh
|
|
|
|
# ----------------------------------------------------------------------
|
2011-02-22 11:14:34 -06:00
|
|
|
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
2012-02-24 04:21:59 -08:00
|
|
|
# Copyright (c) 2009-2012 Canonical Ltd. (All rights reserved)
|
2006-04-11 21:52:54 +00:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
# ----------------------------------------------------------------------
|
2007-04-04 21:56:08 +00:00
|
|
|
# rc.apparmor.functions by Steve Beattie
|
2006-04-11 21:52:54 +00:00
|
|
|
#
|
2007-04-04 21:56:08 +00:00
|
|
|
# NOTE: rc.apparmor initscripts that source this file need to implement
|
2006-04-11 21:52:54 +00:00
|
|
|
# the following set of functions:
|
2007-04-04 21:56:08 +00:00
|
|
|
# aa_action
|
2009-11-11 10:51:05 -08:00
|
|
|
# aa_log_action_start
|
|
|
|
# aa_log_action_end
|
2007-04-04 21:56:08 +00:00
|
|
|
# aa_log_success_msg
|
|
|
|
# aa_log_warning_msg
|
|
|
|
# aa_log_failure_msg
|
|
|
|
# aa_log_skipped_msg
|
2009-11-11 10:51:05 -08:00
|
|
|
# aa_log_daemon_msg
|
|
|
|
# aa_log_end_msg
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
# 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
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_warning_msg "/etc/immunix/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
|
2006-04-11 21:52:54 +00:00
|
|
|
APPARMOR_CONF="/etc/immunix/subdomain.conf"
|
|
|
|
elif [ -f "/etc/subdomain.conf" ] ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_warning_msg "/etc/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead"
|
2006-04-11 21:52:54 +00:00
|
|
|
APPARMOR_CONF="/etc/subdomain.conf"
|
|
|
|
else
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_warning_msg "Unable to find config file in ${CONFIG_DIR}, installation problem?"
|
2006-04-11 21:52:54 +00:00
|
|
|
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
|
2006-12-12 10:54:44 +00:00
|
|
|
. "${APPARMOR_CONF}"
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
|
|
|
|
2009-11-11 10:51:05 -08:00
|
|
|
PARSER=/sbin/apparmor_parser
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
# SUBDOMAIN_DIR and APPARMOR_DIR might be defined in subdomain.conf|apparmor.conf
|
2008-11-18 17:33:38 +00:00
|
|
|
if [ -d "${APPARMOR_DIR}" ] ; then
|
2006-04-11 21:52:54 +00:00
|
|
|
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
|
2010-11-03 17:03:52 -07:00
|
|
|
AA_STATUS=/usr/sbin/aa-status
|
2006-04-11 21:52:54 +00:00
|
|
|
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
|
2007-04-04 21:23:42 +00:00
|
|
|
SECURITYFS=/sys/kernel/security
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2009-07-24 12:06:17 +00:00
|
|
|
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
|
|
|
|
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
# keep exit status from parser during profile load. 0 is good, 1 is bad
|
|
|
|
STATUS=0
|
|
|
|
|
2008-01-03 22:27:20 +00:00
|
|
|
# Test if the apparmor "module" is present.
|
|
|
|
is_apparmor_present() {
|
2009-07-24 12:06:17 +00:00
|
|
|
local modules=$1
|
|
|
|
shift
|
|
|
|
|
|
|
|
while [ $# -gt 0 ] ; do
|
|
|
|
modules="$modules|$1"
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
|
|
|
# check for subdomainfs version of module
|
|
|
|
grep -qE "^($modules)[[:space:]]" /proc/modules
|
2009-11-11 10:51:05 -08:00
|
|
|
|
2011-08-13 14:13:49 +02:00
|
|
|
[ $? -ne 0 -a -d /sys/module/apparmor ]
|
2008-01-03 22:27:20 +00:00
|
|
|
|
|
|
|
return $?
|
|
|
|
}
|
|
|
|
|
2007-08-14 19:19:59 +00:00
|
|
|
# This set of patterns to skip needs to be kept in sync with
|
2011-01-13 13:58:26 -08:00
|
|
|
# AppArmor.pm::isSkippableFile()
|
2009-11-11 10:51:05 -08:00
|
|
|
# returns 0 if profile should NOT be skipped
|
|
|
|
# returns 1 on verbose skip
|
|
|
|
# returns 2 on silent skip
|
2007-04-04 20:42:26 +00:00
|
|
|
skip_profile() {
|
|
|
|
local profile=$1
|
|
|
|
if [ "${profile%.rpmnew}" != "${profile}" -o \
|
|
|
|
"${profile%.rpmsave}" != "${profile}" -o \
|
2009-11-11 10:51:05 -08:00
|
|
|
-e "${PROFILE_DIR}/disable/`basename ${profile}`" -o \
|
2007-04-04 20:42:26 +00:00
|
|
|
"${profile%\~}" != "${profile}" ] ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
# Silently ignore the dpkg files
|
|
|
|
if [ "${profile%.dpkg-new}" != "${profile}" -o \
|
|
|
|
"${profile%.dpkg-old}" != "${profile}" -o \
|
2010-02-16 12:56:04 -08:00
|
|
|
"${profile%.dpkg-dist}" != "${profile}" -o \
|
|
|
|
"${profile%.dpkg-bak}" != "${profile}" ] ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
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
|
2007-04-04 20:42:26 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
parse_profiles() {
|
2006-04-11 21:52:54 +00:00
|
|
|
# get parser arg
|
|
|
|
case "$1" in
|
|
|
|
load)
|
|
|
|
PARSER_ARGS="--add"
|
|
|
|
PARSER_MSG="Loading AppArmor profiles "
|
|
|
|
;;
|
|
|
|
reload)
|
|
|
|
PARSER_ARGS="--replace"
|
|
|
|
PARSER_MSG="Reloading AppArmor profiles "
|
|
|
|
;;
|
|
|
|
*)
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "required 'load' or 'reload'"
|
2006-04-11 21:52:54 +00:00
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
2011-03-17 10:21:06 -07:00
|
|
|
aa_log_action_start "$PARSER_MSG"
|
2006-04-11 21:52:54 +00:00
|
|
|
# run the parser on all of the apparmor profiles
|
|
|
|
if [ ! -f "$PARSER" ]; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "AppArmor parser not found"
|
|
|
|
aa_log_action_end 1
|
2006-04-11 21:52:54 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -d "$PROFILE_DIR" ]; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "Profile directory not found"
|
|
|
|
aa_log_action_end 1
|
|
|
|
exit 1
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
|
|
|
|
2007-03-27 18:38:28 +00:00
|
|
|
if [ -z "$(ls $PROFILE_DIR/)" ]; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "No profiles found"
|
|
|
|
aa_log_action_end 1
|
2006-08-04 17:16:47 +00:00
|
|
|
return 1
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
|
|
|
|
|
|
|
for profile in $PROFILE_DIR/*; do
|
2009-11-11 10:51:05 -08:00
|
|
|
skip_profile "${profile}"
|
|
|
|
skip=$?
|
|
|
|
# Ignore skip status == 2 (silent skip)
|
|
|
|
if [ "$skip" -eq 1 ] ; then
|
|
|
|
aa_log_skipped_msg "$profile"
|
2006-04-11 21:52:54 +00:00
|
|
|
logger -t "AppArmor(init)" -p daemon.warn "Skipping profile $profile"
|
2009-11-11 10:51:05 -08:00
|
|
|
STATUS=2
|
2011-08-04 16:20:26 -07:00
|
|
|
continue
|
2009-11-11 10:51:05 -08:00
|
|
|
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
|
2006-04-11 21:52:54 +00:00
|
|
|
if [ $? -ne 0 ]; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "$profile failed to load"
|
2006-04-11 21:52:54 +00:00
|
|
|
STATUS=1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
2009-11-11 10:51:05 -08:00
|
|
|
if [ $STATUS -eq 2 ]; then
|
|
|
|
STATUS=0
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_action_end "$STATUS"
|
|
|
|
return $STATUS
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
profiles_names_list() {
|
2006-04-11 21:52:54 +00:00
|
|
|
# run the parser on all of the apparmor profiles
|
|
|
|
if [ ! -f "$PARSER" ]; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_failure_msg "- AppArmor parser not found"
|
2006-04-11 21:52:54 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -d "$PROFILE_DIR" ]; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_failure_msg "- Profile directory not found"
|
2006-04-11 21:52:54 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
for profile in $PROFILE_DIR/*; do
|
2009-11-11 10:51:05 -08:00
|
|
|
if skip_profile "${profile}" && [ -f "${profile}" ] ; then
|
Attached is a patch to make the initscript not fail if /tmp is full
by converting the comm(1) usage on temporary files to an embedded
awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in
Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency
on the minimal or base package set, and the original reporter also
mentioned that an awk-based solution would be palatable in a way that
converting to bash, or using perl or python here would not be.
In the embedded awk script, I've tried to avoid gawk or mawk specific
behaviors or extensions; e.g. this is the reason for the call to sort
on the output of the awk script, rather than using gawk's asort(). But
please let me know if you see anything that shouldn't be portable
across awk implementations.
An additional issue that is fixed in both scripts is handling child
profiles (e.g. hats) during reload. If child profiles are filtered
out (via grep -v '//') of the list to consider, then on reloading
a profile where a child profile has been removed or renamed, that
child profile will continue to stick around. However, if the profile
containing child profiles is removed entirely, if the initscript
attempts to unload the child profiles after the parent is removed,
this will fail because they were unloaded when the parent was unloaded.
Thus I removed any filtering of child profiles out, but do a post-awk
reverse sort which guarantees that any child profiles will be removed
before their parent is. I also added the LC_COLLATE=C (based on the
Ubuntu version) to the sort call to ensure a consistent sort order.
To restate, the problem with the existing code is that it creates
temporary files in $TMPDIR (by default /tmp) and if that partition
is full, problems with the reload action ensue. Alternate solutions
include switching the initscript to use bash and its <$() extension
or setting TMPDIR to /dev/shm/. The former is unpalatable to some
(particularly for an initscript), and for the latter, /dev/shm is
only guaranteed to exist on GNU libc based systems (glibc apparently
expects /dev/shm to exist for its POSIX shared memory implementation;
see shm_overview(7)). So to me, awk (sans GNU extensions) looks to
be the least bad option here.
Bug: https://launchpad.net/bugs/775785
2011-08-26 15:55:43 -07:00
|
|
|
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" )
|
2006-04-11 21:52:54 +00:00
|
|
|
if [ $? -eq 0 ]; then
|
Attached is a patch to make the initscript not fail if /tmp is full
by converting the comm(1) usage on temporary files to an embedded
awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in
Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency
on the minimal or base package set, and the original reporter also
mentioned that an awk-based solution would be palatable in a way that
converting to bash, or using perl or python here would not be.
In the embedded awk script, I've tried to avoid gawk or mawk specific
behaviors or extensions; e.g. this is the reason for the call to sort
on the output of the awk script, rather than using gawk's asort(). But
please let me know if you see anything that shouldn't be portable
across awk implementations.
An additional issue that is fixed in both scripts is handling child
profiles (e.g. hats) during reload. If child profiles are filtered
out (via grep -v '//') of the list to consider, then on reloading
a profile where a child profile has been removed or renamed, that
child profile will continue to stick around. However, if the profile
containing child profiles is removed entirely, if the initscript
attempts to unload the child profiles after the parent is removed,
this will fail because they were unloaded when the parent was unloaded.
Thus I removed any filtering of child profiles out, but do a post-awk
reverse sort which guarantees that any child profiles will be removed
before their parent is. I also added the LC_COLLATE=C (based on the
Ubuntu version) to the sort call to ensure a consistent sort order.
To restate, the problem with the existing code is that it creates
temporary files in $TMPDIR (by default /tmp) and if that partition
is full, problems with the reload action ensue. Alternate solutions
include switching the initscript to use bash and its <$() extension
or setting TMPDIR to /dev/shm/. The former is unpalatable to some
(particularly for an initscript), and for the latter, /dev/shm is
only guaranteed to exist on GNU libc based systems (glibc apparently
expects /dev/shm to exist for its POSIX shared memory implementation;
see shm_overview(7)). So to me, awk (sans GNU extensions) looks to
be the least bad option here.
Bug: https://launchpad.net/bugs/775785
2011-08-26 15:55:43 -07:00
|
|
|
echo "$LIST_ADD"
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
failstop_system() {
|
2006-04-11 21:52:54 +00:00
|
|
|
level=$(runlevel | cut -d" " -f2)
|
|
|
|
if [ $level -ne "1" ] ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_failure_msg "- could not start AppArmor. Changing to runlevel 1"
|
2006-04-11 21:52:54 +00:00
|
|
|
telinit 1;
|
|
|
|
return -1;
|
|
|
|
fi
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_failure_msg "- could not start AppArmor."
|
2006-04-11 21:52:54 +00:00
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
module_panic() {
|
2006-04-11 21:52:54 +00:00
|
|
|
# the module failed to load, determine what action should be taken
|
|
|
|
|
|
|
|
case "$SUBDOMAIN_MODULE_PANIC" in
|
2007-04-04 21:23:42 +00:00
|
|
|
"warn"|"WARN")
|
|
|
|
return 1 ;;
|
2006-04-11 21:52:54 +00:00
|
|
|
"panic"|"PANIC") failstop_system
|
|
|
|
rc=$?
|
|
|
|
return $rc ;;
|
2007-04-04 21:56:08 +00:00
|
|
|
*) aa_log_failure_msg "- invalid AppArmor module fail option"
|
2006-04-11 21:52:54 +00:00
|
|
|
return -1 ;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
2007-04-04 21:23:42 +00:00
|
|
|
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
|
|
|
|
|
2009-07-24 12:06:17 +00:00
|
|
|
if [ -f "${SUBDOMAINFS_MOUNTPOINT}/profiles" ]; then
|
|
|
|
SFS_MOUNTPOINT=${SUBDOMAINFS_MOUNTPOINT}
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
|
2007-04-04 21:23:42 +00:00
|
|
|
# check for subdomainfs version of module
|
2009-07-24 12:06:17 +00:00
|
|
|
is_apparmor_present apparmor subdomain
|
2008-01-03 22:27:20 +00:00
|
|
|
|
2007-04-04 21:23:42 +00:00
|
|
|
return $?
|
|
|
|
}
|
|
|
|
|
|
|
|
is_securityfs_mounted() {
|
2011-08-13 14:15:58 +02:00
|
|
|
test -d ${SECURITYFS} -a -d /sys/fs/cgroup/systemd || grep -q securityfs /proc/filesystems && grep -q securityfs /proc/mounts
|
2007-04-04 21:23:42 +00:00
|
|
|
return $?
|
|
|
|
}
|
|
|
|
|
|
|
|
mount_securityfs() {
|
|
|
|
if grep -q securityfs /proc/filesystems ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_action "Mounting securityfs on ${SECURITYFS}" \
|
2007-04-04 21:23:42 +00:00
|
|
|
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
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_action "Mounting subdomainfs on ${SUBDOMAINFS_MOUNTPOINT}" \
|
2007-04-04 21:23:42 +00:00
|
|
|
mount "${SUBDOMAINFS_MOUNTPOINT}"
|
|
|
|
return $?
|
|
|
|
fi
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
unmount_subdomainfs() {
|
|
|
|
SUBDOMAINFS=$(grep subdomainfs /proc/mounts | cut -d" " -f2 2> /dev/null)
|
|
|
|
if [ -n "${SUBDOMAINFS}" ]; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_action "Unmounting subdomainfs" umount ${SUBDOMAINFS}
|
2007-04-04 21:23:42 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
load_module() {
|
2007-04-04 21:23:42 +00:00
|
|
|
local rc=0
|
2006-04-11 21:52:54 +00:00
|
|
|
if modinfo -F filename apparmor > /dev/null 2>&1 ; then
|
|
|
|
MODULE=apparmor
|
2007-04-04 21:23:42 +00:00
|
|
|
elif modinfo -F filename ${OLD_MODULE} > /dev/null 2>&1 ; then
|
|
|
|
MODULE=${OLD_MODULE}
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
2007-04-04 21:23:42 +00:00
|
|
|
|
2008-01-03 22:27:20 +00:00
|
|
|
if ! is_apparmor_present apparmor subdomain ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_action "Loading AppArmor module" /sbin/modprobe -q $MODULE $1
|
2006-04-11 21:52:54 +00:00
|
|
|
rc=$?
|
|
|
|
if [ $rc -ne 0 ] ; then
|
|
|
|
module_panic
|
|
|
|
rc=$?
|
|
|
|
if [ $rc -ne 0 ] ; then
|
|
|
|
exit $rc
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
2007-04-04 21:23:42 +00:00
|
|
|
|
|
|
|
if ! is_apparmor_loaded ; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
return $rc
|
2009-11-11 10:51:05 -08:00
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_start() {
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_daemon_msg "Starting AppArmor"
|
2007-04-04 21:23:42 +00:00
|
|
|
if ! is_apparmor_loaded ; then
|
2006-04-11 21:52:54 +00:00
|
|
|
load_module
|
|
|
|
rc=$?
|
|
|
|
if [ $rc -ne 0 ] ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_end_msg $rc
|
2006-04-11 21:52:54 +00:00
|
|
|
return $rc
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_end_msg 1
|
2006-04-11 21:52:54 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
configure_owlsm
|
|
|
|
|
2008-11-07 12:53:37 +00:00
|
|
|
# if there is anything in the profiles file don't load
|
2011-08-13 14:13:49 +02:00
|
|
|
if ! read line < "$SFS_MOUNTPOINT/profiles"; then
|
2006-04-11 21:52:54 +00:00
|
|
|
parse_profiles load
|
|
|
|
else
|
2011-08-13 14:13:49 +02:00
|
|
|
aa_log_skipped_msg ": already loaded with profiles."
|
|
|
|
return 0
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_end_msg 0
|
|
|
|
return 0
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
remove_profiles() {
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
# 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
|
2007-04-04 21:23:42 +00:00
|
|
|
if ! is_apparmor_loaded ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "AppArmor module is not loaded"
|
2006-04-11 21:52:54 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -w "$SFS_MOUNTPOINT/.remove" ] ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "Root privileges not available"
|
2006-04-11 21:52:54 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -x "${PARSER}" ] ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "Unable to execute AppArmor parser"
|
2006-04-11 21:52:54 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
retval=0
|
Attached is a patch to make the initscript not fail if /tmp is full
by converting the comm(1) usage on temporary files to an embedded
awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in
Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency
on the minimal or base package set, and the original reporter also
mentioned that an awk-based solution would be palatable in a way that
converting to bash, or using perl or python here would not be.
In the embedded awk script, I've tried to avoid gawk or mawk specific
behaviors or extensions; e.g. this is the reason for the call to sort
on the output of the awk script, rather than using gawk's asort(). But
please let me know if you see anything that shouldn't be portable
across awk implementations.
An additional issue that is fixed in both scripts is handling child
profiles (e.g. hats) during reload. If child profiles are filtered
out (via grep -v '//') of the list to consider, then on reloading
a profile where a child profile has been removed or renamed, that
child profile will continue to stick around. However, if the profile
containing child profiles is removed entirely, if the initscript
attempts to unload the child profiles after the parent is removed,
this will fail because they were unloaded when the parent was unloaded.
Thus I removed any filtering of child profiles out, but do a post-awk
reverse sort which guarantees that any child profiles will be removed
before their parent is. I also added the LC_COLLATE=C (based on the
Ubuntu version) to the sort call to ensure a consistent sort order.
To restate, the problem with the existing code is that it creates
temporary files in $TMPDIR (by default /tmp) and if that partition
is full, problems with the reload action ensue. Alternate solutions
include switching the initscript to use bash and its <$() extension
or setting TMPDIR to /dev/shm/. The former is unpalatable to some
(particularly for an initscript), and for the latter, /dev/shm is
only guaranteed to exist on GNU libc based systems (glibc apparently
expects /dev/shm to exist for its POSIX shared memory implementation;
see shm_overview(7)). So to me, awk (sans GNU extensions) looks to
be the least bad option here.
Bug: https://launchpad.net/bugs/775785
2011-08-26 15:55:43 -07:00
|
|
|
# We filter child profiles as removing the parent will remove
|
|
|
|
# the children
|
2011-10-12 00:45:11 +02:00
|
|
|
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \
|
Attached is a patch to make the initscript not fail if /tmp is full
by converting the comm(1) usage on temporary files to an embedded
awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in
Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency
on the minimal or base package set, and the original reporter also
mentioned that an awk-based solution would be palatable in a way that
converting to bash, or using perl or python here would not be.
In the embedded awk script, I've tried to avoid gawk or mawk specific
behaviors or extensions; e.g. this is the reason for the call to sort
on the output of the awk script, rather than using gawk's asort(). But
please let me know if you see anything that shouldn't be portable
across awk implementations.
An additional issue that is fixed in both scripts is handling child
profiles (e.g. hats) during reload. If child profiles are filtered
out (via grep -v '//') of the list to consider, then on reloading
a profile where a child profile has been removed or renamed, that
child profile will continue to stick around. However, if the profile
containing child profiles is removed entirely, if the initscript
attempts to unload the child profiles after the parent is removed,
this will fail because they were unloaded when the parent was unloaded.
Thus I removed any filtering of child profiles out, but do a post-awk
reverse sort which guarantees that any child profiles will be removed
before their parent is. I also added the LC_COLLATE=C (based on the
Ubuntu version) to the sort call to ensure a consistent sort order.
To restate, the problem with the existing code is that it creates
temporary files in $TMPDIR (by default /tmp) and if that partition
is full, problems with the reload action ensue. Alternate solutions
include switching the initscript to use bash and its <$() extension
or setting TMPDIR to /dev/shm/. The former is unpalatable to some
(particularly for an initscript), and for the latter, /dev/shm is
only guaranteed to exist on GNU libc based systems (glibc apparently
expects /dev/shm to exist for its POSIX shared memory implementation;
see shm_overview(7)). So to me, awk (sans GNU extensions) looks to
be the least bad option here.
Bug: https://launchpad.net/bugs/775785
2011-08-26 15:55:43 -07:00
|
|
|
LC_COLLATE=C sort | grep -v // | while read profile ; do
|
2008-05-29 23:10:27 +00:00
|
|
|
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
2006-04-11 21:52:54 +00:00
|
|
|
rc=$?
|
|
|
|
if [ ${rc} -ne 0 ] ; then
|
|
|
|
retval=${rc}
|
|
|
|
fi
|
|
|
|
done
|
2007-04-04 21:23:42 +00:00
|
|
|
return ${retval}
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_stop() {
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_daemon_msg "Unloading AppArmor profiles "
|
2006-04-11 21:52:54 +00:00
|
|
|
remove_profiles
|
2009-11-11 10:51:05 -08:00
|
|
|
rc=$?
|
2011-03-17 10:21:06 -07:00
|
|
|
aa_log_end_msg $rc
|
2009-11-11 10:51:05 -08:00
|
|
|
return $rc
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_kill() {
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_daemon_msg "Unloading AppArmor modules "
|
2007-04-04 21:23:42 +00:00
|
|
|
if ! is_apparmor_loaded ; then
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "AppArmor module is not loaded"
|
2007-04-04 21:23:42 +00:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
unmount_subdomainfs
|
2008-01-03 22:27:20 +00:00
|
|
|
if is_apparmor_present apparmor ; then
|
2006-04-11 21:52:54 +00:00
|
|
|
MODULE=apparmor
|
2008-01-03 22:27:20 +00:00
|
|
|
elif is_apparmor_present subdomain ; then
|
2006-04-11 21:52:54 +00:00
|
|
|
MODULE=subdomain
|
|
|
|
else
|
2009-11-11 10:51:05 -08:00
|
|
|
aa_log_failure_msg "AppArmor is builtin"
|
2007-04-04 21:23:42 +00:00
|
|
|
return 1
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
2009-11-11 10:51:05 -08:00
|
|
|
/sbin/modprobe -qr $MODULE
|
|
|
|
rc=$?
|
|
|
|
aa_log_end_msg $rc
|
|
|
|
return $rc
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
__apparmor_restart() {
|
2006-04-11 21:52:54 +00:00
|
|
|
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
|
2006-04-11 21:52:54 +00:00
|
|
|
return 4
|
|
|
|
fi
|
|
|
|
|
2011-09-15 21:23:25 +02:00
|
|
|
aa_log_daemon_msg "Restarting AppArmor"
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
configure_owlsm
|
|
|
|
parse_profiles reload
|
2011-02-22 16:24:29 -06:00
|
|
|
# Clean out running profiles not associated with the current profile
|
|
|
|
# set, excluding the libvirt dynamically generated profiles.
|
Attached is a patch to make the initscript not fail if /tmp is full
by converting the comm(1) usage on temporary files to an embedded
awk script. On both Ubuntu and OpenSUSE, a version of awk (mawk in
Ubuntu, gawk in OpenSUSE) is either a direct or indirect dependency
on the minimal or base package set, and the original reporter also
mentioned that an awk-based solution would be palatable in a way that
converting to bash, or using perl or python here would not be.
In the embedded awk script, I've tried to avoid gawk or mawk specific
behaviors or extensions; e.g. this is the reason for the call to sort
on the output of the awk script, rather than using gawk's asort(). But
please let me know if you see anything that shouldn't be portable
across awk implementations.
An additional issue that is fixed in both scripts is handling child
profiles (e.g. hats) during reload. If child profiles are filtered
out (via grep -v '//') of the list to consider, then on reloading
a profile where a child profile has been removed or renamed, that
child profile will continue to stick around. However, if the profile
containing child profiles is removed entirely, if the initscript
attempts to unload the child profiles after the parent is removed,
this will fail because they were unloaded when the parent was unloaded.
Thus I removed any filtering of child profiles out, but do a post-awk
reverse sort which guarantees that any child profiles will be removed
before their parent is. I also added the LC_COLLATE=C (based on the
Ubuntu version) to the sort call to ensure a consistent sort order.
To restate, the problem with the existing code is that it creates
temporary files in $TMPDIR (by default /tmp) and if that partition
is full, problems with the reload action ensue. Alternate solutions
include switching the initscript to use bash and its <$() extension
or setting TMPDIR to /dev/shm/. The former is unpalatable to some
(particularly for an initscript), and for the latter, /dev/shm is
only guaranteed to exist on GNU libc based systems (glibc apparently
expects /dev/shm to exist for its POSIX shared memory implementation;
see shm_overview(7)). So to me, awk (sans GNU extensions) looks to
be the least bad option here.
Bug: https://launchpad.net/bugs/775785
2011-08-26 15:55:43 -07:00
|
|
|
# Note that we reverse sort the list of profiles to remove to
|
|
|
|
# ensure that child profiles (e.g. hats) are removed before the
|
|
|
|
# parent. We *do* need to remove the child profile and not rely
|
|
|
|
# on removing the parent profile when the profile has had its
|
|
|
|
# child profile names changed.
|
|
|
|
profiles_names_list | awk '
|
|
|
|
BEGIN {
|
|
|
|
while (getline < "'${SFS_MOUNTPOINT}'/profiles" ) {
|
|
|
|
str = sub(/ \((enforce|complain)\)$/, "", $0);
|
|
|
|
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
|
|
|
|
arr[$str] = $str
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{ if (length(arr[$0]) > 0) { delete arr[$0] } }
|
|
|
|
|
|
|
|
END {
|
|
|
|
for (key in arr)
|
|
|
|
if (length(arr[key]) > 0) {
|
|
|
|
printf("%s\n", arr[key])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
' | LC_COLLATE=C sort -r | while IFS= read profile ; do
|
2008-06-04 07:24:38 +00:00
|
|
|
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
|
2006-04-11 21:52:54 +00:00
|
|
|
done
|
2011-09-15 21:23:25 +02:00
|
|
|
# will not catch all errors, but still better than nothing
|
|
|
|
rc=$?
|
|
|
|
aa_log_end_msg $rc
|
|
|
|
return $rc
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_restart() {
|
2007-04-04 21:23:42 +00:00
|
|
|
if ! is_apparmor_loaded ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_start
|
2006-04-11 21:52:54 +00:00
|
|
|
rc=$?
|
|
|
|
return $rc
|
|
|
|
fi
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
__apparmor_restart
|
2007-04-04 21:23:42 +00:00
|
|
|
return $?
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_try_restart() {
|
2007-04-04 21:23:42 +00:00
|
|
|
if ! is_apparmor_loaded ; then
|
2007-05-24 05:00:34 +00:00
|
|
|
return 0
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
__apparmor_restart
|
2007-04-04 21:23:42 +00:00
|
|
|
return $?
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2006-12-12 10:54:44 +00:00
|
|
|
configure_owlsm () {
|
2006-04-11 21:52:54 +00:00
|
|
|
if [ "${SUBDOMAIN_ENABLE_OWLSM}" = "yes" -a -f ${SFS_MOUNTPOINT}/control/owlsm ] ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
# Sigh, the "sh -c" is necessary for the SuSE aa_action
|
2006-04-11 21:52:54 +00:00
|
|
|
# and it can't be abstracted out as a seperate function, as
|
|
|
|
# that breaks under RedHat's action, which needs a
|
|
|
|
# binary to invoke.
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_action "Enabling OWLSM extension" sh -c "echo -n \"1\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
|
2006-04-11 21:52:54 +00:00
|
|
|
elif [ -f "${SFS_MOUNTPOINT}/control/owlsm" ] ; then
|
2007-04-04 21:56:08 +00:00
|
|
|
aa_action "Disabling OWLSM extension" sh -c "echo -n \"0\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
|
2006-04-11 21:52:54 +00:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2007-04-04 21:56:08 +00:00
|
|
|
apparmor_status () {
|
2006-04-11 21:52:54 +00:00
|
|
|
if test -x ${AA_STATUS} ; then
|
|
|
|
${AA_STATUS} --verbose
|
|
|
|
return $?
|
|
|
|
fi
|
|
|
|
if test -x ${SD_STATUS} ; then
|
|
|
|
${SD_STATUS} --verbose
|
|
|
|
return $?
|
|
|
|
fi
|
2011-11-10 09:43:10 -08:00
|
|
|
if ! is_apparmor_loaded ; then
|
2006-04-11 21:52:54 +00:00
|
|
|
echo "AppArmor is not loaded."
|
|
|
|
rc=1
|
|
|
|
else
|
2011-11-10 09:43:10 -08:00
|
|
|
echo "AppArmor is enabled."
|
2006-04-11 21:52:54 +00:00
|
|
|
rc=0
|
|
|
|
fi
|
|
|
|
echo "Install the apparmor-utils package to receive more detailed"
|
|
|
|
echo "status information here (or examine ${SFS_MOUNTPOINT} directly)."
|
|
|
|
|
|
|
|
return $rc
|
|
|
|
}
|