#! /bin/sh
#
# Policy Loader.
#
# Copyright (C) 2005-2008  NTT DATA CORPORATION
#
# Version: 2.2.0-pre 2008/06/25
#
# This program is executed automatically by kernel
# when execution of /sbin/init is requested.
#

POLICY_DIR=/proc/tomoyo/
PROFILE="default"
TOMOYO_NOLOAD=0
TOMOYO_QUIET=0
PROC_UNMOUNT=0
SYS_UNMOUNT=0
SECURITY_UNMOUNT=0
CHDIR_OK=0

# Mount /proc if not mounted.
if [ ! -d /proc/self/ ]; then
    mount -nt proc none /proc && PROC_UNMOUNT=1
fi

# Mount /sys if not mounted.
if [ ! -d /sys/kernel/ ]; then
    grep -q sysfs /proc/filesystems && mount -nt sysfs none /sys && SYS_UNMOUNT=1
fi

# Mount /sys/kernel/security if not mounted.
if [ ! -d /sys/kernel/security/tomoyo/ ]; then
    grep -q securityfs /proc/filesystems && mount -nt securityfs none /sys/kernel/security && SECURITY_UNMOUNT=1
fi

# Use /sys/kernel/security/tomoyo/ as policy interface if it exists.
if [ -d /sys/kernel/security/tomoyo/ ]; then
    POLICY_DIR=/sys/kernel/security/tomoyo/
fi

# Unmount and exit if policy interface doesn't exist.
if [ ! -d $POLICY_DIR ]; then
    [ $SECURITY_UNMOUNT -eq 1 ] && umount -n /sys/kernel/security
    [ $SYS_UNMOUNT -eq 1 ] && umount -n /sys
    [ $PROC_UNMOUNT -eq 1 ] && umount -n /proc
    exit 1
fi

# Open /dev/console if stdio are not connected.
#
# WARNING: Don't let this program be invoked implicitly
# if you are not operating from console.
# Otherwise, you will get unable to respond to prompt
# if something went wrong.
if [ ! -r /proc/self/fd/0 ]; then
    exec 0< /dev/console
    exec 1> /dev/console
    exec 2> /dev/console
fi

# Check /proc/cmdline and /proc/self/cmdline
for i in `cat /proc/cmdline` "$@"
  do
  case $i in
      (CCS=ask)
      PROFILE="ask"
      ;;
      (CCS=default)
      PROFILE="default"
      ;;
      (CCS=disabled)
      PROFILE="disable"
      ;;
      (CCS=*)
      PROFILE=`echo $i | cut -b 5-`
      ;;
      (TOMOYO_NOLOAD)
      TOMOYO_NOLOAD=1
      ;;
      (TOMOYO_QUIET)
      TOMOYO_QUIET=1
      ;;
  esac
done

# Does policy directory exist?
if cd /etc/tomoyo/ 2> /dev/null; then
    CHDIR_OK=1
else
    PROFILE="disable"
fi

# Does selected profile exist?
if [ $CHDIR_OK -eq 1 ]; then
    if [ "x$PROFILE" = "xdefault" ]; then
	if [ ! -r profile.conf ]; then
	    echo "TOMOYO Linux: Default profile doesn't exist."
	    PROFILE="ask"
	fi
    elif [ "x$PROFILE" != "xask" -a "x$PROFILE" != "xdisable" ]; then
	if [ ! -r profile-$PROFILE.conf ]; then
	    echo "TOMOYO Linux: Specified profile doesn't exist."
	    PROFILE="ask"
	fi
    fi
fi

# Show prompt if something went wrong or explicitly asked.
if [ "x$PROFILE" = "xask" ]; then
    while :
      do
      echo "TOMOYO Linux: Select a profile from the following list."
      if [ $CHDIR_OK -eq 1 ]; then
	  # Show profiles in policy directory.
	  [ -r profile.conf ] && echo "default"
	  echo profile-*.conf | awk ' { gsub("profile-default.conf", ""); gsub("profile-disable.conf", ""); gsub("profile-", ""); gsub(".conf", ""); if ( $0 != "*") print $0; } '
      fi
      echo "disable"
      PROFILE=""
      read -p "> " PROFILE
      if [ $CHDIR_OK -eq 1 ]; then
	  [ -r profile.conf -a "x$PROFILE" = "xdefault" ] && break
	  [ "x$PROFILE" != "xdefault" -a "x$PROFILE" != "xdisable" -a -r profile-$PROFILE.conf ] && break
      fi
      [ "x$PROFILE" = "xdisable" ] && break
      [ "x$PROFILE" = "xTOMOYO_NOLOAD" ] && TOMOYO_NOLOAD=1
      [ "x$PROFILE" = "xTOMOYO_QUIET" ] && TOMOYO_QUIET=1
    done
fi

# Load policy.
if [ $CHDIR_OK -eq 1 ]; then
    [ -r manager.conf ] && cat manager.conf > $POLICY_DIR/manager
    [ -r system_policy.conf -a -w $POLICY_DIR/system_policy ] && cat system_policy.conf > $POLICY_DIR/system_policy
    [ -r exception_policy.conf -a -w $POLICY_DIR/exception_policy ] && cat exception_policy.conf > $POLICY_DIR/exception_policy
    [ $TOMOYO_NOLOAD -eq 0 -a -r domain_policy.conf -a -w $POLICY_DIR/domain_policy ] && cat domain_policy.conf > $POLICY_DIR/domain_policy
    if [ "x$PROFILE" = "xdefault" ]; then
	[ -r profile.conf ] && cat profile.conf > $POLICY_DIR/profile
    elif [ "x$PROFILE" != "xdisable" ]; then
	[ -r profile-$PROFILE.conf ] && cat profile-$PROFILE.conf > $POLICY_DIR/profile
    fi
fi

# Use disabled mode?
if [ "x$PROFILE" = "xdisable" ]; then
    for i in `seq 0 255`; do echo $i-COMMENT= ; done > $POLICY_DIR/profile
    grep -vF -- -COMMENT= $POLICY_DIR/profile | sed -e 's/[0-9]*$/0/' > $POLICY_DIR/profile
fi

# Disable verbose mode?
if [ $TOMOYO_QUIET -eq 1 ]; then
    grep -F TOMOYO_VERBOSE $POLICY_DIR/profile | sed -e 's/[0-9]*$/0/' > $POLICY_DIR/profile
fi

# Do additional initialization.
[ -x /etc/tomoyo/tomoyo-post-init ] && /etc/tomoyo/tomoyo-post-init

[ -r $POLICY_DIR/domain_policy ] && awk ' BEGIN { domain=0; acl=0; } { if ( $1 == "<kernel>" ) domain++; else if ( $1 != "" && $1 != "use_profile") acl++; } END { print domain " domains. " acl " ACL entries."; } ' $POLICY_DIR/domain_policy

# Show memory usage.
awk ' BEGIN { shared_mem=0; private_mem=0; } { if ( $1 == "Shared:" ) shared_mem = $2 / 1024; else if ( $1 == "Private:" ) private_mem = $2 / 1024; } END { print shared_mem " KB shared. " private_mem " KB private."; } ' $POLICY_DIR/meminfo

# [ $SECURITY_UNMOUNT -eq 1 ] && umount -n /sys/kernel/security
# [ $SYS_UNMOUNT -eq 1 ] && umount -n /sys
[ $PROC_UNMOUNT -eq 1 ] && umount -n /proc
exit 0
