#!/bin/sh # # $Id$ # # ---------------------------------------------------------------------- # Copyright (c) 1999, 2000, 20001, 2004, 2005, 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.subdomain.functions by Steve Beattie # # NOTE: rc.subdomain initscripts that source this file need to implement # the following set of functions: # sd_action # sd_log_success_msg # sd_log_warning_msg # sd_log_failure_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 sd_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 sd_log_warning_msg "/etc/subdomain.conf is deprecated, use ${CONFIG_DIR}/subdomain.conf instead" APPARMOR_CONF="/etc/subdomain.conf" else sd_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 source "${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 sd_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 if grep -q securityfs /proc/filesystems ; then SECURITYFS=/sys/kernel/security fi SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \ sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null) SUBDOMAIN_SRC="/usr/src/kernel-modules/SubDomain/module" 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 function 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 sd_log_failure_msg "- AppArmor parser not found" exit 1 fi if [ ! -d "$PROFILE_DIR" ]; then sd_log_skipped_msg "- Profile directory not found\nNo AppArmor policy loaded." return 1 fi if [ "X" == "X$(ls $PROFILE_DIR/)" ]; then sd_log_skipped_msg "- No profiles found\nNo AppArmor policy loaded." return 1 fi for profile in $PROFILE_DIR/*; do if [ "${profile%.rpmnew}" != "${profile}" -o \ "${profile%.rpmsave}" != "${profile}" -o \ "${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 sd_log_success_msg elif [ $STATUS -eq 2 ]; then sd_log_warning_msg else sd_log_failure_msg exit $STATUS fi } function profiles_names_list() { # run the parser on all of the apparmor profiles TMPFILE=$1 if [ ! -f "$PARSER" ]; then sd_log_failure_msg "- AppArmor parser not found" exit 1 fi if [ ! -d "$PROFILE_DIR" ]; then sd_log_failure_msg "- Profile directory not found" exit 1 fi for profile in $PROFILE_DIR/*; do if [ "${profile%.rpmnew}" != "${profile}" -o \ "${profile%.rpmsave}" != "${profile}" -o \ "${profile%\~}" != "${profile}" ] then echo "nop" >/dev/null elif [ -f "${profile}" ] ; then LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" | grep -v '\^') if [ $? -eq 0 ]; then echo "$LIST_ADD" >>$TMPFILE fi fi done } function is_subdomainfs_mounted() { if grep -q subdomainfs /proc/filesystems ; then if grep -q subdomainfs /proc/mounts && \ [ -f "${SUBDOMAINFS_MOUNTPOINT}/profiles" ]; then SFS_MOUNTPOINT=${SUBDOMAINFS_MOUNTPOINT} return 0 else return 1 fi fi if grep -q securityfs /proc/filesystems && grep -q securityfs /proc/mounts ; then 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 fi return 1 } function mount_subdomainfs() { # for backwords compatibility if grep -q subdomainfs /proc/filesystems ; then if [ "X" != "X${SUBDOMAINFS_MOUNTPOINT}" ]; then SFS_MOUNTPOINT=${SUBDOMAINFS_MOUNTPOINT} sd_action "Mounting subdomainfs on ${SFS_MOUNTPOINT}" mount "${SFS_MOUNTPOINT}" rc=$? return $rc fi fi if [ "X" != "X${SECURITYFS}" ]; then if ! grep -q securityfs /proc/mounts ; then sd_action "Mounting securityfs on ${SECURITYFS}" \ mount -t securityfs securityfs "${SECURITYFS}" rc=$? if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}" elif [ -f "${SECURITYFS}/${OLD_MODULE}/profiles" ]; then SFS_MOUNTPOINT="${SECURITYFS}/${OLD_MODULE}" else SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}" fi return $rc fi fi return 0 } function unmount_subdomainfs() { SUBDOMAINFS=$(grep subdomainfs /proc/mounts | cut -d" " -f2 2> /dev/null) if [ "X" != "X${SUBDOMAINFS}" ]; then sd_action "Unmounting subdomainfs" umount ${SUBDOMAINFS} fi } function rebuild_subdomain() { if [ -d "$SUBDOMAIN_SRC" ] ; then # only try to rebuild for the running kernel cd "$SUBDOMAIN_SRC" kernelver=`uname -r` kernelsrc=`readlink "/lib/modules/$kernelver/build"` line="KERNELVER=$kernelver KERNELSRC=$kernelsrc" /usr/bin/env $line ${SUBDOMAIN_SRC}/BUILD-SUBDOMAIN ; rc=$? if [ $rc -ne 0 ] ; then sd_log_failure_msg "- could not rebuild AppArmor module" return $rc fi depmod -a rc=$? if [ $rc -ne 0 ] ; then sd_log_failure_msg "- could not set AppArmor module dependencies" return $rc ; fi sd_action "Loading AppArmor module" /sbin/modprobe $MODULE $1 rc=$? if [ $rc -ne 0 ] ; then # we couldn't find the module sd_log_failure_msg "- could not load rebuilt AppArmor module" rc=$? return $rc fi else sd_log_failure_msg "- could not rebuild AppArmor, module source not found." return -1 fi } function failstop_system() { level=$(runlevel | cut -d" " -f2) if [ $level -ne "1" ] ; then sd_log_failure_msg "- could not start AppArmor. Changing to runlevel 1" telinit 1; return -1; fi sd_log_failure_msg "- could not start AppArmor." return -1 } function module_panic() { # the module failed to load, determine what action should be taken case "$SUBDOMAIN_MODULE_PANIC" in "warn"|"WARN") sd_log_failure_msg "- could not start AppArmor" return -1 ;; "build"|"BUILD") rebuild_subdomain rc=$? return $rc ;; "build-panic"|"BUILD-PANIC") rebuild_subdomain rc=$? if [ $rc -ne 0 ] ; then failstop_system rc=$? fi return $rc ;; "panic"|"PANIC") failstop_system rc=$? return $rc ;; *) sd_log_failure_msg "- invalid AppArmor module fail option" return -1 ;; esac } function load_module() { if modinfo -F filename apparmor > /dev/null 2>&1 ; then MODULE=apparmor elif modinfo -F filename subdomain > /dev/null 2>&1 ; then MODULE=subdomain fi if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then sd_action "Loading AppArmor module" /sbin/modprobe $MODULE $1 rc=$? if [ $rc -ne 0 ] ; then # we couldn't find the module module_panic rc=$? if [ $rc -ne 0 ] ; then exit $rc fi fi fi } function start_aa_event() { if [ -x "$AA_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then sd_action "Starting AppArmor Event daemon" startproc -f -p $AA_EV_PIDFILE $AA_EV_BIN -p $AA_EV_PIDFILE elif [ -x "$SD_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then sd_action "Starting AppArmor Event daemon" startproc -f -p $SD_EV_PIDFILE $SD_EV_BIN -p $SD_EV_PIDFILE fi } function stop_aa_event() { if [ -x "$AA_EV_BIN" -a -f "$AA_EV_PIDFILE" ] ; then sd_action "Shutting down AppArmor Event daemon" killproc -G -p $AA_EV_PIDFILE -INT $AA_EV_BIN fi if [ -f "$SD_EV_PIDFILE" ] ; then sd_action "Shutting down AppArmor Event daemon" killproc -G -p $SD_EV_PIDFILE -INT $SD_EV_BIN fi } function subdomain_start() { if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then load_module rc=$? if [ $rc -ne 0 ] ; then return $rc fi fi if ! is_subdomainfs_mounted ; then mount_subdomainfs rc=$? if [ $rc -ne 0 ] ; then return $rc fi fi if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then sd_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 sd_log_skipped_msg "Loading AppArmor profiles - AppArmor already loaded with profiles." fi } function 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_subdomainfs_mounted ; then sd_log_failure_msg "- failed, is securityfs loaded?" return 1 fi if [ ! -w "$SFS_MOUNTPOINT/.remove" ] ; then sd_log_failure_msg "- failed, Do you have the correct privileges?" return 1 fi if [ ! -x "${PARSER}" ] ; then sd_log_failure_msg "- failed, unable to execute subdomain parser" return 1 fi retval=0 IFS=$'\n' && for profile in $(sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles") ; do echo "\"$profile\" { }" | $PARSER -R >/dev/null rc=$? if [ ${rc} -ne 0 ] ; then retval=${rc} fi done if [ ${retval} -eq 0 ] ; then sd_log_success_msg else sd_log_failure_msg fi } function subdomain_stop() { stop_aa_event echo -n "Unloading AppArmor profiles " remove_profiles } function subdomain_kill() { stop_aa_event unmount_subdomainfs if grep -qE "^apparmor[[:space:]]" /proc/modules ; then MODULE=apparmor elif grep -qE "^subdomain[[:space:]]" /proc/modules ; then MODULE=subdomain else MODULE=apparmor fi sd_action "Unloading AppArmor modules" /sbin/modprobe -r $MODULE } function __subdomain_restart() { if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then sd_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" #profiles=$(cat $PNAMES_LIST | sort | comm -2 -3 "$MODULE_PLIST" -) #for profile in $profiles ; do IFS=$'\n' && for profile in $(cat $PNAMES_LIST | sort | comm -2 -3 "$MODULE_PLIST" -) ; do echo "\"$profile\" {}" | $PARSER -R >/dev/null done rm "$MODULE_PLIST" rm "$PNAMES_LIST" return 0 } function subdomain_restart() { if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then subdomain_start rc=$? return $rc fi if ! is_subdomainfs_mounted ; then mount_subdomainfs rc=$? if [ $rc -ne 0 ] ; then return $rc fi fi __subdomain_restart rc=$? return $rc } function subdomain_try_restart() { if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then return 1 fi if ! is_subdomainfs_mounted ; then return 1 fi __subdomain_restart rc=$? return $rc } function subdomain_debug() { subdomain_kill load_module "subdomain_debug=1" mount_subdomainfs configure_owlsm parse_profiles load } function configure_owlsm () { if [ "${SUBDOMAIN_ENABLE_OWLSM}" = "yes" -a -f ${SFS_MOUNTPOINT}/control/owlsm ] ; then # Sigh, the "sh -c" is necessary for the SuSE sd_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. sd_action "Enabling OWLSM extension" sh -c "echo -n \"1\" > \"${SFS_MOUNTPOINT}/control/owlsm\"" elif [ -f "${SFS_MOUNTPOINT}/control/owlsm" ] ; then sd_action "Disabling OWLSM extension" sh -c "echo -n \"0\" > \"${SFS_MOUNTPOINT}/control/owlsm\"" fi } function subdomain_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 }