* [PATCH] ACM: adding get_ssid command and cleanup
@ 2005-09-02 3:26 Reiner Sailer
2005-09-02 18:41 ` [Xense-devel] " David Palmer
0 siblings, 1 reply; 5+ messages in thread
From: Reiner Sailer @ 2005-09-02 3:26 UTC (permalink / raw)
To: xen-devel; +Cc: Stefan Berger, xense-devel
[-- Attachment #1.1: Type: text/plain, Size: 865 bytes --]
This patch:
* adds a get_ssid ACM command that allows privileged domains to retrieve
types for either a given ssid reference or a given domain id (of a running
domain); this command can be used to extend access control into device
domains, e.g., to control network traffic currently moving through Domain
0 uncontrolled by the ACM policy
* adds a script getlabel.sh that allows users inside Dom0 to retrieve the
label for a given ssid reference or a given domain id (multiple labels
might map onto a single ssid reference)
* cleans up label-related code in tools/security by merging common
functions into labelfuncs.sh
* cleans up ACM code related to above changes (eventually approximating a
common coding style)
Comments welcome.
Thanks
Reiner
Signed-off-by Reiner Sailer <sailer@us.ibm.com>
Signed-off by Stefan Berger <stefanb@us.ibm.com>
[-- Attachment #1.2: Type: text/html, Size: 1256 bytes --]
[-- Attachment #2: get_ssid.diff --]
[-- Type: application/octet-stream, Size: 67807 bytes --]
tools/security/Makefile | 1
tools/security/getlabel.sh | 130 +++++
tools/security/labelfuncs.sh | 675 ++++++++++++++++++++++++++++
tools/security/secpol_tool.c | 138 +++++
tools/security/setlabel.sh | 313 ++----------
xen/acm/acm_chinesewall_hooks.c | 23
xen/acm/acm_core.c | 146 +++---
xen/acm/acm_null_hooks.c | 13
xen/acm/acm_policy.c | 122 +++--
xen/acm/acm_simple_type_enforcement_hooks.c | 42 +
xen/common/acm_ops.c | 33 +
xen/include/acm/acm_core.h | 9
xen/include/acm/acm_hooks.h | 1
xen/include/public/acm.h | 32 -
xen/include/public/acm_ops.h | 17
15 files changed, 1317 insertions(+), 378 deletions(-)
Index: xen-unstable.hg-shype/tools/security/Makefile
===================================================================
--- xen-unstable.hg-shype.orig/tools/security/Makefile
+++ xen-unstable.hg-shype/tools/security/Makefile
@@ -45,6 +45,7 @@ build: mk-symlinks
$(MAKE) secpol_xml2bin
chmod 700 ./setlabel.sh
chmod 700 ./updategrub.sh
+ chmod 700 ./getlabel.sh
secpol_tool : secpol_tool.c secpol_compat.h
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<
Index: xen-unstable.hg-shype/tools/security/getlabel.sh
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/security/getlabel.sh
@@ -0,0 +1,130 @@
+#!/bin/sh
+# *
+# * getlabel
+# *
+# * Copyright (C) 2005 IBM Corporation
+# *
+# * Authors:
+# * Stefan Berger <stefanb@us.ibm.com>
+# *
+# * This program is free software; you can redistribute it and/or
+# * modify it under the terms of the GNU General Public License as
+# * published by the Free Software Foundation, version 2 of the
+# * License.
+# *
+# * 'getlabel' tries to find the labels corresponding to the ssidref
+# *
+# * 'getlabel -?' shows the usage of the program
+# *
+# * 'getlabel -sid <ssidref> [<policy name>]' lists the label corresponding
+# * to the given ssidref.
+# *
+# * 'getlabel -dom <domain id> [<policy name>]' lists the label of the
+# * domain with given id
+# *
+#
+
+if [ -z "$runbash" ]; then
+ runbash="1"
+ export runbash
+ exec sh -c "bash $0 $*"
+fi
+
+
+export PATH=$PATH:.
+source labelfuncs.sh
+
+usage ()
+{
+ echo "Usage: $0 -sid <ssidref> [<policy name>] or"
+ echo " $0 -dom <domid> [<policy name>] "
+ echo ""
+ echo "policy name : the name of the policy, i.e. 'chwall'"
+ echo " If the policy name is omitted, the grub.conf"
+ echo " entry of the running system is tried to be read"
+ echo " and the policy name determined from there."
+ echo "ssidref : an ssidref in hex or decimal format, i.e., '0x00010002'"
+ echo " or '65538'"
+ echo "domid : id of the domain, i.e., '1'; Use numbers from the 2nd"
+ echo " column shown when invoking 'xm list'"
+ echo ""
+}
+
+
+
+if [ "$1" == "-?" ]; then
+ mode="usage"
+elif [ "$1" == "-dom" ]; then
+ mode="domid"
+ shift
+elif [ "$1" == "-sid" ]; then
+ mode="sid"
+ shift
+elif [ "$1" == "" ]; then
+ usage
+ exit -1
+fi
+
+
+if [ "$mode" == "usage" ]; then
+ usage
+elif [ "$mode" == "domid" ]; then
+ if [ "$2" == "" ]; then
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+ else
+ policy=$2
+ fi
+ findMapFile $policy
+ res=$?
+ if [ "$res" != "0" ]; then
+ getSSIDUsingSecpolTool $1
+ res=$?
+ if [ "$res" != "0" ]; then
+ translateSSIDREF $ssid $mapfile
+ else
+ echo "Could not determine the SSID of the domain."
+ fi
+ else
+ echo "Could not find map file for policy '$policy'."
+ fi
+elif [ "$mode" == "sid" ]; then
+ if [ "$2" == "" ]; then
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+ else
+ policy=$2
+ fi
+ findMapFile $policy
+ res=$?
+ if [ "$res" != "0" ]; then
+ translateSSIDREF $1 $mapfile
+ else
+ echo "Could not find map file for policy '$policy'."
+ fi
+
+else
+ usage
+fi
Index: xen-unstable.hg-shype/tools/security/labelfuncs.sh
===================================================================
--- /dev/null
+++ xen-unstable.hg-shype/tools/security/labelfuncs.sh
@@ -0,0 +1,675 @@
+# *
+# * labelfuncs.sh
+# *
+# * Copyright (C) 2005 IBM Corporation
+# *
+# * Authors:
+# * Stefan Berger <stefanb@us.ibm.com>
+# *
+# * This program is free software; you can redistribute it and/or
+# * modify it under the terms of the GNU General Public License as
+# * published by the Free Software Foundation, version 2 of the
+# * License.
+# *
+# *
+# * A collection of functions to handle polcies, mapfiles,
+# * and ssidrefs.
+#
+
+
+# Find the mapfile given a policy nmame
+# Parameters:
+# 1st : the name of the policy whose map file is to be found, i.e.,
+# chwall
+# Results:
+# The variable mapfile will hold the realtive path to the mapfile
+# for the given policy.
+# In case the mapfile could be found, the functions returns a '1',
+# a '0' otherwise.
+findMapFile ()
+{
+ mapfile="./$1.map"
+ if [ -r "$mapfile" ]; then
+ return 1
+ fi
+
+ mapfile="./policies/$1/$1.map"
+ if [ -r "$mapfile" ]; then
+ return 1
+ fi
+
+ return 0
+}
+
+
+# Determine the name of the primary policy
+# Parameters
+# 1st : the path to the mapfile; the path may be relative
+# to the current directory
+# Results
+# The variable primary will hold the name of the primary policy
+getPrimaryPolicy ()
+{
+ mapfile=$1
+ primary=`cat $mapfile | \
+ awk ' \
+ { \
+ if ( $1 == "PRIMARY" ) { \
+ res=$2; \
+ } \
+ } END { \
+ print res; \
+ } '`
+}
+
+
+# Determine the name of the secondary policy
+# Parameters
+# 1st : the path to the mapfile; the path may be relative
+# to the current directory
+# Results
+# The variable secondary will hold the name of the secondary policy
+getSecondaryPolicy ()
+{
+ mapfile=$1
+ secondary=`cat $mapfile | \
+ awk ' \
+ { \
+ if ( $1 == "SECONDARY" ) { \
+ res=$2; \
+ } \
+ } END { \
+ print res; \
+ } '`
+}
+
+
+#Return where the grub.conf file is.
+#I only know of one place it can be.
+findGrubConf()
+{
+ grubconf="/boot/grub/grub.conf"
+ if [ -w $grubconf ]; then
+ return 1
+ fi
+ if [ -r $grubconf ]; then
+ return 2
+ fi
+ return 0
+}
+
+
+# This function sets the global variable 'linux'
+# to the name and version of the Linux kernel that was compiled
+# for domain 0.
+# If this variable could not be found, the variable 'linux'
+# will hold a pattern
+# Parameters:
+# 1st: the path to reach the root directory of the XEN build tree
+# where linux-*-xen0 is located at
+# Results:
+# The variable linux holds then name and version of the compiled
+# kernel, i.e., 'vmlinuz-2.6.12-xen0'
+getLinuxVersion ()
+{
+ path=$1
+ linux=""
+ for f in $path/linux-*-xen0 ; do
+ versionfile=$f/include/linux/version.h
+ if [ -r $versionfile ]; then
+ lnx=`cat $versionfile | \
+ grep UTS_RELEASE | \
+ awk '{ \
+ len=length($3); \
+ print substr($3,2,len-2) }'`
+ fi
+ if [ "$lnx" != "" ]; then
+ linux="[./0-9a-zA-z]*$lnx"
+ return;
+ fi
+ done
+
+ #Last resort.
+ linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$"
+}
+
+
+# Find out with which policy the hypervisor was booted with.
+# Parameters
+# 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf
+#
+findPolicyInGrub ()
+{
+ grubconf=$1
+ linux=`uname -r`
+ policy=`cat $grubconf | \
+ awk -vlinux=$linux '{ \
+ if ( $1 == "title" ) { \
+ kernelfound = 0; \
+ policymaycome = 0; \
+ } \
+ else if ( $1 == "kernel" ) { \
+ if ( match($2,"xen.gz$") ) { \
+ pathlen=RSTART; \
+ kernelfound = 1; \
+ } \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ match($2,linux) ) { \
+ policymaycome = 1; \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ policymaycome == 1 && \
+ match($2,"[0-9a-zA-Z_]*.bin$") ) { \
+ policymaycome = 0; \
+ kernelfound = 0; \
+ polname = substr($2,pathlen); \
+ len=length(polname); \
+ polname = substr(polname,0,len-4); \
+ } \
+ } END { \
+ print polname \
+ }'`
+}
+
+
+# Get the SSID of a domain
+# Parameters:
+# 1st : domain ID, i.e. '1'
+# Results
+# If the ssid could be found, the variable 'ssid' will hold
+# the currently used ssid in the hex format, i.e., '0x00010001'.
+# The funtion returns '1' on success, '0' on failure
+getSSIDUsingSecpolTool ()
+{
+ domid=$1
+ export PATH=$PATH:.
+ ssid=`secpol_tool getssid -d $domid -f | \
+ grep -E "SSID:" | \
+ awk '{ print $4 }'`
+
+ if [ "$ssid" != "" ]; then
+ return 1
+ fi
+ return 0
+}
+
+
+# Break the ssid identifier into its high and low values,
+# which are equal to the secondary and primary policy references.
+# Parameters:
+# 1st: ssid to break into high and low value, i.e., '0x00010002'
+# Results:
+# The variable ssidlo_int and ssidhi_int will hold the low and
+# high ssid values as integers.
+getSSIDLOHI ()
+{
+ ssid=$1
+ ssidlo_int=`echo $ssid | awk \
+ '{ \
+ len=length($0); \
+ beg=substr($0,1,2); \
+ if ( beg == "0x" ) { \
+ dig = len - 2; \
+ if (dig <= 0) { \
+ exit; \
+ } \
+ if (dig > 4) { \
+ dig=4; \
+ } \
+ lo=sprintf("0x%s",substr($0,len-dig+1,dig)); \
+ print strtonum(lo);\
+ } else { \
+ lo=strtonum($0); \
+ if (lo < 65536) { \
+ print lo; \
+ } else { \
+ hi=lo; \
+ hi2= (hi / 65536);\
+ hi2_str=sprintf("%d",hi2); \
+ hi2=strtonum(hi2_str);\
+ lo=hi-(hi2*65536); \
+ printf("%d",lo); \
+ } \
+ } \
+ }'`
+ ssidhi_int=`echo $ssid | awk \
+ '{ \
+ len=length($0); \
+ beg=substr($0,1,2); \
+ if ( beg == "0x" ) { \
+ dig = len - 2; \
+ if (dig <= 0 || \
+ dig > 8) { \
+ exit; \
+ } \
+ if (dig < 4) { \
+ print 0; \
+ exit; \
+ } \
+ dig -= 4; \
+ hi=sprintf("0x%s",substr($0,len-4-dig+1,dig)); \
+ print strtonum(hi);\
+ } else { \
+ hi=strtonum($0); \
+ if (hi >= 65536) { \
+ hi = hi / 65536; \
+ printf ("%d",hi);\
+ } else { \
+ printf ("0"); \
+ } \
+ } \
+ }'`
+ if [ "$ssidhi_int" == "" -o \
+ "$ssidlo_int" == "" ]; then
+ return 0;
+ fi
+ return 1
+}
+
+
+#Update the grub configuration file.
+#Search for existing entries and replace the current
+#policy entry with the policy passed to this script
+#
+#Arguments passed to this function
+# 1st : the grub configuration file with full path
+# 2nd : the binary policy file name, i.e. chwall.bin
+# 3rd : the name or pattern of the linux kernel name to match
+# (this determines where the module entry will be made)
+#
+# The algorithm here is based on pattern matching
+# and is working correctly if
+# - under a title a line beginning with 'kernel' is found
+# whose following item ends with "xen.gz"
+# Example: kernel /xen.gz dom0_mem=....
+# - a module line matching the 3rd parameter is found
+#
+updateGrub ()
+{
+ grubconf=$1
+ policyfile=$2
+ linux=$3
+
+ tmpfile="/tmp/new_grub.conf"
+
+ cat $grubconf | \
+ awk -vpolicy=$policyfile \
+ -vlinux=$linux '{ \
+ if ( $1 == "title" ) { \
+ kernelfound = 0; \
+ if ( policymaycome == 1 ){ \
+ printf ("\tmodule %s%s\n", path, policy); \
+ } \
+ policymaycome = 0; \
+ } \
+ else if ( $1 == "kernel" ) { \
+ if ( match($2,"xen.gz$") ) { \
+ path=substr($2,1,RSTART-1); \
+ kernelfound = 1; \
+ } \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ match($2,linux) ) { \
+ policymaycome = 1; \
+ } \
+ else if ( $1 == "module" && \
+ kernelfound == 1 && \
+ policymaycome == 1 && \
+ match($2,"[0-9a-zA-Z]*.bin$") ) { \
+ printf ("\tmodule %s%s\n", path, policy); \
+ policymaycome = 0; \
+ kernelfound = 0; \
+ dontprint = 1; \
+ } \
+ else if ( $1 == "" && \
+ kernelfound == 1 && \
+ policymaycome == 1) { \
+ dontprint = 1; \
+ } \
+ if (dontprint == 0) { \
+ printf ("%s\n", $0); \
+ } \
+ dontprint = 0; \
+ } END { \
+ if ( policymaycome == 1 ) { \
+ printf ("\tmodule %s%s\n", path, policy); \
+ } \
+ }' > $tmpfile
+ if [ ! -r $tmpfile ]; then
+ echo "Could not create temporary file! Aborting."
+ exit -1
+ fi
+ mv -f $tmpfile $grubconf
+}
+
+
+# Display all the labels in a given mapfile
+# Parameters
+# 1st: Full or relative path to the policy's mapfile
+showLabels ()
+{
+ mapfile=$1
+ if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
+ echo "Cannot read from vm configuration file $vmfile."
+ return -1
+ fi
+
+ getPrimaryPolicy $mapfile
+ getSecondaryPolicy $mapfile
+
+ echo "The following labels are available:"
+ let line=1
+ while [ 1 ]; do
+ ITEM=`cat $mapfile | \
+ awk -vline=$line \
+ -vprimary=$primary \
+ '{ \
+ if ($1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == primary ) { \
+ ctr++; \
+ if (ctr == line) { \
+ print $4; \
+ } \
+ } \
+ } END { \
+ }'`
+
+ if [ "$ITEM" == "" ]; then
+ break
+ fi
+ if [ "$secondary" != "NULL" ]; then
+ LABEL=`cat $mapfile | \
+ awk -vitem=$ITEM \
+ '{
+ if ($1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == "CHWALL" && \
+ $4 == item ) { \
+ result = item; \
+ } \
+ } END { \
+ print result \
+ }'`
+ else
+ LABEL=$ITEM
+ fi
+
+ if [ "$LABEL" != "" ]; then
+ echo "$LABEL"
+ found=1
+ fi
+ let line=line+1
+ done
+ if [ "$found" != "1" ]; then
+ echo "No labels found."
+ fi
+}
+
+
+# Get the default SSID given a mapfile and the policy name
+# Parameters
+# 1st: Full or relative path to the policy's mapfile
+# 2nd: the name of the policy
+getDefaultSsid ()
+{
+ mapfile=$1
+ pol=$2
+ RES=`cat $mapfile \
+ awk -vpol=$pol \
+ { \
+ if ($1 == "LABEL->SSID" && \
+ $2 == "ANY" && \
+ $3 == pol && \
+ $4 == "DEFAULT" ) {\
+ res=$5; \
+ } \
+ } END { \
+ printf "%04x", strtonum(res) \
+ }'`
+ echo "default NULL mapping is $RES"
+ defaultssid=$RES
+}
+
+
+#Relabel a VM configuration file
+# Parameters
+# 1st: Full or relative path to the VM configuration file
+# 2nd: The label to translate into an ssidref
+# 3rd: Full or relative path to the policy's map file
+# 4th: The mode this function is supposed to operate in:
+# 'relabel' : Relabels the file without querying the user
+# other : Prompts the user whether to proceed
+relabel ()
+{
+ vmfile=$1
+ label=$2
+ mapfile=$3
+ mode=$4
+
+ if [ ! -r "$vmfile" ]; then
+ echo "Cannot read from vm configuration file $vmfile."
+ return -1
+ fi
+
+ if [ ! -w "$vmfile" ]; then
+ echo "Cannot write to vm configuration file $vmfile."
+ return -1
+ fi
+
+ if [ ! -r "$mapfile" ] ; then
+ echo "Cannot read mapping file $mapfile."
+ return -1
+ fi
+
+ # Determine which policy is primary, which sec.
+ getPrimaryPolicy $mapfile
+ getSecondaryPolicy $mapfile
+
+ # Calculate the primary policy's SSIDREF
+ if [ "$primary" == "NULL" ]; then
+ SSIDLO="0001"
+ else
+ SSIDLO=`cat $mapfile | \
+ awk -vlabel=$label \
+ -vprimary=$primary \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == primary && \
+ $4 == label ) { \
+ result=$5 \
+ } \
+ } END { \
+ if (result != "" ) \
+ {printf "%04x", strtonum(result)}\
+ }'`
+ fi
+
+ # Calculate the secondary policy's SSIDREF
+ if [ "$secondary" == "NULL" ]; then
+ if [ "$primary" == "NULL" ]; then
+ SSIDHI="0001"
+ else
+ SSIDHI="0000"
+ fi
+ else
+ SSIDHI=`cat $mapfile | \
+ awk -vlabel=$label \
+ -vsecondary=$secondary \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $2 == "VM" && \
+ $3 == secondary && \
+ $4 == label ) { \
+ result=$5 \
+ } \
+ } END { \
+ if (result != "" ) \
+ {printf "%04x", strtonum(result)}\
+ }'`
+ fi
+
+ if [ "$SSIDLO" == "" -o \
+ "$SSIDHI" == "" ]; then
+ echo "Could not map the given label '$label'."
+ return -1
+ fi
+
+ ACM_POLICY=`cat $mapfile | \
+ awk ' { if ( $1 == "POLICY" ) { \
+ result=$2 \
+ } \
+ } \
+ END { \
+ if (result != "") { \
+ printf result \
+ } \
+ }'`
+
+ if [ "$ACM_POLICY" == "" ]; then
+ echo "Could not find 'POLICY' entry in map file."
+ return -1
+ fi
+
+ SSIDREF="0x$SSIDHI$SSIDLO"
+
+ if [ "$mode" != "relabel" ]; then
+ RES=`cat $vmfile | \
+ awk '{ \
+ if ( substr($1,0,7) == "ssidref" ) {\
+ print $0; \
+ } \
+ }'`
+ if [ "$RES" != "" ]; then
+ echo "Do you want to overwrite the existing mapping ($RES)? (y/N)"
+ read user
+ if [ "$user" != "y" -a "$user" != "Y" ]; then
+ echo "Aborted."
+ return 0
+ fi
+ fi
+ fi
+
+ #Write the output
+ vmtmp1="/tmp/__setlabel.tmp1"
+ vmtmp2="/tmp/__setlabel.tmp2"
+ touch $vmtmp1
+ touch $vmtmp2
+ if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
+ echo "Cannot create temporary files. Aborting."
+ return -1
+ fi
+ RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
+ RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
+ RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
+ echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
+ echo "#ACM_LABEL=$label" >> $vmtmp1
+ echo "ssidref = $SSIDREF" >> $vmtmp1
+ mv -f $vmtmp1 $vmfile
+ rm -rf $vmtmp1 $vmtmp2
+ echo "Mapped label '$label' to ssidref '$SSIDREF'."
+}
+
+
+# Translate an ssidref into its label. This does the reverse lookup
+# to the relabel function above.
+# This function displays the results.
+# Parameters:
+# 1st: The ssidref to translate; must be in the form '0x00010002'
+# 2nd: Full or relative path to the policy's mapfile
+translateSSIDREF ()
+{
+ ssidref=$1
+ mapfile=$2
+
+ if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
+ echo "Cannot read from vm configuration file $vmfile."
+ return -1
+ fi
+
+ getPrimaryPolicy $mapfile
+ getSecondaryPolicy $mapfile
+
+ if [ "$primary" == "NULL" -a "$secondary" == "NULL" ]; then
+ echo "There are no labels for the NULL policy."
+ return
+ fi
+
+ getSSIDLOHI $ssidref
+ ret=$?
+ if [ $ret -ne 1 ]; then
+ echo "Error while parsing the ssid ref number '$ssidref'."
+ fi;
+
+ let line1=0
+ let line2=0
+ while [ 1 ]; do
+ ITEM1=`cat $mapfile | \
+ awk -vprimary=$primary \
+ -vssidlo=$ssidlo_int \
+ -vline=$line1 \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $3 == primary && \
+ int($5) == ssidlo ) { \
+ if (l == line) { \
+ print $4; \
+ exit; \
+ } \
+ l++; \
+ } \
+ }'`
+
+ ITEM2=`cat $mapfile | \
+ awk -vsecondary=$secondary \
+ -vssidhi=$ssidhi_int \
+ -vline=$line2 \
+ '{ \
+ if ( $1 == "LABEL->SSID" && \
+ $3 == secondary && \
+ int($5) == ssidhi ) { \
+ if (l == line) { \
+ print $4; \
+ exit; \
+ } \
+ l++; \
+ } \
+ }'`
+
+ if [ "$secondary" != "NULL" ]; then
+ if [ "$ITEM1" == "" ]; then
+ let line1=0
+ let line2=line2+1
+ else
+ let line1=line1+1
+ fi
+
+ if [ "$ITEM1" == "" -a \
+ "$ITEM2" == "" ]; then
+ echo "Could not determine the referenced label."
+ break
+ fi
+
+ if [ "$ITEM1" == "$ITEM2" ]; then
+ echo "Label: $ITEM1"
+ break
+ fi
+ else
+ if [ "$ITEM1" != "" ]; then
+ echo "Label: $ITEM1"
+ else
+ if [ "$found" == "0" ]; then
+ found=1
+ else
+ break
+ fi
+ fi
+ let line1=line1+1
+ fi
+ done
+}
Index: xen-unstable.hg-shype/tools/security/secpol_tool.c
===================================================================
--- xen-unstable.hg-shype.orig/tools/security/secpol_tool.c
+++ xen-unstable.hg-shype/tools/security/secpol_tool.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -41,6 +42,17 @@
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
errno, strerror(errno))
+void usage(char *progname)
+{
+ printf("Use: %s \n"
+ "\t getpolicy\n"
+ "\t dumpstats\n"
+ "\t loadpolicy <binary policy file>\n"
+ "\t getssid -d <domainid> [-f]\n"
+ "\t getssid -s <ssidref> [-f]\n", progname);
+ exit(-1);
+}
+
static inline int do_policycmd(int xc_handle, unsigned int cmd,
unsigned long data)
{
@@ -320,7 +332,7 @@ int acm_domain_loadpolicy(int xc_handle,
if (ret)
printf
- ("ERROR setting policy. Use 'xm dmesg' to see details.\n");
+ ("ERROR setting policy. Try 'xm dmesg' to see details.\n");
else
printf("Successfully changed policy.\n");
@@ -370,7 +382,7 @@ int acm_domain_dumpstats(int xc_handle)
if (ret < 0)
{
- printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
+ printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
return ret;
}
stats = (struct acm_stats_buffer *) stats_buffer;
@@ -421,18 +433,122 @@ int acm_domain_dumpstats(int xc_handle)
}
return ret;
}
+/************************ get ssidref & types ******************************/
+/*
+ * the ssid (types) can be looked up either by domain id or by ssidref
+ */
+int acm_domain_getssid(int xc_handle, int argc, char * const argv[])
+{
+ /* this includes header and a set of types */
+ #define MAX_SSIDBUFFER 2000
+ int ret, i;
+ acm_op_t op;
+ struct acm_ssid_buffer *hdr;
+ unsigned char *buf;
+ int nice_print = 1;
-/***************************** main **************************************/
+ op.cmd = ACM_GETSSID;
+ op.interface_version = ACM_INTERFACE_VERSION;
+ op.u.getssid.get_ssid_by = UNSET;
+ /* arguments
+ -d ... domain id to look up
+ -s ... ssidref number to look up
+ -f ... formatted print (scripts depend on this format)
+ */
+ while (1)
+ {
+ int c = getopt(argc, argv, "d:s:f");
+ if (c == -1)
+ break;
+ if (c == 'd')
+ {
+ if (op.u.getssid.get_ssid_by != UNSET)
+ usage(argv[0]);
+ op.u.getssid.get_ssid_by = DOMAINID;
+ op.u.getssid.id.domainid = strtoul(optarg, NULL, 0);
+ }
+ else if (c== 's')
+ {
+ if (op.u.getssid.get_ssid_by != UNSET)
+ usage(argv[0]);
+ op.u.getssid.get_ssid_by = SSIDREF;
+ op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0);
+ }
+ else if (c== 'f')
+ {
+ nice_print = 0;
+ }
+ else
+ usage(argv[0]);
+ }
+ if (op.u.getssid.get_ssid_by == UNSET)
+ usage(argv[0]);
+
+ buf = malloc(MAX_SSIDBUFFER);
+ if (!buf)
+ return -ENOMEM;
+
+ /* dump it and then push it down into xen/acm */
+ op.u.getssid.ssidbuf = buf; /* out */
+ op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER;
+ ret = do_acm_op(xc_handle, &op);
-void usage(char *progname)
-{
- printf("Use: %s \n"
- "\t getpolicy\n"
- "\t dumpstats\n"
- "\t loadpolicy <binary policy file>\n", progname);
- exit(-1);
+ if (ret)
+ {
+ printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n");
+ goto out;
+ }
+ hdr = (struct acm_ssid_buffer *)buf;
+ if (hdr->len > MAX_SSIDBUFFER)
+ {
+ printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n",
+ ret, hdr->len);
+ return -EIO;
+ }
+ if (nice_print)
+ {
+ printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
+ printf(" P: %s, max_types = %d\n",
+ ACM_POLICY_NAME(hdr->primary_policy_code), hdr->primary_max_types);
+ printf(" Types: ");
+ for (i=0; i< hdr->primary_max_types; i++)
+ if (buf[hdr->primary_types_offset + i])
+ printf("%02x ", i);
+ else
+ printf("-- ");
+ printf("\n");
+
+ printf(" S: %s, max_types = %d\n",
+ ACM_POLICY_NAME(hdr->secondary_policy_code), hdr->secondary_max_types);
+ printf(" Types: ");
+ for (i=0; i< hdr->secondary_max_types; i++)
+ if (buf[hdr->secondary_types_offset + i])
+ printf("%02x ", i);
+ else
+ printf("-- ");
+ printf("\n");
+ }
+ else
+ {
+ /* formatted print for use with scripts (.sh)
+ * update scripts when updating here (usually
+ * used in combination with -d to determine a
+ * running domain's label
+ */
+ printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
+ }
+
+ /* return ste ssidref */
+ if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ ret = (hdr->ssidref) & 0xffff;
+ else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ ret = (hdr->ssidref) >> 16;
+ out:
+ return ret;
}
+/***************************** main **************************************/
+
int main(int argc, char **argv)
{
@@ -459,6 +575,8 @@ int main(int argc, char **argv)
if (argc != 2)
usage(argv[0]);
ret = acm_domain_dumpstats(acm_cmd_fd);
+ } else if (!strcmp(argv[1], "getssid")) {
+ ret = acm_domain_getssid(acm_cmd_fd, argc, argv);
} else
usage(argv[0]);
Index: xen-unstable.hg-shype/tools/security/setlabel.sh
===================================================================
--- xen-unstable.hg-shype.orig/tools/security/setlabel.sh
+++ xen-unstable.hg-shype/tools/security/setlabel.sh
@@ -34,277 +34,29 @@ if [ -z "$runbash" ]; then
exec sh -c "bash $0 $*"
fi
+export PATH=$PATH:.
+source labelfuncs.sh
usage ()
{
- echo "Usage: $0 [Option] <vmfile> <label> <policy name> "
- echo " or $0 -l <policy name>"
+ echo "Usage: $0 [Option] <vmfile> <label> [<policy name>]"
+ echo " or $0 -l [<policy name>]"
echo ""
- echo "Valid Options are:"
+ echo "Valid options are:"
echo "-r : to relabel a file without being prompted"
echo ""
echo "vmfile : XEN vm configuration file"
- echo "label : the label to map"
+ echo "label : the label to map to an ssidref"
echo "policy name : the name of the policy, i.e. 'chwall'"
+ echo " If the policy name is omitted, it is attempted"
+ echo " to find the current policy's name in grub.conf."
echo ""
- echo "-l <policy name> is used to show valid labels in the map file"
+ echo "-l [<policy name>] is used to show valid labels in the map file of"
+ echo " the given or current policy."
echo ""
}
-findMapFile ()
-{
- mapfile="./$1.map"
- if [ -r "$mapfile" ]; then
- return 1
- fi
-
- mapfile="./policies/$1/$1.map"
- if [ -r "$mapfile" ]; then
- return 1
- fi
-
- return 0
-}
-
-showLabels ()
-{
- mapfile=$1
- if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
- echo "Cannot read from vm configuration file $vmfile."
- return -1
- fi
-
- getPrimaryPolicy $mapfile
- getSecondaryPolicy $mapfile
-
- echo "The following labels are available:"
- let line=1
- while [ 1 ]; do
- ITEM=`cat $mapfile | \
- awk -vline=$line \
- -vprimary=$primary \
- '{ \
- if ($1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == primary ) { \
- ctr++; \
- if (ctr == line) { \
- print $4; \
- } \
- } \
- } END { \
- }'`
-
- if [ "$ITEM" == "" ]; then
- break
- fi
- if [ "$secondary" != "NULL" ]; then
- LABEL=`cat $mapfile | \
- awk -vitem=$ITEM \
- '{
- if ($1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == "CHWALL" && \
- $4 == item ) { \
- result = item; \
- } \
- } END { \
- print result \
- }'`
- else
- LABEL=$ITEM
- fi
-
- if [ "$LABEL" != "" ]; then
- echo "$LABEL"
- found=1
- fi
- let line=line+1
- done
- if [ "$found" != "1" ]; then
- echo "No labels found."
- fi
-}
-
-getPrimaryPolicy ()
-{
- mapfile=$1
- primary=`cat $mapfile | \
- awk ' \
- { \
- if ( $1 == "PRIMARY" ) { \
- res=$2; \
- } \
- } END { \
- print res; \
- } '`
-}
-
-getSecondaryPolicy ()
-{
- mapfile=$1
- secondary=`cat $mapfile | \
- awk ' \
- { \
- if ( $1 == "SECONDARY" ) { \
- res=$2; \
- } \
- } END { \
- print res; \
- } '`
-}
-
-
-getDefaultSsid ()
-{
- mapfile=$1
- pol=$2
- RES=`cat $mapfile \
- awk -vpol=$pol \
- { \
- if ($1 == "LABEL->SSID" && \
- $2 == "ANY" && \
- $3 == pol && \
- $4 == "DEFAULT" ) {\
- res=$5; \
- } \
- } END { \
- printf "%04x", strtonum(res) \
- }'`
- echo "default NULL mapping is $RES"
- defaultssid=$RES
-}
-
-relabel ()
-{
- vmfile=$1
- label=$2
- mapfile=$3
- mode=$4
-
- if [ ! -r "$vmfile" ]; then
- echo "Cannot read from vm configuration file $vmfile."
- return -1
- fi
-
- if [ ! -w "$vmfile" ]; then
- echo "Cannot write to vm configuration file $vmfile."
- return -1
- fi
-
- if [ ! -r "$mapfile" ] ; then
- echo "Cannot read mapping file $mapfile."
- return -1
- fi
-
- # Determine which policy is primary, which sec.
- getPrimaryPolicy $mapfile
- getSecondaryPolicy $mapfile
-
- # Calculate the primary policy's SSIDREF
- if [ "$primary" == "NULL" ]; then
- SSIDLO="0000"
- else
- SSIDLO=`cat $mapfile | \
- awk -vlabel=$label \
- -vprimary=$primary \
- '{ \
- if ( $1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == primary && \
- $4 == label ) { \
- result=$5 \
- } \
- } END { \
- if (result != "" ) \
- {printf "%04x", strtonum(result)}\
- }'`
- fi
-
- # Calculate the secondary policy's SSIDREF
- if [ "$secondary" == "NULL" ]; then
- SSIDHI="0000"
- else
- SSIDHI=`cat $mapfile | \
- awk -vlabel=$label \
- -vsecondary=$secondary \
- '{ \
- if ( $1 == "LABEL->SSID" && \
- $2 == "VM" && \
- $3 == secondary && \
- $4 == label ) { \
- result=$5 \
- } \
- } END { \
- if (result != "" ) \
- {printf "%04x", strtonum(result)}\
- }'`
- fi
-
- if [ "$SSIDLO" == "" -o \
- "$SSIDHI" == "" ]; then
- echo "Could not map the given label '$label'."
- return -1
- fi
-
- ACM_POLICY=`cat $mapfile | \
- awk ' { if ( $1 == "POLICY" ) { \
- result=$2 \
- } \
- } \
- END { \
- if (result != "") { \
- printf result \
- } \
- }'`
-
- if [ "$ACM_POLICY" == "" ]; then
- echo "Could not find 'POLICY' entry in map file."
- return -1
- fi
-
- SSIDREF="0x$SSIDHI$SSIDLO"
-
- if [ "$mode" != "relabel" ]; then
- RES=`cat $vmfile | \
- awk '{ \
- if ( substr($1,0,7) == "ssidref" ) {\
- print $0; \
- } \
- }'`
- if [ "$RES" != "" ]; then
- echo "Do you want to overwrite the existing mapping ($RES)? (y/N)"
- read user
- if [ "$user" != "y" -a "$user" != "Y" ]; then
- echo "Aborted."
- return 0
- fi
- fi
- fi
-
- #Write the output
- vmtmp1="/tmp/__setlabel.tmp1"
- vmtmp2="/tmp/__setlabel.tmp2"
- touch $vmtmp1
- touch $vmtmp2
- if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
- echo "Cannot create temporary files. Aborting."
- return -1
- fi
- RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
- RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
- RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
- echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
- echo "#ACM_LABEL=$label" >> $vmtmp1
- echo "ssidref = $SSIDREF" >> $vmtmp1
- mv -f $vmtmp1 $vmfile
- rm -rf $vmtmp1 $vmtmp2
- echo "Mapped label '$label' to ssidref '$SSIDREF'."
-}
-
-
-
if [ "$1" == "-r" ]; then
mode="relabel"
shift
@@ -317,10 +69,25 @@ fi
if [ "$mode" == "show" ]; then
if [ "$1" == "" ]; then
- usage
- exit -1;
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+ else
+ policy=$3;
fi
- findMapFile $1
+
+
+ findMapFile $policy
res=$?
if [ "$res" != "0" ]; then
showLabels $mapfile
@@ -330,11 +97,29 @@ if [ "$mode" == "show" ]; then
elif [ "$mode" == "usage" ]; then
usage
else
- if [ "$3" == "" ]; then
+ if [ "$2" == "" ]; then
usage
- exit -1;
+ exit -1
+ fi
+ if [ "$3" == "" ]; then
+ findGrubConf
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "Could not find grub.conf"
+ exit -1;
+ fi
+ findPolicyInGrub $grubconf
+ if [ "$policy" != "" ]; then
+ echo "Assuming policy to be '$policy'.";
+ else
+ echo "Could not find policy."
+ exit -1;
+ fi
+
+ else
+ policy=$3;
fi
- findMapFile $3
+ findMapFile $policy
res=$?
if [ "$res" != "0" ]; then
relabel $1 $2 $mapfile $mode
Index: xen-unstable.hg-shype/xen/acm/acm_chinesewall_hooks.c
===================================================================
--- xen-unstable.hg-shype.orig/xen/acm/acm_chinesewall_hooks.c
+++ xen-unstable.hg-shype/xen/acm/acm_chinesewall_hooks.c
@@ -310,6 +310,28 @@ chwall_dump_stats(u8 *buf, u16 len)
return 0;
}
+static int
+chwall_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
+{
+ int i;
+
+ /* fill in buffer */
+ if (chwall_bin_pol.max_types > len)
+ return -EFAULT;
+
+ if (ssidref >= chwall_bin_pol.max_ssidrefs)
+ return -EFAULT;
+
+ /* read types for chwall ssidref */
+ for(i=0; i< chwall_bin_pol.max_types; i++) {
+ if (chwall_bin_pol.ssidrefs[ssidref * chwall_bin_pol.max_types + i])
+ buf[i] = 1;
+ else
+ buf[i] = 0;
+ }
+ return chwall_bin_pol.max_types;
+}
+
/***************************
* Authorization functions
***************************/
@@ -492,6 +514,7 @@ struct acm_operations acm_chinesewall_op
.dump_binary_policy = chwall_dump_policy,
.set_binary_policy = chwall_set_policy,
.dump_statistics = chwall_dump_stats,
+ .dump_ssid_types = chwall_dump_ssid_types,
/* domain management control hooks */
.pre_domain_create = chwall_pre_domain_create,
.post_domain_create = chwall_post_domain_create,
Index: xen-unstable.hg-shype/xen/acm/acm_core.c
===================================================================
--- xen-unstable.hg-shype.orig/xen/acm/acm_core.c
+++ xen-unstable.hg-shype/xen/acm/acm_core.c
@@ -64,17 +64,18 @@ u8 little_endian = 1;
void acm_set_endian(void)
{
u32 test = 1;
- if (*((u8 *)&test) == 1) {
+ if (*((u8 *)&test) == 1)
+ {
printk("ACM module running in LITTLE ENDIAN.\n");
- little_endian = 1;
- } else {
- printk("ACM module running in BIG ENDIAN.\n");
- little_endian = 0;
+ little_endian = 1;
+ }
+ else
+ {
+ printk("ACM module running in BIG ENDIAN.\n");
+ little_endian = 0;
}
}
-#if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
-
/* initialize global security policy for Xen; policy write-locked already */
static void
acm_init_binary_policy(void *primary, void *secondary)
@@ -101,7 +102,8 @@ acm_setup(unsigned int *initrdidx,
* Try all modules and see whichever could be the binary policy.
* Adjust the initrdidx if module[1] is the binary policy.
*/
- for (i = mbi->mods_count-1; i >= 1; i--) {
+ for (i = mbi->mods_count-1; i >= 1; i--)
+ {
struct acm_policy_buffer *pol;
char *_policy_start;
unsigned long _policy_len;
@@ -117,23 +119,32 @@ acm_setup(unsigned int *initrdidx,
continue; /* not a policy */
pol = (struct acm_policy_buffer *)_policy_start;
- if (ntohl(pol->magic) == ACM_MAGIC) {
+ if (ntohl(pol->magic) == ACM_MAGIC)
+ {
rc = acm_set_policy((void *)_policy_start,
(u16)_policy_len,
0);
- if (rc == ACM_OK) {
+ if (rc == ACM_OK)
+ {
printf("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
- if (i == 1) {
- if (mbi->mods_count > 2) {
+ if (i == 1)
+ {
+ if (mbi->mods_count > 2)
+ {
*initrdidx = 2;
- } else {
+ }
+ else {
*initrdidx = 0;
}
- } else {
+ }
+ else
+ {
*initrdidx = 1;
}
break;
- } else {
+ }
+ else
+ {
printk("Invalid policy. %d.th module line.\n", i+1);
}
} /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
@@ -147,57 +158,85 @@ acm_init(unsigned int *initrdidx,
const multiboot_info_t *mbi,
unsigned long initial_images_start)
{
- int ret = -EINVAL;
+ int ret = ACM_OK;
- acm_set_endian();
+ acm_set_endian();
write_lock(&acm_bin_pol_rwlock);
+ acm_init_binary_policy(NULL, NULL);
- if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) {
- acm_init_binary_policy(NULL, NULL);
- acm_init_chwall_policy();
+ /* set primary policy component */
+ switch ((ACM_USE_SECURITY_POLICY) & 0x0f)
+ {
+
+ case ACM_CHINESE_WALL_POLICY:
+ acm_init_chwall_policy();
acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
acm_primary_ops = &acm_chinesewall_ops;
- acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
- acm_secondary_ops = &acm_null_ops;
- ret = ACM_OK;
- } else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
- acm_init_binary_policy(NULL, NULL);
- acm_init_ste_policy();
+ break;
+
+ case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+ acm_init_ste_policy();
acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
acm_primary_ops = &acm_simple_type_enforcement_ops;
+ break;
+
+ default:
+ /* NULL or Unknown policy not allowed primary;
+ * NULL/NULL will not compile this code */
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* secondary policy component part */
+ switch ((ACM_USE_SECURITY_POLICY) >> 4) {
+ case ACM_NULL_POLICY:
acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
acm_secondary_ops = &acm_null_ops;
- ret = ACM_OK;
- } else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
- acm_init_binary_policy(NULL, NULL);
+ break;
+
+ case ACM_CHINESE_WALL_POLICY:
+ if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
+ { /* not a valid combination */
+ ret = -EINVAL;
+ goto out;
+ }
acm_init_chwall_policy();
+ acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
+ acm_secondary_ops = &acm_chinesewall_ops;
+ break;
+
+ case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+ if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ { /* not a valid combination */
+ ret = -EINVAL;
+ goto out;
+ }
acm_init_ste_policy();
- acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
- acm_primary_ops = &acm_chinesewall_ops;
acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
acm_secondary_ops = &acm_simple_type_enforcement_ops;
- ret = ACM_OK;
- } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) {
- acm_init_binary_policy(NULL, NULL);
- acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
- acm_primary_ops = &acm_null_ops;
- acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
- acm_secondary_ops = &acm_null_ops;
- ret = ACM_OK;
- }
+ break;
+
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ out:
write_unlock(&acm_bin_pol_rwlock);
if (ret != ACM_OK)
- return -EINVAL;
+ {
+ printk("%s: Error setting policies.\n", __func__);
+ /* here one could imagine a clean panic */
+ return -EINVAL;
+ }
acm_setup(initrdidx, mbi, initial_images_start);
printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__,
- ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
+ ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
+ ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
return ret;
}
-
-#endif
-
int
acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
{
@@ -205,7 +244,8 @@ acm_init_domain_ssid(domid_t id, ssidref
struct domain *subj = find_domain_by_id(id);
int ret1, ret2;
- if (subj == NULL) {
+ if (subj == NULL)
+ {
printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
return ACM_NULL_POINTER_ERROR;
}
@@ -235,14 +275,16 @@ acm_init_domain_ssid(domid_t id, ssidref
else
ret2 = ACM_OK;
- if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) {
+ if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
+ {
printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
__func__, subj->domain_id);
acm_free_domain_ssid(ssid);
put_domain(subj);
return ACM_INIT_SSID_ERROR;
}
- printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref);
+ printk("%s: assigned domain %x the ssidref=%x.\n",
+ __func__, id, ssid->ssidref);
put_domain(subj);
return ACM_OK;
}
@@ -254,11 +296,12 @@ acm_free_domain_ssid(struct acm_ssid_dom
domid_t id;
/* domain is already gone, just ssid is left */
- if (ssid == NULL) {
+ if (ssid == NULL)
+ {
printk("%s: ACM_NULL_POINTER ERROR.\n", __func__);
return ACM_NULL_POINTER_ERROR;
}
- id = ssid->domainid;
+ id = ssid->domainid;
ssid->subject = NULL;
if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
@@ -268,6 +311,7 @@ acm_free_domain_ssid(struct acm_ssid_dom
acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
ssid->secondary_ssid = NULL;
xfree(ssid);
- printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id);
+ printkd("%s: Freed individual domain ssid (domain=%02x).\n",
+ __func__, id);
return ACM_OK;
}
Index: xen-unstable.hg-shype/xen/acm/acm_null_hooks.c
===================================================================
--- xen-unstable.hg-shype.orig/xen/acm/acm_null_hooks.c
+++ xen-unstable.hg-shype/xen/acm/acm_null_hooks.c
@@ -14,13 +14,13 @@
#include <acm/acm_hooks.h>
static int
-null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
+null_init_domain_ssid(void **ssid, ssidref_t ssidref)
{
return ACM_OK;
}
static void
-null_free_domain_ssid(void *chwall_ssid)
+null_free_domain_ssid(void *ssid)
{
return;
}
@@ -44,6 +44,14 @@ null_dump_stats(u8 *buf, u16 buf_size)
return 0;
}
+static int
+null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size)
+{
+ /* no types */
+ return 0;
+}
+
+
/* now define the hook structure similarly to LSM */
struct acm_operations acm_null_ops = {
.init_domain_ssid = null_init_domain_ssid,
@@ -51,6 +59,7 @@ struct acm_operations acm_null_ops = {
.dump_binary_policy = null_dump_binary_policy,
.set_binary_policy = null_set_binary_policy,
.dump_statistics = null_dump_stats,
+ .dump_ssid_types = null_dump_ssid_types,
/* domain management control hooks */
.pre_domain_create = NULL,
.post_domain_create = NULL,
Index: xen-unstable.hg-shype/xen/acm/acm_policy.c
===================================================================
--- xen-unstable.hg-shype.orig/xen/acm/acm_policy.c
+++ xen-unstable.hg-shype/xen/acm/acm_policy.c
@@ -26,8 +26,8 @@
#include <xen/lib.h>
#include <xen/delay.h>
#include <xen/sched.h>
-#include <public/acm_ops.h>
#include <acm/acm_core.h>
+#include <public/acm_ops.h>
#include <acm/acm_hooks.h>
#include <acm/acm_endian.h>
@@ -37,14 +37,16 @@ acm_set_policy(void *buf, u16 buf_size,
u8 *policy_buffer = NULL;
struct acm_policy_buffer *pol;
- if (buf_size < sizeof(struct acm_policy_buffer))
+ if (buf_size < sizeof(struct acm_policy_buffer))
return -EFAULT;
/* 1. copy buffer from domain */
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
- goto error_free;
+ return -ENOMEM;
+
if (isuserbuffer) {
- if (copy_from_user(policy_buffer, buf, buf_size)) {
+ if (copy_from_user(policy_buffer, buf, buf_size))
+ {
printk("%s: Error copying!\n",__func__);
goto error_free;
}
@@ -57,11 +59,13 @@ acm_set_policy(void *buf, u16 buf_size,
if ((ntohl(pol->magic) != ACM_MAGIC) ||
(ntohl(pol->policy_version) != ACM_POLICY_VERSION) ||
(ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
- (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) {
+ (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code))
+ {
printkd("%s: Wrong policy magics or versions!\n", __func__);
goto error_free;
}
- if (buf_size != ntohl(pol->len)) {
+ if (buf_size != ntohl(pol->len))
+ {
printk("%s: ERROR in buf size.\n", __func__);
goto error_free;
}
@@ -72,27 +76,25 @@ acm_set_policy(void *buf, u16 buf_size,
/* 3. set primary policy data */
if (acm_primary_ops->set_binary_policy(buf + ntohl(pol->primary_buffer_offset),
ntohl(pol->secondary_buffer_offset) -
- ntohl(pol->primary_buffer_offset))) {
+ ntohl(pol->primary_buffer_offset)))
goto error_lock_free;
- }
+
/* 4. set secondary policy data */
if (acm_secondary_ops->set_binary_policy(buf + ntohl(pol->secondary_buffer_offset),
ntohl(pol->len) -
- ntohl(pol->secondary_buffer_offset))) {
+ ntohl(pol->secondary_buffer_offset)))
goto error_lock_free;
- }
+
write_unlock(&acm_bin_pol_rwlock);
- if (policy_buffer != NULL)
- xfree(policy_buffer);
+ xfree(policy_buffer);
return ACM_OK;
error_lock_free:
write_unlock(&acm_bin_pol_rwlock);
error_free:
printk("%s: Error setting policy.\n", __func__);
- if (policy_buffer != NULL)
- xfree(policy_buffer);
- return -ENOMEM;
+ xfree(policy_buffer);
+ return -EFAULT;
}
int
@@ -102,11 +104,14 @@ acm_get_policy(void *buf, u16 buf_size)
int ret;
struct acm_policy_buffer *bin_pol;
+ if (buf_size < sizeof(struct acm_policy_buffer))
+ return -EFAULT;
+
if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL)
return -ENOMEM;
read_lock(&acm_bin_pol_rwlock);
- /* future: read policy from file and set it */
+
bin_pol = (struct acm_policy_buffer *)policy_buffer;
bin_pol->magic = htonl(ACM_MAGIC);
bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code);
@@ -118,27 +123,30 @@ acm_get_policy(void *buf, u16 buf_size)
ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohl(bin_pol->primary_buffer_offset),
buf_size - ntohl(bin_pol->primary_buffer_offset));
- if (ret < 0) {
- printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
- read_unlock(&acm_bin_pol_rwlock);
- return -1;
- }
+ if (ret < 0)
+ goto error_free_unlock;
+
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len));
ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohl(bin_pol->secondary_buffer_offset),
buf_size - ntohl(bin_pol->secondary_buffer_offset));
- if (ret < 0) {
- printk("%s: ERROR creating chwallpolicy buffer.\n", __func__);
- read_unlock(&acm_bin_pol_rwlock);
- return -1;
- }
+ if (ret < 0)
+ goto error_free_unlock;
+
bin_pol->len = htonl(ntohl(bin_pol->len) + ret);
- read_unlock(&acm_bin_pol_rwlock);
if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len)))
- return -EFAULT;
+ goto error_free_unlock;
+
+ read_unlock(&acm_bin_pol_rwlock);
xfree(policy_buffer);
return ACM_OK;
+
+ error_free_unlock:
+ read_unlock(&acm_bin_pol_rwlock);
+ printk("%s: Error getting policy.\n", __func__);
+ xfree(policy_buffer);
+ return -EFAULT;
}
int
@@ -185,4 +193,62 @@ acm_dump_statistics(void *buf, u16 buf_s
return -EFAULT;
}
+
+int
+acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size)
+{
+ /* send stats to user space */
+ u8 *ssid_buffer;
+ int ret;
+ struct acm_ssid_buffer *acm_ssid;
+ if (buf_size < sizeof(struct acm_ssid_buffer))
+ return -EFAULT;
+
+ if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL)
+ return -ENOMEM;
+
+ read_lock(&acm_bin_pol_rwlock);
+
+ acm_ssid = (struct acm_ssid_buffer *)ssid_buffer;
+ acm_ssid->len = sizeof(struct acm_ssid_buffer);
+ acm_ssid->ssidref = ssidref;
+ acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code;
+ acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code;
+ acm_ssid->primary_types_offset = acm_ssid->len;
+
+ /* ret >= 0 --> ret == max_types */
+ ret = acm_primary_ops->dump_ssid_types(ACM_PRIMARY(ssidref),
+ ssid_buffer + acm_ssid->primary_types_offset,
+ buf_size - acm_ssid->primary_types_offset);
+ if (ret < 0)
+ goto error_free_unlock;
+
+ acm_ssid->len += ret;
+ acm_ssid->primary_max_types = ret;
+
+ acm_ssid->secondary_types_offset = acm_ssid->len;
+
+ ret = acm_secondary_ops->dump_ssid_types(ACM_SECONDARY(ssidref),
+ ssid_buffer + acm_ssid->secondary_types_offset,
+ buf_size - acm_ssid->secondary_types_offset);
+ if (ret < 0)
+ goto error_free_unlock;
+
+ acm_ssid->len += ret;
+ acm_ssid->secondary_max_types = ret;
+
+ if (copy_to_user(buf, ssid_buffer, acm_ssid->len))
+ goto error_free_unlock;
+
+ read_unlock(&acm_bin_pol_rwlock);
+ xfree(ssid_buffer);
+ return ACM_OK;
+
+ error_free_unlock:
+ read_unlock(&acm_bin_pol_rwlock);
+ printk("%s: Error getting ssid.\n", __func__);
+ xfree(ssid_buffer);
+ return -ENOMEM;
+}
+
/*eof*/
Index: xen-unstable.hg-shype/xen/acm/acm_simple_type_enforcement_hooks.c
===================================================================
--- xen-unstable.hg-shype.orig/xen/acm/acm_simple_type_enforcement_hooks.c
+++ xen-unstable.hg-shype/xen/acm/acm_simple_type_enforcement_hooks.c
@@ -383,6 +383,27 @@ ste_dump_stats(u8 *buf, u16 buf_len)
return sizeof(struct acm_ste_stats_buffer);
}
+static int
+ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len)
+{
+ int i;
+
+ /* fill in buffer */
+ if (ste_bin_pol.max_types > len)
+ return -EFAULT;
+
+ if (ssidref >= ste_bin_pol.max_ssidrefs)
+ return -EFAULT;
+
+ /* read types for chwall ssidref */
+ for(i=0; i< ste_bin_pol.max_types; i++) {
+ if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i])
+ buf[i] = 1;
+ else
+ buf[i] = 0;
+ }
+ return ste_bin_pol.max_types;
+}
/* we need to go through this before calling the hooks,
* returns 1 == cache hit */
@@ -625,22 +646,23 @@ struct acm_operations acm_simple_type_en
/* policy management services */
.init_domain_ssid = ste_init_domain_ssid,
.free_domain_ssid = ste_free_domain_ssid,
- .dump_binary_policy = ste_dump_policy,
- .set_binary_policy = ste_set_policy,
+ .dump_binary_policy = ste_dump_policy,
+ .set_binary_policy = ste_set_policy,
.dump_statistics = ste_dump_stats,
+ .dump_ssid_types = ste_dump_ssid_types,
/* domain management control hooks */
.pre_domain_create = ste_pre_domain_create,
- .post_domain_create = NULL,
- .fail_domain_create = NULL,
- .post_domain_destroy = ste_post_domain_destroy,
+ .post_domain_create = NULL,
+ .fail_domain_create = NULL,
+ .post_domain_destroy = ste_post_domain_destroy,
/* event channel control hooks */
- .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
+ .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
.fail_eventchannel_unbound = NULL,
.pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
.fail_eventchannel_interdomain = NULL,
/* grant table control hooks */
- .pre_grant_map_ref = ste_pre_grant_map_ref,
- .fail_grant_map_ref = NULL,
- .pre_grant_setup = ste_pre_grant_setup,
- .fail_grant_setup = NULL,
+ .pre_grant_map_ref = ste_pre_grant_map_ref,
+ .fail_grant_map_ref = NULL,
+ .pre_grant_setup = ste_pre_grant_setup,
+ .fail_grant_setup = NULL,
};
Index: xen-unstable.hg-shype/xen/common/acm_ops.c
===================================================================
--- xen-unstable.hg-shype.orig/xen/common/acm_ops.c
+++ xen-unstable.hg-shype/xen/common/acm_ops.c
@@ -19,6 +19,7 @@
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/mm.h>
+#include <public/acm.h>
#include <public/acm_ops.h>
#include <xen/sched.h>
#include <xen/event.h>
@@ -41,7 +42,8 @@ typedef enum acm_operation {
POLICY, /* access to policy interface (early drop) */
GETPOLICY, /* dump policy cache */
SETPOLICY, /* set policy cache (controls security) */
- DUMPSTATS /* dump policy statistics */
+ DUMPSTATS, /* dump policy statistics */
+ GETSSID /* retrieve ssidref for domain id */
} acm_operation_t;
int acm_authorize_acm_ops(struct domain *d, acm_operation_t pops)
@@ -117,6 +119,35 @@ long do_acm_op(acm_op_t * u_acm_op)
}
break;
+ case ACM_GETSSID:
+ {
+ ssidref_t ssidref;
+
+ if (acm_authorize_acm_ops(current->domain, GETSSID))
+ return -EACCES;
+
+ if (op->u.getssid.get_ssid_by == SSIDREF)
+ ssidref = op->u.getssid.id.ssidref;
+ else if (op->u.getssid.get_ssid_by == DOMAINID) {
+ struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid);
+ if (!subj)
+ return -ESRCH; /* domain not found */
+
+ ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
+ put_domain(subj);
+ } else
+ return -ESRCH;
+
+ ret = acm_get_ssid(ssidref,
+ op->u.getssid.ssidbuf,
+ op->u.getssid.ssidbuf_size);
+ if (ret == ACM_OK)
+ ret = 0;
+ else
+ ret = -ESRCH;
+ }
+ break;
+
default:
ret = -ESRCH;
Index: xen-unstable.hg-shype/xen/include/acm/acm_core.h
===================================================================
--- xen-unstable.hg-shype.orig/xen/include/acm/acm_core.h
+++ xen-unstable.hg-shype/xen/include/acm/acm_core.h
@@ -101,9 +101,15 @@ struct ste_ssid {
* primary ssidref = lower 16 bit
* secondary ssidref = higher 16 bit
*/
+#define ACM_PRIMARY(ssidref) \
+ ((ssidref) & 0xffff)
+
+#define ACM_SECONDARY(ssidref) \
+ ((ssidref) >> 16)
+
#define GET_SSIDREF(POLICY, ssidref) \
((POLICY) == acm_bin_pol.primary_policy_code) ? \
- ((ssidref) & 0xffff) : ((ssidref) >> 16)
+ ACM_PRIMARY(ssidref) : ACM_SECONDARY(ssidref)
/* macros to access ssid pointer for primary / secondary policy */
#define GET_SSIDP(POLICY, ssid) \
@@ -116,6 +122,7 @@ int acm_free_domain_ssid(struct acm_ssid
int acm_set_policy(void *buf, u16 buf_size, int isuserbuffer);
int acm_get_policy(void *buf, u16 buf_size);
int acm_dump_statistics(void *buf, u16 buf_size);
+int acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size);
#endif
Index: xen-unstable.hg-shype/xen/include/acm/acm_hooks.h
===================================================================
--- xen-unstable.hg-shype.orig/xen/include/acm/acm_hooks.h
+++ xen-unstable.hg-shype/xen/include/acm/acm_hooks.h
@@ -92,6 +92,7 @@ struct acm_operations {
int (*dump_binary_policy) (u8 *buffer, u16 buf_size);
int (*set_binary_policy) (u8 *buffer, u16 buf_size);
int (*dump_statistics) (u8 *buffer, u16 buf_size);
+ int (*dump_ssid_types) (ssidref_t ssidref, u8 *buffer, u16 buf_size);
/* domain management control hooks (can be NULL) */
int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref);
void (*post_domain_create) (domid_t domid, ssidref_t ssidref);
Index: xen-unstable.hg-shype/xen/include/public/acm.h
===================================================================
--- xen-unstable.hg-shype.orig/xen/include/public/acm.h
+++ xen-unstable.hg-shype/xen/include/public/acm.h
@@ -56,20 +56,22 @@
#define ACM_ACCESS_DENIED -111
#define ACM_NULL_POINTER_ERROR -200
-#define ACM_MAX_POLICY 3
-
+/* primary policy in lower 4 bits */
#define ACM_NULL_POLICY 0
#define ACM_CHINESE_WALL_POLICY 1
#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
-#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3
+
+/* combinations have secondary policy component in higher 4bit */
+#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \
+ ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY)
/* policy: */
#define ACM_POLICY_NAME(X) \
- (X == ACM_NULL_POLICY) ? "NULL policy" : \
- (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \
- (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT policy" : \
- (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
- "UNDEFINED policy"
+ ((X) == (ACM_NULL_POLICY)) ? "NULL policy" : \
+ ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL policy" : \
+ ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT policy" : \
+ ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \
+ "UNDEFINED policy"
/* the following policy versions must be increased
* whenever the interpretation of the related
@@ -122,7 +124,7 @@ typedef u16 domaintype_t;
*/
struct acm_policy_buffer {
u32 policy_version; /* ACM_POLICY_VERSION */
- u32 magic;
+ u32 magic;
u32 len;
u32 primary_policy_code;
u32 primary_buffer_offset;
@@ -151,7 +153,7 @@ struct acm_ste_policy_buffer {
};
struct acm_stats_buffer {
- u32 magic;
+ u32 magic;
u32 len;
u32 primary_policy_code;
u32 primary_stats_offset;
@@ -168,5 +170,15 @@ struct acm_ste_stats_buffer {
u32 gt_cachehit_count;
};
+struct acm_ssid_buffer {
+ u32 len;
+ ssidref_t ssidref;
+ u32 primary_policy_code;
+ u32 primary_max_types;
+ u32 primary_types_offset;
+ u32 secondary_policy_code;
+ u32 secondary_max_types;
+ u32 secondary_types_offset;
+};
#endif
Index: xen-unstable.hg-shype/xen/include/public/acm_ops.h
===================================================================
--- xen-unstable.hg-shype.orig/xen/include/public/acm_ops.h
+++ xen-unstable.hg-shype/xen/include/public/acm_ops.h
@@ -1,3 +1,4 @@
+
/******************************************************************************
* acm_ops.h
*
@@ -27,7 +28,7 @@
* This makes sure that old versions of acm tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define ACM_INTERFACE_VERSION 0xAAAA0003
+#define ACM_INTERFACE_VERSION 0xAAAA0004
/************************************************************************/
@@ -46,6 +47,7 @@ typedef struct acm_getpolicy {
u16 pullcache_size;
} acm_getpolicy_t;
+
#define ACM_DUMPSTATS 6
typedef struct acm_dumpstats {
void *pullcache;
@@ -53,6 +55,18 @@ typedef struct acm_dumpstats {
} acm_dumpstats_t;
+#define ACM_GETSSID 7
+enum get_type {UNSET, SSIDREF, DOMAINID};
+typedef struct acm_getssid {
+ enum get_type get_ssid_by;
+ union {
+ domaintype_t domainid;
+ ssidref_t ssidref;
+ } id;
+ void *ssidbuf;
+ u16 ssidbuf_size;
+} acm_getssid_t;
+
typedef struct acm_op {
u32 cmd;
u32 interface_version; /* ACM_INTERFACE_VERSION */
@@ -60,6 +74,7 @@ typedef struct acm_op {
acm_setpolicy_t setpolicy;
acm_getpolicy_t getpolicy;
acm_dumpstats_t dumpstats;
+ acm_getssid_t getssid;
} u;
} acm_op_t;
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Xense-devel] [PATCH] ACM: adding get_ssid command and cleanup
2005-09-02 3:26 [PATCH] ACM: adding get_ssid command and cleanup Reiner Sailer
@ 2005-09-02 18:41 ` David Palmer
2005-09-03 2:53 ` Reiner Sailer
0 siblings, 1 reply; 5+ messages in thread
From: David Palmer @ 2005-09-02 18:41 UTC (permalink / raw)
To: Reiner Sailer; +Cc: xen-devel, Stefan Berger, xense-devel
[-- Attachment #1.1: Type: text/plain, Size: 2094 bytes --]
Reiner,
I've looked over the code. As input, it takes either an SSID or a DomainID.
If given a DomainID, it looks up the domain's SSID. It then returns two
arrays of 0's and 1's. One array is a row from the STE-Type matrix and the
other is a row from the ChWall-Type matrix corresponding to the given SSID.
My question then: What constitutes a legitimate use vs. a clear abuse of
this information?
For example, lets say I create a domain that manages a resource. When
another domain connects, the resource domain checks for a specific type
using get_ssid() on the subject's DomainID and indexes one of the arrays
with the type number. If the type is set, then it provides the "Privileged"
interface with the other domain. If it is not set, then it provides the
"Unprivileged" interface with the domain. Is this legitimate or an abuse of
the function? Why or why not?
Dave
On 9/1/05, Reiner Sailer <sailer@us.ibm.com> wrote:
>
>
> This patch:
>
> * adds a get_ssid ACM command that allows privileged domains to retrieve
> types for either a given ssid reference or a given domain id (of a running
> domain); this command can be used to extend access control into device
> domains, e.g., to control network traffic currently moving through Domain
> 0 uncontrolled by the ACM policy
>
> * adds a script getlabel.sh that allows users inside Dom0 to retrieve the
> label for a given ssid reference or a given domain id (multiple labels might
> map onto a single ssid reference)
>
> * cleans up label-related code in tools/security by merging common
> functions into labelfuncs.sh
>
> * cleans up ACM code related to above changes (eventually approximating a
> common coding style)
>
> Comments welcome.
>
> Thanks
> Reiner
>
> Signed-off-by Reiner Sailer <sailer@us.ibm.com>
> Signed-off by Stefan Berger <stefanb@us.ibm.com>
>
>
>
> _______________________________________________
> Xense-devel mailing list
> Xense-devel@lists.xensource.com
> http://lists.xensource.com/xense-devel
>
>
>
>
[-- Attachment #1.2: Type: text/html, Size: 3275 bytes --]
[-- Attachment #2: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Xense-devel] [PATCH] ACM: adding get_ssid command and cleanup
2005-09-02 18:41 ` [Xense-devel] " David Palmer
@ 2005-09-03 2:53 ` Reiner Sailer
2005-09-03 16:49 ` David Palmer
0 siblings, 1 reply; 5+ messages in thread
From: Reiner Sailer @ 2005-09-03 2:53 UTC (permalink / raw)
To: David Palmer; +Cc: xen-devel, Stefan Berger, xense-devel
[-- Attachment #1.1: Type: text/plain, Size: 6129 bytes --]
David Palmer <dwpalmer.xense@gmail.com> wrote on 09/02/2005 02:41:28 PM:
> Reiner,
>
> I've looked over the code. As input, it takes either an SSID or a
> DomainID. If given a DomainID, it looks up the domain's SSID. It
> then returns two arrays of 0's and 1's. One array is a row from the
> STE-Type matrix and the other is a row from the ChWall-Type matrix
> corresponding to the given SSID.
More information explaining legitimate and envisioned use of this
function:
The get_ssid (get subject security identifier) command was mainly
introduced to allow device domains to retrieve the security related
information they need from the hypervisor. This way, they can enforce
access control on the virtual resources they are offering to other
domains. To do this, a device domain only needs to know those types of a
remote domain that it shares with this domain. In the future, we will
restrict domains other than the security management domain (currently
dom0) to those types.
We use get_ssid based on the domainID in device domains that need to know
the types of their peer domains requiring access (e.g., requesting to
mount a logical partition). This usually involves code "behind" backend
interfaces in Xen.
We plan to use get_ssid based on the ssidref for resources (once resource
labeling is introduced) to control the allocation of physical resources
(e.g. peripherals) to domains according to the types of the domain to
which a peripheral is being assigned and the types of the peripheral (only
domains that share a type with the peripheral can own it).
> My question then: What constitutes a legitimate use vs. a clear
> abuse of this information?
> For example, lets say I create a domain that manages a resource.
> When another domain connects, the resource domain checks for a
> specific type using get_ssid() on the subject's DomainID and indexes
> one of the arrays with the type number. If the type is set, then it
> provides the "Privileged" interface with the other domain.
Some background for the legitimate use of this function:
The access control decision of a device domain is yes/no to a request of a
remote domain to access a resource (e.g., connect a front-end virtual
block device driver in a user domain to a back-end virtual block device
driver in a device domain). It is not based on any specific operation but
only on the security types of the domains. The "privileged" part comes in
when a domain tries to use get_ssid on the hypervisor.
Your question seems to go towards operation granularity for access control
decisions, which is not what the current policies envision. We leave this
granularity to upper layers (inside domains) in Xen. I could re-formulate
your latter sentence: "If the type is set, then it allows access (any
access), otherwise it denies access to the resource." Denying access in
this context means, e.g., that connecting a front-end block device driver
to the respective back-end block device driver fails and a domain will not
be able to mount a drive (or access the network in case of network
front/back ends).
The hypervisor with the help of device domains does NOT control the
operation ("mount disk" or "send network traffic") but controls general
access of domains to virtual resources (access to the storage domain's
virtual disks, access to the network domains virtual network interfaces).
In this context, the hypervisor controls if a domain can communicate at
all to a device domain, the device domain then controls if a domain can
access a certain virtual resource.
>Is this legitimate or an abuse of the function? Why or why not?
Using get_ssid is restricted to privileged domains. If the privileged
domain is a device domain, then it MUST enforce the hypervisor policy
(here Type Enforcement). To further restrict access in higher layers is
legitimate and envisioned in device domains. Offering other domains even
an unprivileged interface if they don't share a type is a violation of the
hypervisor STE policy; this is illegal in device domains. Using get_ssid
in any other privileged domain in the way you describe could / should be
considered abuse since:
a) the policy information is not used as intended and inconsistencies are
likely to evolve
b) predicting the effect of policy settings onto the enforcement becomes
increasingly difficult (even the simple STE policy now can define quite
complex relationships)
Resolution:
i) The privileged/unprivileged access control interface could be
implemented based on a separate policy/enforcement layer above and
independent of the hypervisor (inside the privileged domain).
ii) A different hypervisor security policy could be implemented that does
not conflict with your privileged/unprivileged interface interpretation.
At this point your example use of get_ssid becomes legitimate since it is
consistent with the interpretation of the hypervisor policy.
I hope this is helful.
Thanks
Reiner
> On 9/1/05, Reiner Sailer <sailer@us.ibm.com> wrote:
>
> This patch:
>
> * adds a get_ssid ACM command that allows privileged domains to
> retrieve types for either a given ssid reference or a given domain
> id (of a running domain); this command can be used to extend access
> control into device domains, e.g., to control network traffic
> currently moving through Domain 0 uncontrolled by the ACM policy
>
> * adds a script getlabel.sh that allows users inside Dom0 to
> retrieve the label for a given ssid reference or a given domain id
> (multiple labels might map onto a single ssid reference)
>
> * cleans up label-related code in tools/security by merging common
> functions into labelfuncs.sh
>
> * cleans up ACM code related to above changes (eventually
> approximating a common coding style)
>
> Comments welcome.
>
> Thanks
> Reiner
>
> Signed-off-by Reiner Sailer <sailer@us.ibm.com>
> Signed-off by Stefan Berger <stefanb@us.ibm.com>
>
>
>
> _______________________________________________
> Xense-devel mailing list
> Xense-devel@lists.xensource.com
> http://lists.xensource.com/xense-devel
>
>
[-- Attachment #1.2: Type: text/html, Size: 7345 bytes --]
[-- Attachment #2: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Xense-devel] [PATCH] ACM: adding get_ssid command and cleanup
2005-09-03 2:53 ` Reiner Sailer
@ 2005-09-03 16:49 ` David Palmer
2005-09-03 20:16 ` Reiner Sailer
0 siblings, 1 reply; 5+ messages in thread
From: David Palmer @ 2005-09-03 16:49 UTC (permalink / raw)
To: Reiner Sailer; +Cc: xen-devel, Stefan Berger, xense-devel
[-- Attachment #1.1: Type: text/plain, Size: 10186 bytes --]
Yes, that helps considerably. I had the mistaken impression that you were
implementing the Flask architecture. From the papers I've read, it calls for
object managers and a security server. Each object manager is only concerned
with object specific knowledge for policy enforcement. Object managers rely
on a central security server to make policy decisions. The security server
has the sole responsibility of interpreting the policy. This is clearly not
the architecture you envision for sHype.
Instead, what I hear you saying sounds like a collection of resource
reference monitors that follow a global policy that applies to all reference
monitors.
1. Each reference monitor makes policy decisions and enforces them for its
resources.
2. A central policy server is used to provide the relevant portions of the
global policy to the reference monitors.
3. Each reference monitor faithfully interprets the global policy according
to the common policy semantics.
4. Each reference monitor enforces the global policy in that it does not
allow any more access than what is permitted by the policy semantics. It may
choose to grant less access as long as it does not change the meaning of the
global policy.
For example, lets consider the case where I have a domain that provides both
a "privileged" and "unprivileged" interface to its resources. The global
policy allows a red and a black domain to each connect to the resource
domain. The resource domain may choose to provide different levels of access
to red and black. It should not interpret the global policy differently, but
instead it can honor a local policy that names the red and black domains.
Have you published a paper detailing this architecture and how it compares
with other architectures? It would be interesting to go over it in detail
and see what you have learned about the approach.
In your messages, you note that it is important that the global policy has a
consistent meaning for all reference monitors, and that the architecture
supports the ability to change the meaning of the policy in the future.
1. Doesn't optimizing the policy decision logic for each resource monitor
increase the risk that there will be differences in how each of them
interprets the global policy?
Although we all try to write perfect code, we certainly have to accept that
it doesn't generally happen. There is an advantage to having a single golden
implementation where defects can be fixed such that all resource managers
benefit. Independent optimizations for the policy decision logic in each
resource monitor increases the chances for defects that have to be fix
independently. Unfortunately, testing tends not to work well for eliminating
security vulnerabilities as it only finds the few that were tested for.
2. How can semantic changes in the global policy be made?
If each resource monitor is responsible for interpreting the policy
consistently with each other, aren't they locked into the specific semantics
of the policy they understand? In the worse case, won't this lead to needing
to rewrite each reference monitor in order to add or alter the policy
semantics?
I'm concerned that if I start implementing my own reference monitor with the
given get_ssid() function, I'll end up having to rewrite it completely as it
won't be consistent with the solution you have in mind for addressing the
goals of providing consistent policy semantics and allowing them to be
changed in the future.
Dave
On 9/2/05, Reiner Sailer <sailer@us.ibm.com> wrote:
>
>
> David Palmer <dwpalmer.xense@gmail.com> wrote on 09/02/2005 02:41:28 PM:
>
> > Reiner,
> >
> > I've looked over the code. As input, it takes either an SSID or a
> > DomainID. If given a DomainID, it looks up the domain's SSID. It
> > then returns two arrays of 0's and 1's. One array is a row from the
> > STE-Type matrix and the other is a row from the ChWall-Type matrix
> > corresponding to the given SSID.
>
> More information explaining legitimate and envisioned use of this
> function:
> The get_ssid (get subject security identifier) command was mainly
> introduced to allow device domains to retrieve the security related
> information they need from the hypervisor. This way, they can enforce access
> control on the virtual resources they are offering to other domains. To do
> this, a device domain only needs to know those types of a remote domain that
> it shares with this domain. In the future, we will restrict domains other
> than the security management domain (currently dom0) to those types.
>
> We use get_ssid based on the domainID in device domains that need to know
> the types of their peer domains requiring access (e.g., requesting to
> mount a logical partition). This usually involves code "behind" backend
> interfaces in Xen.
>
> We plan to use get_ssid based on the ssidref for resources (once resource
> labeling is introduced) to control the allocation of physical resources (
> e.g. peripherals) to domains according to the types of the domain to which
> a peripheral is being assigned and the types of the peripheral (only domains
> that share a type with the peripheral can own it).
>
> > My question then: What constitutes a legitimate use vs. a clear
> > abuse of this information?
> > For example, lets say I create a domain that manages a resource.
> > When another domain connects, the resource domain checks for a
> > specific type using get_ssid() on the subject's DomainID and indexes
> > one of the arrays with the type number. If the type is set, then it
> > provides the "Privileged" interface with the other domain.
>
> Some background for the legitimate use of this function:
> The access control decision of a device domain is yes/no to a request of a
> remote domain to access a resource (e.g., connect a front-end virtual
> block device driver in a user domain to a back-end virtual block device
> driver in a device domain). It is not based on any specific operation but
> only on the security types of the domains. The "privileged" part comes in
> when a domain tries to use get_ssid on the hypervisor.
>
> Your question seems to go towards operation granularity for access control
> decisions, which is not what the current policies envision. We leave this
> granularity to upper layers (inside domains) in Xen. I could re-formulate
> your latter sentence: "If the type is set, then it allows access (any
> access), otherwise it denies access to the resource." Denying access in this
> context means, e.g., that connecting a front-end block device driver to
> the respective back-end block device driver fails and a domain will not be
> able to mount a drive (or access the network in case of network front/back
> ends).
>
> The hypervisor with the help of device domains does NOT control the
> operation ("mount disk" or "send network traffic") but controls general
> access of domains to virtual resources (access to the storage domain's
> virtual disks, access to the network domains virtual network interfaces). In
> this context, the hypervisor controls if a domain can communicate at all to
> a device domain, the device domain then controls if a domain can access a
> certain virtual resource.
>
> >Is this legitimate or an abuse of the function? Why or why not?
>
> Using get_ssid is restricted to privileged domains. If the privileged
> domain is a device domain, then it MUST enforce the hypervisor policy (here
> Type Enforcement). To further restrict access in higher layers is legitimate
> and envisioned in device domains. Offering other domains even an
> unprivileged interface if they don't share a type is a violation of the
> hypervisor STE policy; this is illegal in device domains. Using get_ssid in
> any other privileged domain in the way you describe could / should be
> considered abuse since:
>
> a) the policy information is not used as intended and inconsistencies are
> likely to evolve
> b) predicting the effect of policy settings onto the enforcement becomes
> increasingly difficult (even the simple STE policy now can define quite
> complex relationships)
>
> Resolution:
> i) The privileged/unprivileged access control interface could be
> implemented based on a separate policy/enforcement layer above and
> independent of the hypervisor (inside the privileged domain).
>
> ii) A different hypervisor security policy could be implemented that does
> not conflict with your privileged/unprivileged interface interpretation. At
> this point your example use of get_ssid becomes legitimate since it is
> consistent with the interpretation of the hypervisor policy.
>
> I hope this is helful.
>
> Thanks
>
> Reiner
>
> > On 9/1/05, Reiner Sailer <sailer@us.ibm.com> wrote:
> >
> > This patch:
> >
> > * adds a get_ssid ACM command that allows privileged domains to
> > retrieve types for either a given ssid reference or a given domain
> > id (of a running domain); this command can be used to extend access
> > control into device domains, e.g., to control network traffic
> > currently moving through Domain 0 uncontrolled by the ACM policy
> >
> > * adds a script getlabel.sh that allows users inside Dom0 to
> > retrieve the label for a given ssid reference or a given domain id
> > (multiple labels might map onto a single ssid reference)
> >
> > * cleans up label-related code in tools/security by merging common
> > functions into labelfuncs.sh
> >
> > * cleans up ACM code related to above changes (eventually
> > approximating a common coding style)
> >
> > Comments welcome.
> >
> > Thanks
> > Reiner
> >
> > Signed-off-by Reiner Sailer <sailer@us.ibm.com>
> > Signed-off by Stefan Berger <stefanb@us.ibm.com>
> >
> >
> >
> > _______________________________________________
> > Xense-devel mailing list
> > Xense-devel@lists.xensource.com
> > http://lists.xensource.com/xense-devel
> >
> >
>
[-- Attachment #1.2: Type: text/html, Size: 12506 bytes --]
[-- Attachment #2: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Xense-devel] [PATCH] ACM: adding get_ssid command and cleanup
2005-09-03 16:49 ` David Palmer
@ 2005-09-03 20:16 ` Reiner Sailer
0 siblings, 0 replies; 5+ messages in thread
From: Reiner Sailer @ 2005-09-03 20:16 UTC (permalink / raw)
To: dwpalmer.xense; +Cc: xen-devel, Stefan Berger, xense-devel
[-- Attachment #1.1: Type: text/plain, Size: 7181 bytes --]
David Palmer <dwpalmer.xense@gmail.com> wrote on 09/03/2005 12:49:01 PM:
> Yes, that helps considerably. I had the mistaken impression that
> you were implementing the Flask architecture. From the papers I've
> read, it calls for object managers and a security server. Each
> object manager is only concerned with object specific knowledge for
> policy enforcement. Object managers rely on a central security
> server to make policy decisions. The security server has the sole
> responsibility of interpreting the policy. This is clearly not the
> architecture you envision for sHype.
You are right. On one hand, are applying a flask-like architecture inside
the hypervisor where we have "hooks" around operations on eventchannels
and grant-tables. These hooks actually do not know about policies but call
into the ACM (security server).
On the other hand, since some objects are located outside the hypervisor
(virtual resources based on peripherals), we need to modularly extend this
basic access control to allow certain trusted domains (device domains).
Such domains are part of the access control infrastructure; they are not
user domains.
> Instead, what I hear you saying sounds like a collection of resource
> reference monitors that follow a global policy that applies to all
> reference monitors.
yes.
> 1. Each reference monitor makes policy decisions and enforces them
> for its resources.
>
> 2. A central policy server is used to provide the relevant portions
> of the global policy to the reference monitors.
>
> 3. Each reference monitor faithfully interprets the global policy
> according to the common policy semantics.
>
> 4. Each reference monitor enforces the global policy in that it does
> not allow any more access than what is permitted by the policy
> semantics. It may choose to grant less access as long as it does
> not change the meaning of the global policy.
yes.
> For example, lets consider the case where I have a domain that
> provides both a "privileged" and "unprivileged" interface to its
> resources. The global policy allows a red and a black domain to
> each connect to the resource domain. The resource domain may choose
> to provide different levels of access to red and black. It should
> not interpret the global policy differently, but instead it can
> honor a local policy that names the red and black domains.
>
> Have you published a paper detailing this architecture and how it
> compares with other architectures? It would be interesting to go
> over it in detail and see what you have learned about the approach.
Will be on ACSAC 2005 (December, Tuscon) We are working on it ;_)
> In your messages, you note that it is important that the global
> policy has a consistent meaning for all reference monitors, and that
> the architecture supports the ability to change the meaning of the
> policy in the future.
>
> 1. Doesn't optimizing the policy decision logic for each resource
> monitor increase the risk that there will be differences in how each
> of them interprets the global policy?
The current policies are simple so it should be possible to get this right
(eventually). The more difficult part is to ensure that the device domains
are small and tight enough to keep access to resources of different types
safely apart (MAC confinement). Minimal Linx + enforcment (e.g. SELinux),
micro-kernels, ... might be interesting experiment candidates and we
encourage experiments.
> Although we all try to write perfect code, we certainly have to
> accept that it doesn't generally happen. There is an advantage to
> having a single golden implementation where defects can be fixed
> such that all resource managers benefit. Independent optimizations
> for the policy decision logic in each resource monitor increases the
> chances for defects that have to be fix independently.
> Unfortunately, testing tends not to work well for eliminating
> security vulnerabilities as it only finds the few that were tested for.
This is one correct side of arguments. The other is that modularity has
advantages too. We try to minimize the code intrusiveness by controlling
access at the natural points where we have direct control on access and
all necessary information to derive the access decision. Both alternative
ways should be explored.
> 2. How can semantic changes in the global policy be made?
>
> If each resource monitor is responsible for interpreting the policy
> consistently with each other, aren't they locked into the specific
> semantics of the policy they understand? In the worse case, won't
> this lead to needing to rewrite each reference monitor in order to
> add or alter the policy semantics?
>
> I'm concerned that if I start implementing my own reference monitor
> with the given get_ssid() function, I'll end up having to rewrite it
> completely as it won't be consistent with the solution you have in
> mind for addressing the goals of providing consistent policy
> semantics and allowing them to be changed in the future.
>
> Dave
All reference monitors (hypervisor + device domains of multiple types) are
part of the policy enforcement; from an access control viewpoint, they are
more part of the hypervisor than they are a real domain. If you change the
policy, then you need to do this in all the elements. No different from
any other reference monitor implementation. Of course, the enforcement for
device domains should ideally be a pretty small patch to the driver code
leveraging existing OS controls (e.g., SELinux) to take over the
confinement/isolation part inside the domain.
The hypervisor-level access control is supposed to be simple but strong
(small TCB). It is not one of our current goals to optimize for changes in
the semantics of a policy since this is best done by defining a new policy
and implementing respective code. The coarse granularity of control rather
suggests that the policy should be a smallest common denominator and a
strong safety-net.
There is certainly room for choices while we are moving into device
domains and it can be pretty interesting to experiment with different
approaches for this integration.
I believe that your original suggestion is a good one and that we should
think about introducing an additional ACM call that allows to retrieve a
policy decision for the current policy based on two ssidrefs or one
ssidref and a domain id (whatever is available in the device domain) to
ensure that such experiments can apply to the full range of possible
enforcement options in device domains and to arrive at the best
architecture and not some local maxima.
We have so far used the following criteria when evaluating hypervisor
security architecture alternatives:
a) performance (without this it cannot survive in commercial environments;
see history)
b) minimize code-intrusiveness (without this, the security architecture
code will be subject to endless changes when other hypervisor code is
optimized and maintained or we end up re-writing the hypervisor; see
history)
c) simplicity (minimal TCB but considering a) and b))
Regards
Reiner
[-- Attachment #1.2: Type: text/html, Size: 8751 bytes --]
[-- Attachment #2: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2005-09-03 20:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-02 3:26 [PATCH] ACM: adding get_ssid command and cleanup Reiner Sailer
2005-09-02 18:41 ` [Xense-devel] " David Palmer
2005-09-03 2:53 ` Reiner Sailer
2005-09-03 16:49 ` David Palmer
2005-09-03 20:16 ` Reiner Sailer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.